Optimizing JSON:API Response Size for Headless Frontendsfor Drupal 11 , 10 , 9 , and 8

Last updated :  

A headless Drupal site can have a beautifully optimized backend and still feel sluggish — if the JSON:API response for a single page is 200KB of fields nobody asked for, the frontend is stuck waiting on bytes it will never render. This lesson is about trimming exactly what goes over the wire to your React, Vue, or Next.js frontend, without touching a single line of frontend code.

What you'll learn in this lesson

  • How to request only the fields a page actually needs with JSON:API's fields parameter
  • How to avoid the "N+1 request" trap using include instead of separate follow-up calls
  • How pagination keeps large collections from becoming one giant response
  • Why response compression is a one-line win most sites forget to enable

Limiting fields with the fields parameter

By default, JSON:API returns every field on an entity — including ones your frontend never renders. The fields query parameter narrows that down explicitly:

/jsonapi/node/article?fields[node--article]=title,body,field_tags

The bracket syntax fields[TYPE] targets one resource type at a time — request a related type's fields the same way (e.g. fields[taxonomy_term--tags]=name) if you're also including it. Leave this off entirely during early development if you like, but treat it as mandatory before shipping: on a content type with 20+ fields, this alone can cut response size by more than half.

Avoiding the N+1 problem with include

A classic headless mistake: fetch a list of articles, then loop over them on the frontend making a separate request per article to get its author. That's N+1 requests for N articles — exactly the kind of request-count explosion this whole topic is about avoiding.

/jsonapi/node/article?include=uid,field_tags&fields[node--article]=title,uid,field_tags

One request, with the author and tags embedded directly in the response's included array. Combine include with fields on the included types too, or you've just traded "many requests" for "one enormous one."

Paginating large collections

Fetching every node of a type in one response doesn't scale past a few dozen items. JSON:API's page[limit] and page[offset] parameters cap how much comes back per request:

/jsonapi/node/article?page[limit]=20&page[offset]=0

The response's links object includes a ready-made next URL, so your frontend doesn't need to compute offsets by hand — just follow the link JSON:API already gives you.

Don't forget response compression: none of the above matters much if your web server isn't gzipping (or better, brotli-compressing) the response body in the first place. Confirm Content-Encoding: gzip is actually present in your API responses — it's usually a one-line web server config change, and typically shrinks JSON payloads by 70-80% on top of everything else in this lesson.

Quick check: your frontend needs a list of articles with each author's name shown inline. Which is the better request — fetching articles, then a separate request per author, or one request using include=uid? (If you said the single include request, you've got it — that's exactly the N+1 problem this lesson exists to prevent, and it only gets worse as your article list grows.)

Key takeaways

  • Use fields[type]=... to request only the fields your frontend actually renders — the single highest-impact change for large content types.
  • Use include to embed related entities in one response instead of making a follow-up request per item — avoids the N+1 request pattern.
  • page[limit]/page[offset] keep large collections from arriving as one oversized response, and JSON:API's own links.next hands you the next page URL for free.
  • Confirm gzip/brotli compression is actually enabled at the web server level — it's the easiest win in this whole lesson and easy to overlook.

Coming up next

Trimming what goes into a response is one lever. The next lesson covers the other one: making sure a response that hasn't changed doesn't need to be rebuilt at all, using cache tags on your API endpoints.