Skip to content

Releases: apollographql/router

v2.12.0

24 Feb 15:31
48e385f

Choose a tag to compare

🚀 Features

Support Unix domain socket (UDS) communication for coprocessors (Issue #5739)

Many coprocessor deployments run side-by-side with the router, typically on the same host (for example, within the same Kubernetes pod).

This change brings coprocessor communication to parity with subgraphs by adding Unix domain socket (UDS) support. When the router and coprocessor are co-located, communicating over a Unix domain socket bypasses the full TCP/IP network stack and uses shared host memory instead, which can meaningfully reduce latency compared to HTTP.

By @theJC in #8348

Add redact_query_validation_errors supergraph config option (PR #8888)

The new redact_query_validation_errors option in the supergraph configuration section replaces all query validation errors with a single generic error:

{
  "message": "invalid query",
  "extensions": {
    "code": "UNKNOWN_ERROR"
  }
}

By @phryneas in #8888

Support multiple @listSize directives on the same field (PR #8872)

Warning

Multiple @listSize directives on a field only take effect after Federation supports repeatable @listSize in the supergraph schema. Until then, composition continues to expose at most one directive per field. This change makes the router ready for that Federation release.

The router now supports multiple @listSize directives on a single field, enabling more flexible cost estimation when directives from different subgraphs are combined during federation composition.

  • The router processes all @listSize directives on a field (stored as Vec<ListSizeDirective> instead of Option<ListSizeDirective>).
  • When multiple directives specify assumedSize values, the router uses the maximum value for cost calculation.
  • Existing schemas with single directives continue to work exactly as before.

This change prepares the router for federation's upcoming support for repeatable @listSize directives, and maintains full compatibility with current non-repeatable directive schemas.

By @cmorris in #8872

Add parser recursion and lexical token metrics (PR #8845)

The router now emits two new metrics: apollo.router.operations.recursion for the recursion level reached, and apollo.router.operations.lexical_tokens for the number of lexical tokens in a query.

By @jhrldev in #8845

Support subgraph-level demand control (PR #8829)

Subgraph-level demand control lets you enforce per-subgraph query cost limits in the router, in addition to the existing global cost limit for the whole supergraph. This helps you protect specific backend services that have different capacity or cost profiles from being overwhelmed by expensive operations.

When a subgraph-specific cost limit is exceeded, the router:

  • Still runs the rest of the operation, including other subgraphs whose cost is within limits.
  • Skips calls to only the over-budget subgraph, and composes the response as if that subgraph had returned null, instead of rejecting the entire query.

Per-subgraph limits apply to the total work for that subgraph in a single operation. For each request, the router tracks the aggregate estimated cost per subgraph across the entire query plan. If the same subgraph is fetched multiple times (for example, through entity lookups, nested fetches, or conditional branches), those costs are summed together and the subgraph's limit is enforced against that total.

Configuration

demand_control:
  enabled: true
  mode: enforce
  strategy:
    static_estimated:
      max: 10
      list_size: 10
      actual_cost_mode: by_subgraph
      subgraphs: # everything from here down is new (all fields optional)
        all:
          max: 8
          list_size: 10
        subgraphs:
          products:
            max: 6
            # list_size omitted, 10 implied because of all.list_size
          reviews:
            list_size: 50
            # max omitted, 8 implied because of all.max

Example

Consider a topProducts query that fetches a list of products from a products subgraph and then performs an entity lookup for each product in a reviews subgraph. Assume the products cost is 10 and the reviews cost is 5, leading to a total estimated cost of 15 (10 + 5).

Previously, you could only restrict that query via demand_control.static_estimated.max:

  • If you set it to 15 or higher, the query executes.
  • If you set it below 15, the query is rejected.

Subgraph-level demand control enables much more granular control. In addition to demand_control.static_estimated.max, which operates as before, you can also set per-subgraph limits.

For example, if you set max = 20 and reviews.max = 2, the query passes the aggregate check (15 < 20) and executes on the products subgraph (no limit specified), but doesn't execute against the reviews subgraph (5 > 2). The result is composed as if the reviews subgraph had returned null.

By @carodewig in #8829

Improve @listSize directive parsing and nested path support (PR #8893)

Demand control cost calculation now supports:

  • Array-style parsing for @listSize sizing (for example, list arguments)
  • Nested input paths when resolving list size from query arguments
  • Nested field paths in the sizedFields argument on @listSize for more accurate cost estimation

These changes are backward compatible with existing schemas and directives.

By @cmorris in #8893

Add coprocessor hooks for connector request and response stages (PR #8869)

You can now configure a coprocessor hook for the ConnectorRequest and ConnectorResponse stages of the router lifecycle.

coprocessor:
  url: http://localhost:3007
  connector:
    all:
      request:
        uri: true
        headers: true
        body: true
        context: all
        service_name: true
      response:
        headers: true
        body: true
        context: all
        service_name: true

By @andrewmcgivery in #8869

🐛 Fixes

Pass variables to introspection queries (PR #8816)

Introspection queries now receive variables, enabling @include and @skip directives during introspection.

By @Jephuff in #8816

Log warning instead of returning error for non-UTF-8 headers in externalize_header_map (PR #8828)

  • The router now emits a warning log with the name of the header instead of returning an error.
  • The remaining valid headers are returned, which is more consistent with the router's default behavior when a coprocessor isn't used.

By @rohan-b99 in #8828

Place http_client span attributes on the http_request span (PR #8798)

Attributes configured under telemetry.instrumentation.spans.http_client are now added to the http_request span instead of subgraph_request.

Given this config:

telemetry:
  instrumentation:
    spans:
      http_client:
        attributes:
          http.request.header.content-type:
            request_header: "content-type"
          http.response.header.content-type:
            response_header: "content-type"

Both attributes are now placed on the http_request span.

By @rohan-b99 in #8798

Validate ObjectValue variable fields against input type definitions (PR #8821 and PR #8884)

The router now validates individual fields of input object variables against their type definitions. Previously, variable validation checked that the variable itself was present but didn't validate the fields within the object.

Example:

## schema ##
input MessageInput {
    content: String
    author: String
}
type Receipt {
    id: ID!
}
type Query{
    send(message: MessageInput): Receipt
}

## query ##
query(: MessageInput) {
    send(message: ) {
        id
    }
}

## input variables ##
{"msg":
    {
    "content": "Hello",
    "author": "Me",
    "unknownField": "unknown",
    }
}

This request previously passed validation because the variable msg was present in the input, but the fields of msg weren't validated against the MessageInput type.

Warning

To opt out of this behavior, set the supergraph.strict_variable_validation config option to measure.

Enabled:

supergraph:
  strict_variable_validation: enforce

Disabled:

supergraph:
  strict_variable_validation: measure

By @conwuegb in #8821 and #8884

Increase internal Redis timeout from 5s to 10s (PR #8863)

Because mTLS handshakes can be slow in some environments, the internal Redis timeout is now 10s (previously 5s). The connection "unresponsive" threshold is also increased from 5s to 10s.

By @aaronArinder in #8863

Enforce and log operation limits for cached query plans (PR #8810)

The router now logs the operation-limits wa...

Read more

v2.12.0-rc.1

18 Feb 16:52

Choose a tag to compare

v2.12.0-rc.1 Pre-release
Pre-release
2.12.0-rc.1

v2.12.0-rc.0

18 Feb 13:23

Choose a tag to compare

v2.12.0-rc.0 Pre-release
Pre-release
2.12.0-rc.0

v2.12.0-alpha.0

18 Feb 11:26

Choose a tag to compare

v2.12.0-alpha.0 Pre-release
Pre-release
2.12.0-alpha.0

v2.11.0

27 Jan 15:04
01d3752

Choose a tag to compare

🚀 Features

Support client awareness metadata via HTTP headers (PR #8503)

Clients can now send library name and version metadata for client awareness and enhanced client awareness using HTTP headers. This provides a consistent transport mechanism instead of splitting values between headers and request.extensions.

By @calvincestari in #8503

Reload OCI artifacts when a tag reference changes (PR #8805)

You can now configure tag-based OCI references in the router. When you use a tag reference such as artifacts.apollographql.com/my-org/my-graph:prod, the router polls and reloads when that tag points to a new artifact.

This also applies to automatically generated variant tags and custom tags.

By @graytonio in #8805

Add memory limit option for cooperative cancellation (PR #8808)

The router now supports a memory_limit option on experimental_cooperative_cancellation to cap memory allocations during query planning. When the memory limit is exceeded, the router:

  • In enforce mode, cancels query planning and returns an error to the client.
  • In measure mode, records the cancellation outcome in metrics and allows query planning to complete.

The memory limit works alongside the existing timeout option. Whichever limit is reached first triggers cancellation.

This feature is only available on Unix platforms when the global-allocator feature is enabled and dhat-heap is not enabled.

Example configuration:

supergraph:
  query_planning:
    experimental_cooperative_cancellation:
      enabled: true
      mode: enforce  # or "measure" to only record metrics
      memory_limit: 50mb  # Supports formats like "50mb", "1gb", "1024kb", etc.
      timeout: 5s  # Optional: can be combined with memory_limit

By @rohan-b99 in #8808

Add memory tracking metrics for requests (PR #8717)

The router now emits two histogram metrics to track memory allocation activity during request processing:

  • apollo.router.request.memory: Memory activity across the full request lifecycle (including parsing, validation, query planning, and plugins)
  • apollo.router.query_planner.memory: Memory activity for query planning work in the compute job thread pool

Each metric includes:

  • allocation.type: allocated, deallocated, zeroed, or reallocated
  • context: The tracking context name (for example, router.request or query_planning)

This feature is only available on Unix platforms when the global-allocator feature is enabled and dhat-heap is not enabled.

By @rohan-b99 in #8717

🐛 Fixes

Support nullable @key fields in response caching (PR #8767)

Response caching can now use nullable @key fields. Previously, the response caching feature rejected nullable @key fields, which prevented caching in schemas that use them.

When you cache data keyed by nullable fields, keep your cache keys simple and avoid ambiguous null values.

By @aaronArinder in #8767

Return 429 instead of 503 when enforcing a rate limit (PR #8765)

In v2.0.0, the router changed the rate-limiting error from 429 (TOO_MANY_REQUESTS) to 503 (SERVICE_UNAVAILABLE). This change restores 429 to align with the router error documentation.

By @carodewig in #8765

Add status code and error type attributes to http_request spans (PR #8775)

The router now always adds the http.response.status_code attribute to http_request spans (for example, for router -> subgraph requests). The router also conditionally adds error.type for non-success status codes.

By @rohan-b99 in #8775

Report response cache invalidation failures as errors (PR #8813)

The router now returns an error when response cache invalidation fails. Previously, an invalidation attempt could fail without being surfaced as an error.

After you upgrade, you might see an increase in the apollo.router.operations.response_cache.invalidation.error metric.

By @bnjjj in #8813

Reuse response cache Redis connections for identical subgraph configuration (PR #8764)

The response cache now reuses Redis connection pools when subgraph-level configuration resolves to the same Redis configuration as the global all setting. Previously, the router could create redundant Redis connections even when the effective configuration was identical.

Impact: If you configure response caching at both the global and subgraph levels, you should see fewer Redis connections and lower connection overhead.

By @bnjjj in #8764

Prevent TLS connections from hanging when a handshake stalls (PR #8779)

The router listener loop no longer blocks while waiting for a TLS handshake to complete. Use server.http.tls_handshake_timeout to control how long the router waits before terminating a connection (default: 10s).

By @rohan-b99 in #8779

Emit cardinality overflow metrics for more OpenTelemetry error formats (PR #8740)

The router now emits the apollo.router.telemetry.metrics.cardinality_overflow metric for additional OpenTelemetry cardinality overflow error formats.

By @bonnici in #8740

Propagate trace context on WebSocket upgrade requests (PR #8739)

The router now injects trace propagation headers into the initial HTTP upgrade request when it opens WebSocket connections to subgraphs. This preserves distributed trace continuity between the router and subgraph services.

Trace propagation happens during the HTTP handshake only. After the WebSocket connection is established, headers cannot be added to individual messages.

By @theJC in #8739

Stop query planning compute jobs when the parent task is canceled (PR #8741)

Query planning compute jobs now stop when cooperative cancellation cancels the parent task.

By @rohan-b99 in #8741

Reject invalidation requests with unknown fields (PR #8752)

The response cache invalidation endpoint now rejects request payloads that include unknown fields. When unknown fields are present, the router returns HTTP 400 (Bad Request).

By @bnjjj in #8752

Restore plugin access to SubscriptionTaskParams in execution::Request builders (PR #8771)

Plugins and other external crates can use SubscriptionTaskParams with execution::Request builders again. This restores compatibility for plugin unit tests that construct subscription requests.

By @aaronArinder in #8771

Support JWT tokens with multiple audiences (PR #8780)

When issuers or audiences is included in the router's JWK configuration, the router will check each request's JWT for iss or aud and reject requests with mismatches.

Expected behavior:

  • If present, the iss claim must be specified as a string.
    • ✅ The JWK's issuers is empty.
    • ✅ The iss is a string and is present in the JWK's issuers.
    • ✅ The iss is null.
    • ❌ The iss is a string but is not present in the JWK's issuers.
    • ❌ The iss is not a string or null.
  • If present, the aud claim can be specified as either a string or an array of strings.
    • ✅ The JWK's audiences is empty.
    • ✅ The aud is a string and is present in the JWK's audiences.
    • ✅ The aud is an array of strings and at least one of those strings is present in the JWK's audiences.
    • ❌ The aud is not a string or array of strings (i.e., null).

Behavior prior to this change:

  • If the iss was not null or a string, it was permitted (regardless of its value).
  • If the aud was an array, it was rejected (regardless of its value).

By @carodewig in #8780

Enforce feature restrictions for warning-state licenses (PR #8768)

The router now enforces license restrictions even when a license is in a warning state. Previously, warning-state licenses could bypass enforcement for restricted features.

If your deployment uses restricted features, the router returns an error instead of continuing to run.

By @aaronArinder in #8768

🛠 Maintenance

Warn at startup when OTEL_EXPORTER_OTLP_ENDPOINT is set (PR #8729)

The ...

Read more

v2.11.0-rc.0

22 Jan 16:55

Choose a tag to compare

v2.11.0-rc.0 Pre-release
Pre-release
2.11.0-rc.0

v2.11.0-abstract.1

18 Dec 20:08
v2.11.0-abstract.1
df42d72

Choose a tag to compare

v2.11.0-abstract.1 Pre-release
Pre-release
2.11.0-abstract.1

v2.10.0 (LTS)

12 Dec 12:42
696b1e1

Choose a tag to compare

Long-Term Support

This release is marked for LTS under the v2026.1 LTS Policy for the GraphOS Runtime. It will be supported until September 30, 2026 with patch updates.

🚀 Features

Response caching is now Generally Available 🎉 (PR #8678)

Response caching is now Generally Available (GA) and ready for production use!

Response caching enables the router to cache subgraph query responses using Redis, improving query latency and reducing load on your underlying services. Unlike traditional HTTP caching solutions, response caching provides GraphQL-aware caching at the entity and root field level, making cached data reusable across different users and queries.

For complete documentation, configuration options, and quickstart guide, see the response caching documentation.

Key benefits

  • Improved performance: Cache origin responses and reuse them across queries to reduce latency
  • Reduced subgraph load: Minimize redundant requests to your subgraphs by serving cached data
  • Entity-level caching: Cache individual entity representations independently, enabling fine-grained control over data freshness
  • Flexible cache control: Set different TTLs for different types of data based on @cacheControl directives or Cache-Control response headers
  • Privacy-aware: Share cached data across users while maintaining privacy for personalized data
  • Active cache invalidation: Tag cached data with @cacheTag and invalidate specific cache entries via HTTP endpoint when data changes

What's cached

The router caches two kinds of data:

  • Root query fields: Cached as complete units (the entire response for these root fields)
  • Entity representations: Cached independently—each origin's contribution to an entity is cached separately and can be reused across different queries

Additional features

  • Cache debugger: See exactly what's being cached during development
  • Redis cluster support: Scale your cache with Redis cluster deployments and read replicas
  • Comprehensive metrics: Monitor cache performance with detailed Redis-specific metrics

By @bnjjj in #8678

Support Redis read replicas (PR #8405)

Read-only queries are now sent to replica nodes when using clustered Redis. Previously, all commands were sent to the primary nodes.

This change applies to all Redis caches, including the query plan cache and the response cache.

By @carodewig in #8405

Enable HTTP/2 header size limits for TCP and UDS (PR #8673)

The router's HTTP/2 header size limit configuration option now applies to requests using TCP and UDS (Unix domain sockets). Previously, this setting only worked for TLS connections.

By @aaronArinder in #8673

🐛 Fixes

Enable invalidation endpoint when any subgraph has invalidation enabled (PR #8680)

Previously, the response cache invalidation endpoint was only enabled when global invalidation was enabled via response_cache.subgraph.all.invalidation.enabled. If you enabled invalidation for only specific subgraphs without enabling it globally, the invalidation endpoint wouldn't start, preventing cache invalidation requests from being processed.

The invalidation endpoint now starts if either:

  • Global invalidation is enabled (response_cache.subgraph.all.invalidation.enabled: true), OR
  • Any individual subgraph has invalidation enabled

This enables more flexible configuration where you can enable invalidation selectively for specific subgraphs:

response_cache:
  enabled: true
  invalidation:
    listen: 127.0.0.1:4000
    path: /invalidation
  subgraph:
    all:
      enabled: true
      # Global invalidation not enabled
    subgraphs:
      products:
        invalidation:
          enabled: true  # Endpoint now starts
          shared_key: 

By @bnjjj in #8680

Require Redis configuration only when response caching is enabled (PR #8684)

Previously, the router attempted to connect to Redis for response caching regardless of whether response caching was enabled or disabled. This caused unnecessary connection attempts and configuration errors even when the feature was explicitly disabled.

The router now ignores Redis configuration if response caching is disabled. If response caching is configured to be enabled, Redis configuration is required, and missing Redis configuration raises an error on startup:

Error: you must have a redis configured either for all subgraphs or for subgraph "products"

By @bnjjj in #8684

Prevent deleted coprocessor context keys from reappearing in later stages (PR #8679)

Coprocessor context keys deleted in a previous stage no longer reappear in later stages.

By @rohan-b99 in #8679

Customize response caching behavior at the subgraph level (PR #8652)

You can now customize cached responses using Rhai or coprocessors. You can also set a different private_id based on subgraph request headers.

Example Rhai script customizing private_id:

fn subgraph_service(service, subgraph) {
    service.map_request(|request| {
        if "private_id" in request.headers {
            request.context["private_id"] = request.headers["private_id"];
        }
    });
}

By @bnjjj in #8652

Prevent glibc mismatch in DIY Docker images (Issue #8450)

The DIY Dockerfile now pins the Rust builder to the Bookworm variant (for example, rust:1.91.1-slim-bookworm) so the builder and runtime share the same Debian base. This prevents the image from failing at startup with /lib/x86_64-linux-gnu/libc.so.6: version 'GLIBC_2.39' not found.

This resolves a regression introduced when the rust:1.90.0 bump used a generic Rust image without specifying a Debian variant. The upstream Rust image default advanced to a newer variant with glibc 2.39, although the DIY runtime remained on Bookworm, creating a version mismatch.

By @theJC in #8629

Correct response cache fetch error metric (PR #8711)

The apollo.router.operations.response_cache.fetch.error metric was out of sync with the apollo.router.cache.redis.errors metric because errors weren't being returned from the Redis client wrapper. The response caching plugin now increments the error metric as expected.

By @carodewig in #8711

Emit http.client.request.body.size metric correctly (PR #8712)

The histogram for http.client.request.body.size was using the SubgraphRequestHeader selector, looking for Content-Length before it had been set in on_request, so http.client.request.body.size wasn't recorded. The router now uses the on_response handler and stores the body size in the request context extensions.

By @rohan-b99 in #8712

Record http.server.response.body.size metric correctly (PR #8697)

Previously, the http.server.response.body.size metric wasn't recorded because the router attempted to read from the Content-Length header before it had been set. The router now uses the size_hint of the body if it's exact.

By @rohan-b99 in #8697

Treat interface objects as entities in response caching (PR #8582)

Interface objects can be entities, but response caching wasn't treating them that way. Interface objects are now respected as entities so they can be used as cache keys.

By @aaronArinder in #8582

🛠 Maintenance

Warn when Datadog propagator isn't exclusively active (PR #8677)

The router now validates propagator configuration and emits a warning log if:

  • The Datadog propagator is enabled and any other propagators are enabled (except baggage)
  • Datadog tracing is enabled and other propagators are enabled (except baggage)

By @rohan-b99 in #8677

v2.10.0-rc.0

08 Dec 17:39

Choose a tag to compare

v2.10.0-rc.0 Pre-release
Pre-release
2.10.0-rc.0

v2.9.0

28 Nov 17:47
f65c6b9

Choose a tag to compare

🚀 Features

Add CORS Private Network Access support (PR #8279)

CORS configuration now supports private network access (PNA). Enable PNA for a CORS policy by specifying the private_network_access field, which supports two optional subfields: access_id and access_name.

Example configuration:

cors:
  policies:
    - origins: ["https://studio.apollographql.com"]
      private_network_access:
        access_id:
    - match_origins: ["^https://(dev|staging|www)?\\.my-app\\.(com|fr|tn)$"]
      private_network_access:
        access_id: "01:23:45:67:89:0A"
        access_name: "mega-corp device"

By @TylerBloom in #8279

Configure maximum HTTP/2 header list size (PR #8636)

The router now supports configuring the maximum size for HTTP/2 header lists via the limits.http2_max_headers_list_bytes setting. This protects against excessive resource usage from clients sending large sets of HTTP/2 headers.

The default remains 16KiB. When a client sends a request with HTTP/2 headers whose total size exceeds the configured limit, the router rejects the request with a 431 error code.

Example configuration:

limits:
  http2_max_headers_list_bytes: "48KiB"

By @aaronArinder in #8636

Customize response cache key per subgraph via context (PR #8543)

The response cache key can now be customized per subgraph using the apollo::response_cache::key context entry. The new subgraphs field enables defining separate cache keys for individual subgraphs.

Subgraph-specific data takes precedence over data in the all field—the router doesn't merge them. To set common data when providing subgraph-specific data, add it to the subgraph-specific section.

Example payload:

{
  "all": 1,
  "subgraph_operation1": "key1",
  "subgraph_operation2": {
    "data": "key2"
  },
  "subgraphs": {
    "my_subgraph": {
      "locale": "be"
    }
  }
}

By @bnjjj in #8543

Add telemetry selector for Cache-Control metrics (PR #8524)

The new response_cache_control selector enables telemetry metrics based on the computed Cache-Control header from subgraph responses.

Example configuration:

telemetry:
  exporters:
    metrics:
      common:
        service_name: apollo-router
        views:
          - name: subgraph.response.cache_control.max_age
            aggregation:
              histogram:
                buckets:
                - 10
                - 100
                - 1000
                - 10000
                - 100000
  instrumentation:
    instruments:
      subgraph:
        subgraph.response.cache_control.max_age:
          value:
            response_cache_control: max_age
          type: histogram
          unit: s
          description: A histogram of the computed TTL for a subgraph response

By @bnjjj in #8524

🐛 Fixes

Remove _redacted suffix from event attributes in apollo.router.state.change.total metric (Issue #8464)

Event names in the apollo.router.state.change.total metric no longer include the _redacted suffix. The metric now uses the Display trait instead of Debug for event names, changing values like updateconfiguration_redacted to updateconfiguration in APM platforms.

The custom behavior for UpdateLicense events is retained—the license state name is still appended.

By @rohan-b99 in #8464

Preserve Content-Length header for responses with known size (Issue #7941)

The router now uses the Content-Length header for GraphQL responses with known content lengths instead of transfer-encoding: chunked. Previously, the fleet_detector plugin destroyed HTTP body size hints when collecting metrics.

This extends the fix from #6538, which preserved size hints for router → subgraph requests, to also cover client → router requests and responses. Size hints now flow correctly through the entire pipeline for optimal HTTP header selection.

By @morriswchris in #7977

Correct apollo.router.operations.subscriptions.events metric counting (PR #8483)

The apollo.router.operations.subscriptions.events metric now increments correctly for each subscription event (excluding ping/pong/close messages). The counter call has been moved into the stream to trigger on each event.

This change also removes custom pong response handling before connection acknowledgment, which previously caused duplicate pongs because the WebSocket implementation already handles pings by default.

By @rohan-b99 in #8483

Unify timeout codes in response caching metrics (PR #8515)

Tokio- and Redis-based timeouts now use the same timeout code in apollo.router.operations.response_cache.*.error metrics. Previously, they were inadvertently given different code values.

By @carodewig in #8515

📃 Configuration

Remove unused TTL parameter from response cache Redis configuration (PR #8513)

The ttl parameter under redis configuration had no effect and is removed. Configure TTL at the subgraph level to control cache entry expiration:

preview_response_cache:
  enabled: true
  subgraph:
    all:
      enabled: true
      ttl: 10m  # ✅ Configure TTL here
      redis:
        urls: [ "redis://..." ]
        # ❌ ttl was here previously (unused)

By @carodewig in #8513

📚 Documentation

Document active subgraph requests selector (PR #8530)

The telemetry selectors documentation now correctly reflects the active_subgraph_requests attribute.

By @faisalwaseem in #8530

Add Redis cache suggestions to response cache documentation (PR #8624)

The FAQ now includes information about supported Redis versions and Redis key eviction setup.

By @carodewig in #8624