chore(deps): update dependency apollographql/router to v2.13.0#88
Merged
renovate[bot] merged 1 commit intomainfrom Apr 1, 2026
Merged
chore(deps): update dependency apollographql/router to v2.13.0#88renovate[bot] merged 1 commit intomainfrom
renovate[bot] merged 1 commit intomainfrom
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
2.12.1→2.13.0Release Notes
apollographql/router (apollographql/router)
v2.13.0Compare Source
🚀 Features
Add
context_idselector for telemetry to expose unique per-request identifier (PR #8899)A new
context_idselector is now available for router, supergraph, subgraph, and connector telemetry instrumentation. This selector exposes the unique per-request context ID, which you can use to reliably correlate and debug requests in traces, logs, and custom events.The context ID was previously accessible in Rhai scripts as
request.idbut had no telemetry selector. You can now includecontext_id: truein your telemetry configuration to add the context ID to spans, logs, and custom events.Example configuration:
By @BobaFetters in #8899
Enable Unix Domain Socket paths (PR #8894)
Enables Unix Domain Socket (UDS) paths for both coprocessors and subgraphs. Paths must use
?path=as the query param:unix:///tmp/some.sock?path=some_pathBy @aaronarinder in #8894
Add configurable
pool_idle_timeoutfor HTTP client connection pools (PR #9014)Adds a new
pool_idle_timeoutconfiguration option to the HTTP client used by subgraphs, connectors, and coprocessors. This controls how long idle keep-alive connections remain in the connection pool before being evicted. The default is 15 seconds (up from the previous hardcoded 5 seconds). Setting it tonulldisables the idle eviction interval entirely, meaning pooled connections are never evicted due to idleness.The option is available at every level where HTTP client configuration applies:
By @aaronarinder in #9014
Add persisted query ID context key (PR #8959)
Adds a context key for the persisted query ID in the router. The
PersistedQueryLayernow stores the persisted query ID in the request context, and the Rhai engine can access it via that key.By @faisalwaseem in #8959
Add retry layer for push metrics exporters (PR #9036)
Adds a
RetryMetricExporterlayer that retries up to three times with jittered exponential backoff for theapollo metricsandotlpnamed exporters.By @rohan-b99 in #9036
🐛 Fixes
Support more types of nullable elements in response/entity cache keys (PR #8923)
PR #8767 (released in Router v2.11.0) changed the entity and response caching keys to support nullable elements. The implementation covered the case of a field explicitly being set to null, but didn't cover the following cases:
This change adds support for those cases.
By @carodewig in #8923
Pin transitive
h2dependency at minimum v0.4.13 to pick up critical flow-control, deadlock, and tracing fixes (PR #9033)h20.4.13 (released January 5, 2026) contains three fixes directly relevant to the router, which uses h2 exclusively as a client when connecting to subgraphs:Capacity deadlock under concurrent streams (#860) — high relevance: Under concurrent load with
max_concurrent_streamslimits in effect, flow-control capacity could be assigned to streams still inpending_openstate. Those streams could never consume the capacity, starving already-open streams and permanently freezing all outgoing traffic on the connection with no error surfaced. This is directly triggerable in the router: any subgraph behind Envoy or a gRPC backend advertises amax_concurrent_streamslimit (Envoy defaults to 100), and under production load the router will routinely queue more concurrent requests than that limit allows.OTel tracing span lifetime leak (#868) — high relevance: The h2
Connectionobject captured the active tracing span at connection creation time as its parent, keeping that span alive for the entire lifetime of the connection. Since the router wraps every subgraph request in an OpenTelemetry span and connections are pooled, affected spans could linger indefinitely under sustained traffic — never being exported to the tracing backend and accumulating in memory.Flow-control stall on padded DATA frames (#869) — lower relevance for typical subgraphs, higher for connectors: Padding bytes in
DATAframes were not being returned to the flow-control window, causing the connection window to drain to zero and permanently stalling downloads with no error. Typical GraphQL/gRPC subgraphs do not send padded frames, but router connectors calling arbitrary HTTP APIs (e.g., Google Cloud Storage or CDN-backed endpoints) can encounter this.By @theJC in #9033
Return 503 for rate limit traffic shaping (PR #9013)
Reverts PR #8765.
When the router's rate limit or buffer capacity is exceeded, it now returns HTTP 503 (Service Unavailable) instead of HTTP 429 (Too Many Requests).
HTTP 429 implies that a specific client has sent too many requests and should back off. HTTP 503 more accurately reflects the situation: the router is temporarily unable to handle the request due to overall service load, not because of the behavior of any individual client.
This change affects both router-level and subgraph-level rate limiting. Documentation has been updated to reflect the new status code.
By @carodewig in #9013
Set
Cache-Control: no-storewhen the response cache returns GraphQL errors (PR #8933)When using the response cache plugin, if a query spans multiple subgraphs and one returns an error or times out, the final HTTP response was still carrying the successful subgraph's
Cache-Controlheader (e.g.max-age=1800, public). This allowed intermediate caches (CDNs, reverse proxies) to cache and serve incomplete or stale partial responses to other clients.If the response cache plugin is enabled and was going to set a
Cache-Controlheader, but the response contains any GraphQL errors, it now setsCache-Control: no-storeinstead of the merged subgraph cache control value.By @carodewig in #8933
Apply entity-less subgraph errors to the nearest parent instead of every entity
When making an entity resolution, if entity resolution fails (for example, because the path from the subgraph was malformed), the router applied errors to every item in the list of entities expected. For example, if 2000 entities were expected but 2000 errors were returned instead, each error was applied to every entity. This causes an explosion of errors and leads to significant memory allocations that can cause OOMKills.
When the router can't determine where an error should be applied, it now applies it to the most immediate parent of the targeted entity — for a list of users, it applies to the list itself rather than to each index of that list.
By @aaronArinder in #8962
Report
http.client.response.body.sizeandhttp.server.response.body.sizeconsistently whencontent-lengthis absent or compression is used (PR #8972)Reporting these metrics previously relied on either the
Content-Lengthheader or thesize_hintof the body, which reports the uncompressed size. OpenTelemetry semantic conventions recommend reporting the compressed size.The router now consistently reports the compressed size when compression is used, even when
Content-Lengthis absent, for:By @rohan-b99 in #8972
Ensure query planning allocation stats are still recorded if cooperative cancellation is not enabled (PR #8902)
The metric
apollo.router.query_planner.memorywas unintentionally only showing allocations during thequery_parsingcompute job if cooperative cancellation for query planning was not enabled. Bothquery_parsingandquery_planningshould now be available.By @rohan-b99 in #8902
Align
ServiceMonitornaming with other chart resources using therouter.fullnamehelper (Issue #TSH-22160)The
ServiceMonitorHelm resource was using.Release.Namedirectly as itsmetadata.name, while all other chart resources (e.g.Service,Deployment) already used therouter.fullnamehelper. This caused a naming inconsistency: for a release namedmy-release, theServicewould be namedmy-release-routerbut theServiceMonitorwould be namedmy-release.This change aligns the
ServiceMonitorname with the rest of the chart by using{{ include "router.fullname" . }}, ensuring consistent naming and proper support fornameOverrideandfullnameOverridevalues.By @mateusgoettems in #8929
Return null data and respect error location config for fully-unauthorized requests (PR #9022)
When the query planner rejected a request because all fields were unauthorized, the response always placed errors in the
errorsarray and returneddata: {}, ignoring the configurederrors.responselocation (errors,extensions, ordisabled). The router now returnsdata: nulland respectserrors.responseanderrors.log, consistent with partially-unauthorized requests.By @carodewig in #9022
Handle both
deprecatedenum values when merging coprocessor context (PR #8913)A change to coprocessor context merges in Router v2.10 caused keys to be deleted when
context: trueis used as the coprocessor context selector in the router configuration file.The workaround was to pass
context: deprecatedinstead. This change brings parity whencontext: trueis provided.By @carodewig in #8913
Block router startup when certain OTEL environment variables are set (PR #8915)
The router now fails to start if any of the following OpenTelemetry (OTEL) environment variables are set:
OTEL_EXPORTER_OTLP_ENDPOINTOTEL_EXPORTER_OTLP_TRACES_ENDPOINTOTEL_EXPORTER_OTLP_METRICS_ENDPOINTUsing these variables isn't supported by the router because they can override or interfere with its built-in telemetry configuration, leading to unexpected behavior.
Previously, the router emitted a warning when
OTEL_EXPORTER_OTLP_ENDPOINTwas present. Startup is now blocked to prevent unintended telemetry configuration conflicts.If your deployment defines any of these environment variables (for example, through base container images, platform defaults, or infrastructure tooling), remove them before starting the router.
By @OriginLeon in #8915
Prevent the readiness ticker from resetting the sampling window clock on recovery (PR #8966)
The readiness ticker recreated its
interval_atinside the recovery loop on every cycle, which reset the sampling window clock each time the router returned to ready. This caused inconsistent sampling behavior across recovery cycles. Additionally, the rejection counter was read and zeroed with separate atomic operations (load+store(0)), leaving a race window where rejections arriving between the two operations could be silently dropped.The fix creates the interval once outside the loop, sets
MissedTickBehavior::Delayto prevent catch-up ticks after the recovery sleep, and usesswap(0, Relaxed)to atomically read and reset the rejection counter in a single operation.By @OriginLeon in #8966
Ensure
http2onlyuses h2c for cleartext connections (PR #9018)hyperdoes not support upgrading cleartext connections from HTTP/1.1 to HTTP/2. To use HTTP/2 without TLS, clients must use 'prior knowledge' — connecting with the HTTP/2 preface directly. This is whatexperimental_http2: http2onlyis for, but previously HTTP/1 was always enabled in the connector, causing the client to fall back to HTTP/1.1 regardless. This fix applies to all outbound HTTP connections: subgraphs, connectors, and coprocessors.experimental_http2disabledisableenableenablehttp2onlyhttp2onlyBy @carodewig in #9018
Reject invalid values for client library name and version (PR #8934)
Rejects invalid values (validated against a regex) for library name and version provided in headers or operation extensions, which are used for the Client Awareness feature and telemetry.
By @BoD in #8934
Correct
no-storeandno-cachebehavior for response cache and entity cache plugins (PR #8948 and PR #8952)no-storeandno-cachehave different meanings. Per RFC 9111:no-store: allows serving a response from cache, but prohibits storing the response in cacheno-cache: prohibits serving a response from cache, but allows storing the response in cache(Note:
no-cacheactually prohibits serving a response from cache without revalidation — but the router doesn't distinguish between lookup and revalidation.)The response caching and entity caching plugins were incorrectly treating
no-storeas both 'no serving response from the cache' and 'no storing response in the cache.' This change corrects that behavior.By @carodewig in #8948 and #8952
Allow
existsconditions withrequest_headerselectors on response-stage coprocessor and event configurations (PR #8964)Using
exists: { request_header: <name> }as a condition on response-stage coprocessor or telemetry event configurations (e.g.on: response) previously caused the router to reject the configuration at startup with a validation error, even though the condition is valid and works correctly at runtime.The validator was incorrectly rejecting request-stage selectors inside
Existsconditions for response-stage configurations. This is safe becauseevaluate_request()pre-resolves these conditions before they are stored for response-time evaluation: if the header is present the condition becomesTrue; if absent, the event or coprocessor call is discarded and never reaches the response stage.By @OriginLeon in #8964
📃 Configuration
Enable the router to pull graph artifacts from insecure (non-SSL) registries
You can configure a list of safe registry hostnames to enable the router to pull graph artifacts over HTTP instead of HTTPS. Insecure registries are commonly run within a private network such as a Kubernetes cluster or as a pull-through cache, where you want to avoid the overhead of setting up and distributing SSL certificates.
By @sirddoger in #8919
🛠 Maintenance
Update to OpenTelemetry 0.31.0 (PR #8922)
The router now uses v0.31.0 of the OpenTelemetry Rust libraries. This update includes many bug fixes and performance improvements from upstream.
The router doesn't guarantee the stability of downstream pre-1.0 APIs, so users that directly interact with OpenTelemetry must update their code accordingly.
As part of this upgrade, Zipkin Native exporter is deprecated upstream. Switch to the OTLP exporter, which Zipkin now supports natively. Note that Zipkin Native exporter no longer supports setting a service name — if you need this, switch to the OTLP exporter.
By @BrynCooke @goto-bus-stop @rohan-b99 in #8922
Use
cargo build --locked --releasein DIYDockerfile.repofor deterministic, lockfile-respecting builds (PR #8983)The DIY
Dockerfile.repopreviously usedcargo install --path apollo-router, which doesn't enforce the versions inCargo.lock— resulting in possible non-deterministic dependency resolution and builds that could diverge from what CI produces.Using
cargo build --locked --release -p apollo-routerensures the versions in the lockfile are respected and the DIY build path more closely aligns with CI.By @theJC in #8983
📚 Documentation
Document AWS API Gateway support for HTTP multipart subscriptions
Updates the API gateway subscriptions documentation to reflect that Amazon API Gateway now supports response streaming for REST APIs. HTTP multipart subscriptions are supported when the router is behind AWS API Gateway. Includes a link to the AWS announcement (November 2025) and a short configuration note linking to Response transfer mode.
By @smyrick in #8907
Add documentation for
experimental_hoist_orphan_errorsconfigurationAdds the
experimental_hoist_orphan_errorsconfiguration option to the YAML configuration reference. The documentation covers the feature's purpose (reducing multiplicative error propagation from entity resolution), per-subgraph and global enablement examples, the spec compliance caveat, and the known limitation that error counts are reduced but not hard-capped.By @andywgarcia in #8999
Document proxy root certificate configuration for router containers (PR #8823)
Documents how to add corporate proxy root certificates to Apollo Router containers — required for enterprise environments where TLS inspection proxies intercept HTTPS traffic.
The documentation includes:
By @the-gigi-apollo in #8823
Correct JWT authentication example hierarchy in the router authentication guide
Updates the GraphOS Router authentication guide to use the correct JWT configuration path in the YAML example. The example now shows
authentication.router.jwt.jwksandauthentication.router.jwt.on_error, matching the actual router configuration hierarchy.By @the-gigi-apollo in #8901
Document
http_clientspan attribute limitations (PR #8967)Documents that
http_clientspan attributes don't support conditions or thestaticselector, causing a router startup failure when attempted.By @mabuyo in #8967
🧪 Experimental
Add
experimental_hoist_orphan_errorsconfiguration for controlling orphan error path assignmentAdds a new
experimental_hoist_orphan_errorsconfiguration that controls how entity-less ("orphan") errors from subgraphs are assigned paths in the response. When enabled for a subgraph, orphan errors are assigned to the nearest non-array ancestor in the response path, preventing them from being duplicated across every element in an array. This can be enabled globally viaallor per-subgraph via thesubgraphsmap. Per-subgraph settings overrideall.Here's an example when targeting a specific subgraph,
my_subgraph:An example when targeting all subgraphs:
And an example enabling for all subgraphs except one:
Use this feature only if you know you have subgraphs that don't respond with the correct paths when making entity calls. If you're unsure, you probably don't need this.
By @aaronArinder in #8998
Configuration
📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 Automerge: Enabled.
♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.