> ## Documentation Index
> Fetch the complete documentation index at: https://cosmo-docs.wundergraph.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Defer

> Deliver the slow parts of a query response incrementally with the @defer directive.

<Info>
  Available since Router [0.328.0](https://github.com/wundergraph/cosmo/releases/tag/router%400.328.0).
</Info>

## What @defer does

When resolving a regular GraphQL response, a GraphQL server waits for every field to resolve.
The response latency equals the resolve time of the slowest field.
This can be a problem for large queries with many fields.

One solution splits the query into smaller queries.
The client then maintains two queries and makes two HTTP calls.

With the `@defer` directive, a client marks fragments for later delivery.
The router sends fields outside active `@defer` fragments in the initial response.
The router sends deferred fields in later parts of the same multipart HTTP response.

The client renders the initial data immediately.
The client adds each deferred fragment when it arrives.
The merged result is identical to the result of the same query without `@defer`.

```graphql theme={"system"}
query {
  employee(id: 1) {
    id
    details {
      forename
      location { language }
    }
    ... @defer {
      hobbies { __typename }
    }
  }
  teammates(team: OPERATIONS) {
    id
    details { forename }
    products
  }
}
```

This query spans three subgraphs:

* The `employees` subgraph returns `employee` and `teammates`.
* The `products` subgraph returns `products`.
* The `hobbies` subgraph returns `hobbies`.

Without `@defer`, the router waits for all three subgraphs before it sends the response.
With `@defer`, the client receives everything except `hobbies` in the initial response.
The client receives `hobbies` in an incremental response.

## Specification status

`@defer` is not yet part of a released GraphQL specification.
The router implements the [Incremental Delivery spec draft](https://github.com/graphql/graphql-spec/pull/1110).
The draft describes the response format as the `pending`, `incremental`, and `completed` format.

graphql-js `17.0.0-alpha.9` and Apollo Client 4.1 implement the same format.
Apollo Client implements it through its `GraphQL17Alpha9Handler`.
See [Using @defer](/router/defer/usage) for client setup.

## How to enable it

The router ignores `@defer` by default.
It treats deferred fragments as regular fragments and returns one JSON response.
To enable it, add the following to the router configuration:

```yaml config.yaml theme={"system"}
engine:
  enable_defer: true
```

The corresponding environment variable is `ENGINE_ENABLE_DEFER`.

## Send a request

A client opts into incremental delivery with the `Accept` header:

```http theme={"system"}
POST /graphql
Content-Type: application/json
Accept: multipart/mixed
```

The router accepts these forms:

* `multipart/mixed` without a format version.
* `multipart/mixed;incrementalSpec=v0.2`, the format version the router implements.
* The wildcards `multipart/*` and `*/*`.
* No `Accept` header.
  The router then treats the request as one that accepts every form.

The `Accept` header can allow none of these forms.
If the operation contains an active `@defer`, the router answers with status 200 and a GraphQL error:

```json theme={"system"}
{
  "errors": [
    {
      "message": "the router received a query with the @defer directive but the client does not accept multipart/mixed HTTP responses. To enable @defer support, add the HTTP header 'Accept: multipart/mixed'",
      "extensions": {
        "code": "DEFER_BAD_HEADER"
      }
    }
  ]
}
```

A client can ask for a different incremental delivery format, such as `multipart/mixed;deferSpec=20220824`.
Apollo Router uses that older format.
Such a client parses the response incorrectly and loses the deferred data.
The router rejects the request with status 200 and the error code `DEFER_UNSUPPORTED_SPEC`:

```json theme={"system"}
{
  "errors": [
    {
      "message": "the router received a query with the @defer directive but the client requested the incremental delivery format 'deferSpec=20220824', while the router implements 'incrementalSpec=v0.2'. Use a client that supports this format, for example Apollo Client with GraphQL17Alpha9Handler",
      "extensions": {
        "code": "DEFER_UNSUPPORTED_SPEC"
      }
    }
  ]
}
```

A named format takes priority over a wildcard.
The router rejects `Accept: multipart/mixed;deferSpec=20220824, */*`, because the client stated which format it can parse.

`@defer(if: false)` disables that directive.
If every `@defer` directive is inactive, the router executes the operation without incremental delivery.
The router returns one JSON response regardless of the `Accept` header.

## Response format

The router responds with these headers:

```http theme={"system"}
Content-Type: multipart/mixed; boundary="graphql"; incrementalSpec=v0.2
Transfer-Encoding: chunked
Cache-Control: no-cache
X-Accel-Buffering: no
```

The router sends `Transfer-Encoding: chunked` on HTTP/1.1 only.
HTTP/2 forbids the header and frames the stream itself.

Each part starts with the boundary `--graphql`, a `Content-Type: application/json` header, and an empty line.
One JSON payload follows.
The stream ends with the closing boundary `--graphql--`.
Line breaks inside the framing are `\r\n`.

Every part carries a plain GraphQL payload.
This differs from [multipart subscriptions](/router/subscriptions/multipart-http-requests).
There, each part wraps the result in a `payload` object.

The query above produces this response:

```text theme={"system"}
--graphql
Content-Type: application/json

{"data":{"employee":{"id":1,"details":{"forename":"Jens","location":{"language":"German"}}},"teammates":[{"id":4,"details":{"forename":"Björn"},"products":["FINANCE","HUMAN_RESOURCES","MARKETING"]},{"id":11,"details":{"forename":"Alexandra"},"products":["FINANCE"]}]},"pending":[{"id":"1","path":["employee"]}],"hasNext":true}

--graphql
Content-Type: application/json

{"incremental":[{"data":{"hobbies":[{"__typename":"Exercise"},{"__typename":"Gaming"},{"__typename":"Other"},{"__typename":"Programming"},{"__typename":"Travelling"}]},"id":"1"}],"completed":[{"id":"1"}],"hasNext":false}

--graphql--
```

## Payload fields

| Field         | Appears in                        | Meaning                                                                                                                        |
| ------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `data`        | initial response                  | All fields outside deferred fragments.                                                                                         |
| `errors`      | initial response                  | Errors of the non-deferred fields, as in a regular response.                                                                   |
| `extensions`  | initial response                  | Extensions, as in a regular response.                                                                                          |
| `pending`     | initial and incremental responses | Announces a deferred fragment. Each entry has an `id`, the `path` where the fragment applies, and an optional `label`.         |
| `incremental` | incremental response              | Delivered fragment data. Each entry has `data`, the `id` of its `pending` entry, an optional `subPath`, and optional `errors`. |
| `completed`   | incremental response              | Fragments that the router delivered in full in the current incremental response. Each entry has an `id` and optional `errors`. |
| `hasNext`     | every part                        | `true` while more parts follow, `false` on the last part.                                                                      |

A client merges an `incremental` entry into its result at the location `pending[id].path`, followed by `incremental.subPath`.
The router adds a `subPath` in two cases.
The fragment is inside a list, and the `subPath` carries the list index.
The delivered object is deeper than the path of the fragment, as in the [duplicated fields example](/router/defer/usage#fields-selected-both-inside-and-outside-defer).

The router announces a nested `@defer` in the `pending` list of the incremental response that delivers its parent fragment.

## Proxies and load balancers

Incremental delivery needs the client to receive each part as soon as the router writes it.
Every intermediary between the router and the client must pass each part through without buffering.
The router sets `X-Accel-Buffering: no`.
This header disables buffering in NGINX and in compatible proxies.
Check ingress controllers, CDNs, and compression settings separately.

## Next steps

<CardGroup cols={2}>
  <Card title="Using @defer" icon="code" href="/router/defer/usage">
    Query patterns, response walkthroughs, and client setup for curl, fetch, and Apollo Client.
  </Card>

  <Card title="How the Router Executes @defer" icon="diagram-project" href="/router/defer/how-it-works">
    What happens between receiving the query and sending the last part.
  </Card>

  <Card title="When to Use @defer" icon="scale-balanced" href="/router/defer/when-to-use">
    Choosing between @defer, separate queries, pagination, and subscriptions.
  </Card>

  <Card title="@defer directive reference" icon="forward-step" href="/federation/directives/defer">
    Definition, arguments, locations, and rules.
  </Card>
</CardGroup>
