# https://github.com/apollographql/apollo-client Project Manual

Generated at: 2026-07-10 05:52:40 UTC

## Table of Contents

- [Project Overview and Core Architecture](#page-1)
- [Caching System and InMemoryCache](#page-2)
- [React Integration, Hooks, and SSR](#page-3)
- [Network Links, Transport, Errors, and v3 to v4 Migration](#page-4)

<a id='page-1'></a>

## Project Overview and Core Architecture

### Related Pages

Related topics: [Caching System and InMemoryCache](#page-2), [React Integration, Hooks, and SSR](#page-3), [Network Links, Transport, Errors, and v3 to v4 Migration](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [README.md](https://github.com/apollographql/apollo-client/blob/main/README.md)
- [package.json](https://github.com/apollographql/apollo-client/blob/main/package.json)
- [src/core/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/index.ts)
- [src/core/ApolloClient.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/ApolloClient.ts)
- [src/core/QueryManager.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/QueryManager.ts)
- [src/core/ObservableQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/core/ObservableQuery.ts)
</details>

# Project Overview and Core Architecture

Apollo Client is the most widely used JavaScript/TypeScript GraphQL client, powering applications that fetch, cache, and manage local + remote GraphQL data. The repository distributes a cohesive set of packages under the `@apollo/client` umbrella, with a strong focus on React integration while remaining framework-agnostic at the core layer. Source: [README.md:1-40]().

The project is organized as a monorepo (`pnpm` workspaces). The root `package.json` declares the workspace locations and orchestrates versioning via Changesets; subpackages include `@apollo/client` (the umbrella), `@apollo/client/cache`, `@apollo/client/core`, `@apollo/client/react`, `@apollo/client/testing`, `@apollo/client-graphql-codegen`, and `@apollo/client/utilities`. Source: [package.json:1-80]().

## Purpose and Scope

Apollo Client's purpose is to give application developers a single, normalized place to interact with GraphQL data: send queries/mutations/subscriptions, cache results, and reactively push updates back into the UI. The framework ships:

- A normalized in-memory cache that merges and deduplicates results by `__typename` and identifier.
- Reactive `Observable`-based primitives that hooks and components subscribe to.
- A pluggable transport layer (HTTP, `multipart/mixed` subscriptions, WebSocket via `graphql-ws`, persisted queries).
- React bindings (`useQuery`, `useMutation`, `useSubscription`, `useFragment`, etc.) layered on top of the framework-agnostic core.

The community consistently raises architectural questions about cache disablement (#1419), `Missing field` write warnings for subscriptions (#8677), and SSR/Suspense behavior (#10231) — all of these are addressed by features implemented inside the `core/` and `cache/` directories described below. Source: [README.md:40-80]().

## Core Architecture Layers

The runtime architecture cleanly separates concerns into three layers.

| Layer | Responsibility | Key Files |
|-------|----------------|-----------|
| Public API (`@apollo/client`) | Re-exports the user-facing surface (`ApolloClient`, `ApolloProvider`, hooks, `gql`). | `src/index.ts` |
| Framework-agnostic core (`@apollo/client/core`) | `ApolloClient`, `QueryManager`, `ObservableQuery`, link pipeline, cache orchestration. | `src/core/ApolloClient.ts`, `src/core/QueryManager.ts`, `src/core/ObservableQuery.ts` |
| Cache + utilities | Normalized store, write/read/evict, scalar handling, policies. | `src/cache/inmemory/`, `src/utilities/` |

Source: [src/core/index.ts:1-60]().

The `ApolloClient` class is the user-facing entry point. It composes a `cache`, a `link` (transport + middleware chain), and exposes `query`, `mutate`, `subscribe`, `readQuery`, `readFragment`, `writeQuery`, and `watchFragment`. Internally, every public call delegates to a long-lived `QueryManager`, which keeps an internal `Map<string, QueryInfo>` indexed by observable (a deterministic hash of the operation document + variables). Source: [src/core/ApolloClient.ts:1-140]().

`QueryManager` is the orchestrator: it owns caches of in-flight `ObservableQuery` instances, deduplicates identical concurrent operations, executes `DocumentNode`s through the link chain, and routes results back into the cache via `cache.writeQuery`. When `optimisticResponse` is supplied on mutations, it issues optimistic writes that are later reconciled with the real server response. Source: [src/core/QueryManager.ts:1-180]().

`ObservableQuery` is the reactive primitive exposed to callers. It wraps the operation as a Zen-like observable (`subscribe(observer)`), tracks `loading`, `data`, `error`, `previousData`, and `variables` in a result object, and triggers `notifyOnNext` whenever a relevant cache change (or network update) occurs. Source: [src/core/ObservableQuery.ts:1-200]().

## Data Flow (Query Example)

A typical read path traverses the following sequence:

```mermaid
flowchart LR
    UI[React hook useQuery] --> OQ[ObservableQuery]
    OQ --> QM[QueryManager]
    QM --> Link[Apollo Link chain]
    Link --> Net[(GraphQL endpoint)]
    Net --> Link
    Link --> Cache[(Normalized InMemoryCache)]
    Cache --> OQ
    OQ --> UI
```

Source: [src/core/ApolloClient.ts:140-220](), [src/core/QueryManager.ts:180-260](), [src/core/ObservableQuery.ts:200-300]().

Each link in the chain may inspect, transform, or short-circuit the operation. After execution, the result passes through `cache.write` (which also performs merge-function evaluation for paginated fields, see issue #13304 about `hasDirectives(["stream"])` overhead in `StoreWriter.processSelectionSet`). The cache then broadcasts invalidation events to every watching observable, and `ObservableQuery` re-emits a new `ApolloQueryResult`.

## Key Architectural Invariants

1. **Cache identity**: `client.cache` may be configured as any implementation of `Cache.Implementation` (recent 4.3.0-alpha work extended generics here, see releases).
2. **`ApolloClient` is the only public mutation surface**: replacing the link or cache after construction is supported but discouraged; creation-time configuration is the norm.
3. **Subscriptions share the write path**: `client.subscribe` and `useSubscription` route writes through the same `cache.write` used by queries, which is why the "Missing field" patterns reported in #8677 surface here.
4. **Observable deduplication**: identical operation+variables pairs share the same `ObservableQuery` instance for as long as they remain active, avoiding duplicate network traffic.

Source: [src/core/ApolloClient.ts:220-320](), [src/core/QueryManager.ts:260-340](), [src/core/ObservableQuery.ts:300-380]().

Together, these layers form a small, composable system where the cache is the single source of truth, `ObservableQuery` is the reactive view, and `ApolloClient` is the ergonomic façade — the rest of the codebase (React bindings, testing utilities, dev tools) hangs off this trio.

---

<a id='page-2'></a>

## Caching System and InMemoryCache

### Related Pages

Related topics: [Project Overview and Core Architecture](#page-1), [React Integration, Hooks, and SSR](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/cache/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/index.ts)
- [src/cache/core/cache.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/core/cache.ts)
- [src/cache/core/types/Cache.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/core/types/Cache.ts)
- [src/cache/core/types/common.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/core/types/common.ts)
- [src/cache/inmemory/inMemoryCache.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/inMemoryCache.ts)
- [src/cache/inmemory/entityStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/entityStore.ts)
- [src/cache/inmemory/writeToStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/writeToStore.ts)
- [src/cache/inmemory/readFromStore.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/readFromStore.ts)
- [src/cache/inmemory/policies.ts](https://github.com/apollographql/apollo-client/blob/main/src/cache/inmemory/policies.ts)
</details>

# Caching System and InMemoryCache

The Apollo Client caching system is a pluggable, normalized graph data store that mediates between the network layer and UI components. Its primary responsibility is to read query/fragment results from a local store, write incoming server responses into that store, broadcast changes to subscribed watchers, and expose an `optimistic` mutation layer for in-flight updates. The default and most feature-rich implementation is `InMemoryCache`, but the package is designed around an abstract `Cache` interface so alternative stores (e.g., persisted or distributed) can be substituted. `Source: [src/cache/index.ts:1-40]()`

## Architecture Overview

The cache subsystem is split into two layers: a framework-agnostic `core` and an `inmemory` backend.

- `src/cache/core/cache.ts` defines the abstract `Cache` class. It declares the contract every implementation must satisfy: `read`, `write`, `diff`, `watch`, `evict`, `reset`, `restore`, `identify`, `gc`, `addOptimistic`, `removeOptimistic`, and `performTransaction`. `Source: [src/cache/core/cache.ts:1-120]()`
- `src/cache/core/types/Cache.ts` declares the public `Cache.Implementation` shape and the `WatchCallback` / `Broadcastable` helpers that observers rely on. `Source: [src/cache/core/types/Cache.ts:1-80]()`
- `src/cache/inmemory/inMemoryCache.ts` extends the abstract `Cache` and composes three collaborators: an `EntityStore`, a `StoreReader`, and a `StoreWriter`. `Source: [src/cache/inmemory/inMemoryCache.ts:1-160]()`

```mermaid
flowchart LR
    Client[ApolloClient] --> Cache[Cache<br/>abstract]
    Cache --> IMC[InMemoryCache]
    IMC --> ES[EntityStore]
    IMC --> SR[StoreReader]
    IMC --> SW[StoreWriter]
    IMC --> Pol[TypePolicies]
    ES -->|broadcast| W[Watchers]
```

The diagram illustrates how a query travels from `ApolloClient` down into the abstract `Cache`, is delegated to `InMemoryCache`, and then decomposed into reads (`StoreReader`), writes (`StoreWriter`), and state (`EntityStore`), with `TypePolicies` governing normalization rules.

## InMemoryCache and the Entity Store

`InMemoryCache` is a normalized store keyed by entity identifiers. Instead of storing raw query shapes, it splits every object into a separate entry keyed by `__typename:id`. Re-joining happens at read time via field policies. `Source: [src/cache/inmemory/inMemoryCache.ts:160-340]()`

Key behaviors:

- **Identity generation** — `cache.identify(object)` produces the canonical store key from a result object using `keyFields`/`keyFn` from the type policy. `Source: [src/cache/inmemory/entityStore.ts:1-90]()`
- **Reference handling** — when writing an object that contains another object reference, the inner object is stored as a `Reference` rather than duplicated, so updates to one query propagate to every place that points at the same entity. `Source: [src/cache/inmemory/entityStore.ts:90-220]()`
- **Optimistic layer** — `addOptimistic(expectationId, optimistic)` overlays a layer onto the store; reads merge optimistic data on top of canonical data, while `removeOptimistic` tears it down. `Source: [src/cache/inmemory/entityStore.ts:220-360]()`

The store exposes a `gc()` method that walks every known reference and removes unreachable entities to bound memory. `Source: [src/cache/inmemory/entityStore.ts:360-440]()`

## Reads, Writes, and Type Policies

`StoreReader` (`src/cache/inmemory/readFromStore.ts`) reconstructs a query-shaped result from the normalized store. It walks the selection set, replaces `Reference` placeholders with the referenced entities, and applies `read` field functions from the type policy. This is also where `merge` policies for paginated or custom-shaped fields execute during reads. `Source: [src/cache/inmemory/readFromStore.ts:1-160]()`

`StoreWriter` (`src/cache/inmemory/writeToStore.ts`) handles incoming `data` payloads. For each selection set it:

1. Resolves the entity identifier using the parent type's `keyFields`.
2. Calls `processSelectionSet` which recursively writes fields, honoring `merge` functions and field policies. The community-flagged performance issue in #13304 stems from this routine calling `hasDirectives(["stream"])` for every field lacking a merge function. `Source: [src/cache/inmemory/writeToStore.ts:1-200]()`

`TypePolicies` (configured via `cache.policies.addTypePolicies(...)`) supply four hooks per type/field: `keyFields`, `merge`, `read`, and `queryType`/`mutationType` definitions. `RelayFieldPolicy` and `KeyArgsFunction` are exported types for building these (added in `4.2.5`). `Source: [src/cache/inmemory/policies.ts:1-160]()`

## Public API and Reactivity

The abstract `Cache` exposes the user-facing surface that `ApolloClient` calls. Notable members documented in the type module:

- `read<T>(options): T | null` — perform a `readQuery`/`readFragment` against the cache, returning either `null` or the data. `Source: [src/cache/core/cache.ts:120-220]()`
- `write(options): Reference[] | undefined` — merge a `data` payload into the store; returns affected references so watchers can be notified. `Source: [src/cache/core/cache.ts:220-300]()`
- `diff<T>(options): DiffResult<T>` — produce a `Cache.DiffResult` describing the result and any missing fields, used by `useQuery` to compute `loading` states. `Source: [src/cache/core/cache.ts:300-380]()`
- `watch(watchOptions): Observable<T>` — subscribe to changes; the returned observable emits whenever the relevant entities are written, evicted, or replaced. `Source: [src/cache/core/types/Cache.ts:80-180]()`

Watchers are how React hooks stay reactive: a write triggers `broadcast()` on the `EntityStore`, which iterates over matching `Watchers` and pushes new results into their observables. `Source: [src/cache/inmemory/entityStore.ts:440-520]()`

In the 4.x line, `InMemoryCache` generics were aligned with `Cache.Implementation` (see `@apollo/client@4.3.0-alpha.1`), and the `4.3.0-alpha.0` release introduced the ability to define the cache type at the client level so `client.cache` reflects the concrete subclass. `Source: [src/cache/inmemory/inMemoryCache.ts:340-420]()`

## Recent Operational Notes

- `readQuery`/`readFragment` previously ignored the `optimistic` option; this was fixed in 4.2.4 (PR #13281). `Source: [src/cache/inmemory/readFromStore.ts:160-240]()`
- `@stream` directive support was added to the write path; the cost is now visible to apps that never use `@stream`, motivating the optimization proposed in issue #13304. `Source: [src/cache/inmemory/writeToStore.ts:200-280]()`
- Referentially equal results are preserved across refetches when the masked shape is unchanged (4.2.2). `Source: [src/cache/inmemory/readFromStore.ts:240-320]()`

Together, these pieces form a system where the cache is the single source of truth for normalized application data, writes flow through a deterministic normalization pipeline, and reads project that data back into query shapes while remaining reactive to changes across the entire client.

---

<a id='page-3'></a>

## React Integration, Hooks, and SSR

### Related Pages

Related topics: [Project Overview and Core Architecture](#page-1), [Caching System and InMemoryCache](#page-2), [Network Links, Transport, Errors, and v3 to v4 Migration](#page-4)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/react/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/index.ts)
- [src/react/index.react-server.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/index.react-server.ts)
- [src/react/context/ApolloContext.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/context/ApolloContext.ts)
- [src/react/context/ApolloProvider.tsx](https://github.com/apollographql/apollo-client/blob/main/src/react/context/ApolloProvider.tsx)
- [src/react/hooks/useApolloClient.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useApolloClient.ts)
- [src/react/hooks/useQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useQuery.ts)
- [src/react/hooks/useMutation.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useMutation.ts)
- [src/react/hooks/useSubscription.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useSubscription.ts)
- [src/react/hooks/useLazyQuery.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useLazyQuery.ts)
- [src/react/hooks/useFragment.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useFragment.ts)
- [src/react/hooks/useReactiveVar.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/hooks/useReactiveVar.ts)
- [src/react/ssr/RenderPromises.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/ssr/RenderPromises.ts)
- [src/react/ssr/renderToStringWithData.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/ssr/renderToStringWithData.ts)
- [src/react/ssr/getDataFromTree.ts](https://github.com/apollographql/apollo-client/blob/main/src/react/ssr/getDataFromTree.ts)
- [src/react/testing/MockedProvider.tsx](https://github.com/apollographql/apollo-client/blob/main/src/react/testing/MockedProvider.tsx)
</details>

# React Integration, Hooks, and SSR

The React integration layer in Apollo Client bridges the framework-agnostic core (client, cache, link chain) with React's component and rendering model. It exposes a small React Context-based provider, a family of hooks for executing queries, mutations, subscriptions, and reading fragments, plus a set of server-side rendering helpers that allow GraphQL data to be resolved before React flushes HTML to the client. A separate entry file exists for React Server Components (RSC), where hooks are intentionally replaced with thin stubs so client-only APIs do not leak into server-only module graphs.

## Context and Provider Layer

The Context layer is the foundation that every hook depends on. `ApolloContext` defines a single React context slot that carries the active `ApolloClient` instance and, optionally, the SSR `RenderPromises` collector used during server rendering. `ApolloProvider` consumes a `client` prop and pushes it into that context, walking the tree on the way down so any descendant can read it without prop drilling.

Source: [src/react/context/ApolloContext.ts:1-60]()
Source: [src/react/context/ApolloProvider.tsx:1-80]()

`useApolloClient` is the canonical way to read the client from context. Internally it calls `React.useContext(ApolloContext)` and throws if no provider is found, ensuring hooks fail loudly rather than silently returning undefined. This pattern is reused by every other hook to access the same client reference, guaranteeing a single client per tree.

Source: [src/react/hooks/useApolloClient.ts:1-40]()

## Hooks for Data Operations

`useQuery` is the most feature-dense hook. It accepts a query document, variables, and an options object, then orchestrates the full lifecycle: read from cache, subscribe to cache changes via `ObservableQuery`, expose loading/error/data state, drive refetching, pagination, polling, and partial results. The hook returns a tuple-like result with `data`, `loading`, `error`, `refetch`, `fetchMore`, `subscribeToMore`, `startPolling`, `stopPolling`, and other fields depending on options.

Source: [src/react/hooks/useQuery.ts:1-120]()

`useMutation` accepts a mutation document and returns an executor function plus a result tuple. Unlike `useQuery`, it does not execute on mount; it executes only when the returned function is invoked. This makes it natural for event handlers. The hook integrates with the cache so `refetchQueries`, `update`, and `optimisticResponse` propagate through the same ObservableQuery mechanism.

Source: [src/react/hooks/useMutation.ts:1-100]()

`useSubscription` opens a long-lived subscription on mount and tears it down on unmount or when variables change. It supports the same `subscribeToMore` style re-subscription behavior used by `useQuery` and forwards server-side errors through the same `errorLink` path.

Source: [src/react/hooks/useSubscription.ts:1-90]()

Two convenience hooks round out the surface:

- `useLazyQuery` returns an executor plus the same tuple shape as `useQuery`, letting callers defer execution until a user interaction fires.
- `useFragment` reads a GraphQL fragment against the normalized cache, returning a `complete` flag and the latest fragment-shaped data without owning the parent query's lifecycle.
- `useReactiveVar` subscribes a component to a single `ReactiveVar`, re-rendering the component when the local-only value changes.

Source: [src/react/hooks/useLazyQuery.ts:1-50]()
Source: [src/react/hooks/useFragment.ts:1-70]()
Source: [src/react/hooks/useReactiveVar.ts:1-30]()

## Server-Side Rendering

The SSR module is built around `RenderPromises`, a per-request collector. When a hook runs on the server, it registers an in-flight promise with `RenderPromises` instead of returning `loading: true`. After React's render pass completes, `getDataFromTree` walks the rendered tree, awaits every registered promise, and re-renders so the data appears as already-loaded. `renderToStringWithData` is a higher-level wrapper that calls `renderToString`, then awaits `getDataFromTree` and renders again until no new promises are registered. Together, these helpers let a Next.js-style `getServerSideProps` pipeline emit HTML with data already inlined.

Source: [src/react/ssr/RenderPromises.ts:1-80]()
Source: [src/react/ssr/renderToStringWithData.ts:1-50]()
Source: [src/react/ssr/getDataFromTree.ts:1-60]()

A summary of the responsibilities:

| Module | Role |
| --- | --- |
| `ApolloContext` | Carries client and SSR promise collector through the tree |
| `ApolloProvider` | Pushes `client` into context |
| `useApolloClient` | Reads client from context |
| `useQuery` / `useLazyQuery` | Subscribe to query results |
| `useMutation` | Imperative mutation executor |
| `useSubscription` | Long-lived subscription lifecycle |
| `useFragment` | Read fragment from normalized cache |
| `useReactiveVar` | React to local-only state |
| `RenderPromises` | Per-request SSR promise collector |
| `getDataFromTree` / `renderToStringWithData` | Drive React render until all queries settle |

## React Server Components and Testing

To support Next.js's App Router and similar RSC environments, Apollo Client ships a second entry at `src/react/index.react-server.ts`. That file re-exports only the parts of the public API that are safe to run in a server component module graph — types, link utilities, client factories, and SSR helpers — while replacing hooks like `useQuery`, `useMutation`, and `useSubscription` with stub implementations that throw a descriptive error if invoked. This prevents accidental imports of React DOM APIs from server-only bundles.

Source: [src/react/index.ts:1-60]()
Source: [src/react/index.react-server.ts:1-60]()

For testing, `MockedProvider` exposes a mocked link that resolves pre-canned responses keyed by GraphQL operation, with an `addTypename` toggle, `mocks` prop, and `MockLink` integration. This is the most common entry point for unit-testing components that use Apollo hooks, and its limitations (silent fall-through when no mock matches, no inspection of in-flight operations) are a frequent source of community questions.

Source: [src/react/testing/MockedProvider.tsx:1-120]()

## Limitations and Community Notes

Two long-standing community discussions are particularly relevant:

- RFC #10231 ("React 18 SSR + Suspense Support") tracks how streaming SSR and `Suspense` interact with `useQuery`'s `loading` state, and remains the canonical thread for SSR-related design decisions.
- Issue #5917 highlights that `MockedProvider` does not log missing mocks and exposes no inspection API for in-flight queries, leading to silent test failures.

These issues are upstream of the surface documented here, but they influence how teams choose between `useQuery`, `useFragment`, and mocked tests in real codebases.

---

<a id='page-4'></a>

## Network Links, Transport, Errors, and v3 to v4 Migration

### Related Pages

Related topics: [Project Overview and Core Architecture](#page-1), [React Integration, Hooks, and SSR](#page-3)

<details>
<summary>Related Source Files</summary>

The following source files were used to generate this page:

- [src/link/core/ApolloLink.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/ApolloLink.ts)
- [src/link/core/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/index.ts)
- [src/link/core/from.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/from.ts)
- [src/link/core/split.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/split.ts)
- [src/link/core/concat.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/concat.ts)
- [src/link/core/execute.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/core/execute.ts)
- [src/link/http/createHttpLink.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/http/createHttpLink.ts)
- [src/link/http/parseAndCheckHttpResponse.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/http/parseAndCheckHttpResponse.ts)
- [src/link/error/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/error/index.ts)
- [src/link/utils/createOperation.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/utils/createOperation.ts)
- [src/errors/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/errors/index.ts)
- [src/link/subscriptions/index.ts](https://github.com/apollographql/apollo-client/blob/main/src/link/subscriptions/index.ts)
</details>

# Network Links, Transport, Errors, and v3 to v4 Migration

## Overview

Apollo Client communicates with GraphQL servers through a composable pipeline called the **Link chain**. Each link is a small object implementing a `request` method that receives an `Operation` and an `Observable`-like `forward` function. Links can transform, route, retry, or terminate operations, and they are chained together with `ApolloLink.from`, `split`, and `concat`. The link layer is transport-agnostic: HTTP, WebSocket subscriptions (graphql-ws / legacy subscriptions-transport-ws), multipart subscriptions, and batched HTTP all sit on top of the same primitive.

Source: [src/link/core/ApolloLink.ts:1-120]()

## Link Architecture

The `ApolloLink` class defines the contract every link must satisfy: `request(operation, forward)` returns an `Observable` of results. Terminal links produce a real network request (for example `HttpLink`), while non-terminal links typically wrap `forward` to add behavior such as auth headers, retry, error logging, or local mocking.

Composition helpers live next to `ApolloLink`:

- `from(links)` — combines an array of links left-to-right into a single chain; the last link is expected to be terminal. Source: [src/link/core/from.ts:1-50]()
- `concat(linkA, linkB)` — explicit two-link composition equivalent to `from([linkA, linkB])`. Source: [src/link/core/concat.ts:1-40]()
- `split(test, left, right)` — routes an operation to one of two sub-chains based on a predicate, commonly used to send subscriptions to a WebSocket transport while queries/mutations go over HTTP. Source: [src/link/core/split.ts:1-60]()
- `empty()` — a no-op terminal link useful as a default. Source: [src/link/core/empty.ts:1-20]()

The `execute(link, operation)` entry point kicks off a request and is what `ApolloClient` calls internally when `client.query`, `client.mutate`, or `client.subscribe` is invoked. Source: [src/link/core/execute.ts:1-80]()

```mermaid
flowchart LR
  C[ApolloClient] --> E[execute]
  E --> A[AuthLink]
  A --> R[RetryLink]
  R --> S{split}
  S -->|query/mutation| H[HttpLink]
  S -->|subscription| W[WebSocketLink]
  H --> NET[(GraphQL Server)]
  W --> NET
```

## Transport

### HTTP

`HttpLink` (created via `createHttpLink`) is the default transport. It builds a `fetch` `Request`, applies configured headers and credentials, and forwards the response through `parseAndCheckHttpResponse`, which distinguishes HTTP errors from GraphQL errors and emits `ProtocolError` when the body cannot be parsed. Source: [src/link/http/createHttpLink.ts:1-180](), [src/link/http/parseAndCheckHttpResponse.ts:1-140]()

### Subscriptions and Multipart

For real-time updates, Apollo Client provides dedicated subscription links (e.g., `GraphQLWsLink`, `WebSocketLink`) and a multipart HTTP subscription link used by Relay-style servers. Recent releases harden these paths: `@apollo/client@4.2.6` prevents multipart subscriptions from issuing a fetch request after the request body fails to serialize. Source: [@apollo/client@4.2.6 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.6)

### Batching and Custom Transports

Because the link layer only requires a `request` method, custom transports (gRPC bridges, in-memory mocks via `SchemaLink`, polling transports) all plug into the same pipeline. `createOperation` normalizes a user request into the canonical `Operation` shape passed through the chain. Source: [src/link/utils/createOperation.ts:1-90]()

## Error Handling

Apollo Client distinguishes two error categories surfaced through the link layer:

| Class | Origin | Where it surfaces |
| --- | --- | --- |
| `GraphQLError` | Returned in the response `errors` array with a successful HTTP status | `result.errors` and `error.graphQLErrors` |
| `NetworkError` | Transport failure (offline, CORS, non-2xx HTTP, parse failure) | `error.networkError` |
| `ProtocolError` | Response could not be parsed as JSON or matched expected schema | `error.networkError` |
| `ApolloError` | Base class unifying the above | catch site of the returned `Observable` |

The `ErrorLink` (`src/link/error/index.ts`) lets applications subscribe to both `graphQLErrors` and `networkError` on every operation without terminating the chain. Source: [src/link/error/index.ts:1-80](), [src/errors/index.ts:1-60]()

Community threads such as issue #8677 (“Missing field while writing result” with subscriptions) demonstrate why error inspection matters: a `GraphQLError` returned from a subscription can short-circuit cache writes, so consuming code typically subscribes via the `next`/`error`/`complete` callbacks or inspects `error.graphQLErrors` explicitly. Source: [issue #8677](https://github.com/apollographql/apollo-client/issues/8677)

## v3 to v4 Migration

Version 4 reorganizes the public surface and tightens generic constraints on cache and link APIs. The migration is largely mechanical:

1. **Entry points.** Import from `@apollo/client` and `@apollo/client/link/...` rather than the legacy `@apollo/client/core` style. The link utilities re-exported from `src/link/core/index.ts` remain stable. Source: [src/link/core/index.ts:1-40]()
2. **Transport peer deps.** `graphql` v17 is now a valid peer dependency, so upgrading `graphql` no longer forces an Apollo Client pin. Source: [@apollo/client@4.2.3 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.3)
3. **Read APIs.** `client.readFragment` and `client.readQuery` honor `optimistic` in v4.2.4 — apps that previously monkey-patched reads should remove that logic. Source: [@apollo/client@4.2.4 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.4)
4. **Type exports.** `KeyArgsFunction` and `RelayFieldPolicy` are now exported from public entrypoints (v4.2.5), eliminating direct deep imports. Source: [@apollo/client@4.2.5 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.5)
5. **Cache generics.** The remaining cache generic constraints were aligned with `Cache.Implementation` in v4.3.0-alpha.1; some type parameters are deprecated and will be removed in a later minor. Source: [@apollo/client@4.3.0-alpha.1 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.1)
6. **Codegen.** `@apollo/client-graphql-codegen@2.1.0` supports the latest GraphQL Codegen majors, and `2.1.1` fixes omitted runtime files. Source: [@apollo/client-graphql-codegen@2.1.0 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client-graphql-codegen%402.1.0), [@apollo/client-graphql-codegen@2.1.1 release notes](https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client-graphql-codegen%402.1.1)

For most apps the migration reduces to: bump the package version, run the TypeScript compiler, address the deprecations surfaced by `Cache.Implementation`, and re-validate custom link authors against the updated `ApolloLink` typings.

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Pitfall Log

Project: apollographql/apollo-client

Summary: Found 23 structured pitfall item(s), including 3 high/blocking item(s). Top priority: Installation risk - Installation risk requires verification.

## 1. Installation risk - Installation risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/apollographql/apollo-client/issues/13305

## 2. Configuration risk - Configuration risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a configuration risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/apollographql/apollo-client/issues/13227

## 3. Security or permission risk - Security or permission risk requires verification

- Severity: high
- Evidence strength: source_linked
- Finding: Project evidence flags a security or permission risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/apollographql/apollo-client/issues/11062

## 4. Identity risk - Identity risk requires verification

- Severity: medium
- Evidence strength: runtime_trace
- Finding: Project evidence flags a identity risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Repro command: `npm install @apollo/client`
- Evidence: identity.distribution | https://github.com/apollographql/apollo-client

## 5. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: @apollo/client@4.2.3
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.2.3
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.3

## 6. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this installation risk before relying on the project: Dependency Dashboard
- User impact: Developers may fail before the first successful local run: Dependency Dashboard
- Evidence: failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/11062

## 7. Installation risk - Installation risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a installation risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: community_evidence:github | https://github.com/apollographql/apollo-client/issues/13304

## 8. Configuration risk - Configuration risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this configuration risk before relying on the project: @apollo/client@4.3.0-alpha.2
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.3.0-alpha.2
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.2

## 9. Capability evidence risk - Capability evidence risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: capability.assumptions | https://github.com/apollographql/apollo-client

## 10. Runtime risk - Runtime risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this runtime risk before relying on the project: @apollo/client-graphql-codegen@2.1.1
- User impact: Upgrade or migration may change expected behavior: @apollo/client-graphql-codegen@2.1.1
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client-graphql-codegen%402.1.1

## 11. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Developers should check this migration risk before relying on the project: @apollo/client@4.3.0-alpha.1
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.3.0-alpha.1
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.1

## 12. Maintenance risk - Maintenance risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/apollographql/apollo-client

## 13. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: downstream_validation.risk_items | https://github.com/apollographql/apollo-client

## 14. Security or permission risk - Security or permission risk requires verification

- Severity: medium
- Evidence strength: source_linked
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: risks.scoring_risks | https://github.com/apollographql/apollo-client

## 15. Runtime risk - Runtime risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this performance risk before relying on the project: @apollo/client@4.3.0-alpha.0
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.3.0-alpha.0
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.3.0-alpha.0

## 16. Runtime risk - Runtime risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this performance risk before relying on the project: Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream
- User impact: Developers may hit a documented source-backed failure mode: Cache writes call hasDirectives(["stream"]) for every written field — large overhead for apps that never use @stream
- Evidence: failure_mode_cluster:github_issue | https://github.com/apollographql/apollo-client/issues/13304

## 17. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/apollographql/apollo-client

## 18. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Evidence: evidence.maintainer_signals | https://github.com/apollographql/apollo-client

## 19. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: @apollo/client-graphql-codegen@2.1.0
- User impact: Upgrade or migration may change expected behavior: @apollo/client-graphql-codegen@2.1.0
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client-graphql-codegen%402.1.0

## 20. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.2
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.2.2
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.2

## 21. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.4
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.2.4
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.4

## 22. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.5
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.2.5
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.5

## 23. Maintenance risk - Maintenance risk requires verification

- Severity: low
- Evidence strength: source_linked
- Finding: Developers should check this maintenance risk before relying on the project: @apollo/client@4.2.6
- User impact: Upgrade or migration may change expected behavior: @apollo/client@4.2.6
- Evidence: failure_mode_cluster:github_release | https://github.com/apollographql/apollo-client/releases/tag/%40apollo/client%404.2.6

<!-- canonical_name: apollographql/apollo-client; human_manual_source: deepwiki_human_wiki -->
