Skip to content

Releases: graphql-hive/router

apollo-router-hive-fork 3.1.1 (2026-08-16)

Choose a tag to compare

@knope-bot knope-bot released this 16 Aug 15:00
da8f2ad

Fixes

Stop cancellation from interrupting an active usage flush

The usage agent now observes cancellation while waiting for the next flush interval instead of checking only after the full interval has elapsed. Cancellation remains pending while an active flush completes, preventing a drained report batch from being lost when its send future is interrupted.

hive-router 0.1.0 (2026-08-13)

Choose a tag to compare

@knope-bot knope-bot released this 13 Aug 13:29
32b6f84

Breaking Changes

Fix missing demand control metrics names

Previously added metrics names were missing the hive.router.demand_control. prefix. This has been fixed in this change.

Here's a list of the metrics that have been fixed:

  • cost.estimated -> hive.router.demand_control.cost.estimated
  • cost.actual -> hive.router.demand_control.cost.actual
  • cost.delta -> hive.router.demand_control.cost.delta

Fixes

Allow async fn in the on_http_request plugin hook

RouterPlugin::on_http_request now returns OnHttpRequestHookFuture<'req> instead of OnHttpRequestHookResult<'req> directly, so plugins can await inside - for example calling an upstream auth or feature-flag service - before the rest of the request pipeline runs.

The hook still runs on the same worker thread it started on and is never moved across threads, so the returned future does not need to be Send.

Update any plugin that overrides on_http_request to return a boxed future:

// Before
fn on_http_request<'req>(
    &self,
    payload: OnHttpRequestHookPayload<'req>,
) -> OnHttpRequestHookResult<'req> {
    self.record_request(&payload);
    payload.proceed()
}

// After
fn on_http_request<'req>(
    &'req self,
    payload: OnHttpRequestHookPayload<'req>,
) -> OnHttpRequestHookFuture<'req> {
    Box::pin(async move {
        self.record_request(&payload);
        payload.proceed()
    })
}

If the body reads self inside the async move block, &self needs to become &'req self - the future now holds that borrow for its own lifetime 'req, so the borrow has to be able to live at least that long.

Plugins that don't override on_http_request are unaffected.

See plugin_examples/async_http_fetch for an example that awaits an upstream HTTP call before proceeding.

hive-router-plan-executor 8.0.0 (2026-08-13)

Choose a tag to compare

@knope-bot knope-bot released this 13 Aug 13:29
32b6f84

Breaking Changes

Allow async fn in the on_http_request plugin hook

RouterPlugin::on_http_request now returns OnHttpRequestHookFuture<'req> instead of OnHttpRequestHookResult<'req> directly, so plugins can await inside - for example calling an upstream auth or feature-flag service - before the rest of the request pipeline runs.

The hook still runs on the same worker thread it started on and is never moved across threads, so the returned future does not need to be Send.

Update any plugin that overrides on_http_request to return a boxed future:

// Before
fn on_http_request<'req>(
    &self,
    payload: OnHttpRequestHookPayload<'req>,
) -> OnHttpRequestHookResult<'req> {
    self.record_request(&payload);
    payload.proceed()
}

// After
fn on_http_request<'req>(
    &'req self,
    payload: OnHttpRequestHookPayload<'req>,
) -> OnHttpRequestHookFuture<'req> {
    Box::pin(async move {
        self.record_request(&payload);
        payload.proceed()
    })
}

If the body reads self inside the async move block, &self needs to become &'req self - the future now holds that borrow for its own lifetime 'req, so the borrow has to be able to live at least that long.

Plugins that don't override on_http_request are unaffected.

See plugin_examples/async_http_fetch for an example that awaits an upstream HTTP call before proceeding.

hive-router-internal 0.1.0 (2026-08-13)

Choose a tag to compare

@knope-bot knope-bot released this 13 Aug 13:29
32b6f84

Breaking Changes

Fix missing demand control metrics names

Previously added metrics names were missing the hive.router.demand_control. prefix. This has been fixed in this change.

Here's a list of the metrics that have been fixed:

  • cost.estimated -> hive.router.demand_control.cost.estimated
  • cost.actual -> hive.router.demand_control.cost.actual
  • cost.delta -> hive.router.demand_control.cost.delta

hive-router 0.0.89 (2026-08-12)

Choose a tag to compare

@knope-bot knope-bot released this 12 Aug 13:39
69752b7

Features

Multiplex and reuse WebSocket subgraph connections

The router can now multiplex GraphQL operations over shared graphql-transport-ws subgraph connections.

Subscriptions with the same subgraph and inbound connection identity reuse one initialized connection instead of opening one WebSocket per operation. Different operations retain independent streams while sharing the physical connection.

Queries and mutations can also reuse a connection opened by a subscription:

subscriptions:
  enabled: true
  websocket:
    subgraphs:
      reviews:
        path: /reviews/ws

traffic_shaping:
  all:
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

With this configuration:

  1. A subscription initializes the pooled reviews connection.
  2. Matching subscriptions multiplex over it.
  3. Matching queries and mutations use it while it remains initialized.
  4. A query or mutation uses HTTP when the connection is missing, expired, or still initializing.

Use WebSocket for every operation by selecting websocket mode:

traffic_shaping:
  all:
    websocket:
      reuse_connections: true
      execute_mode: websocket

The first operation initializes the connection, concurrent operations join that initialization, and later matching operations reuse the initialized connection.

Once an operation selects WebSocket, transport failures and timeouts are returned to the client without retrying over HTTP. This prevents a mutation that may have reached the subgraph from being executed twice.

Idle pooled connections close after the effective pool_idle_timeout. Active operations keep the connection open, and dropping one operation cancels only that operation without closing the shared connection.

The router also exposes WebSocket pool telemetry for active connections and operations, initialization success and failure, initialization waiters, reuse lookup hits and misses, and connection closure reasons. These metrics help measure reuse hit rate, multiplexing, connection churn, handshake failures, and per-subgraph pool usage.

Fixes

Add WebSocket connection reuse and execution mode configuration

WebSocket-enabled subgraphs can now configure connection reuse and choose how queries and mutations are transported.

Configure defaults for all subgraphs under traffic_shaping.all.websocket:

subscriptions:
  enabled: true
  websocket:
    subgraphs:
      reviews:
        path: /reviews/ws

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

reuse_connections defaults to true:

  • true multiplexes matching operations over initialized pooled WebSocket connections
  • false opens a dedicated connection for each WebSocket operation

execute_mode defaults to http and supports:

  • http: queries and mutations always use HTTP
  • reuse_existing: queries and mutations use an initialized matching WebSocket when available, otherwise they immediately use HTTP
  • websocket: queries and mutations use WebSocket, creating or joining a pooled connection when reuse is enabled

Settings can be overridden per subgraph. Omitted WebSocket fields inherit the global value:

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

  subgraphs:
    payments:
      pool_idle_timeout: 5s
      websocket:
        reuse_connections: false
        execute_mode: websocket

In this example, other WebSocket-enabled subgraphs opportunistically reuse initialized connections. payments sends each operation over a dedicated WebSocket.

Pooled WebSockets use the effective pool_idle_timeout. A per-subgraph value overrides traffic_shaping.all.pool_idle_timeout for both HTTP and WebSocket pools. Active WebSocket operations do not expire.

Connection matching uses the inbound headers selected by traffic_shaping.router.dedupe.headers, even when router request deduplication is disabled. Include every header that can affect connection-scoped authentication, authorization, cookies, or tenant identity:

traffic_shaping:
  router:
    dedupe:
      headers:
        include: [authorization, cookie, x-tenant]

Improve variable coercion error messages

Variable coercion errors (invalid scalar/enum/object values, missing required fields, non-null violations) reports clear and informative error messages.

This only changes error text - error codes and HTTP status codes are unchanged.

Fix doubled _total suffix on Prometheus counters

The built-in Prometheus metrics exporter (/metrics) generated counter names with a
doubled suffix, e.g. hive_router_graphql_errors_total_total instead of
hive_router_graphql_errors_total.

Counter names on /metrics now end in a single _total, matching standard
Prometheus conventions.

OTLP metrics exporter is not affected.

Mask internal error details from client responses

Improve router's error handling by masking internal error details from client responses.

Client-caused errors still return their real message, since it only ever reflects the client's own request. Internal errors now always return a generic "Internal server error" message and never the underlying error message, which previously leaked details such as subgraph URLs, storage/network errors, and other backend internals. The real error is still logged for debugging purposes.

Error codes are unchanged. HTTP status codes are unchanged, except for GraphQL operation normalization and minification failures, which are now correctly treated as router-side bugs and always return 500 (previously 400, or 200 based on Accept header) instead of being treated as a client mistake.

Propagate all multi-instance headers from a single subgraph response

When a subgraph responded with multiple instances of a never-join header (Set-Cookie or WWW-Authenticate), the router only forwarded one of them to the client and silently dropped the rest.

The fix is to propagate all values of a never-join header as separate header fields end-to-end, rather than just the first value.

Fixes #1388

Upgrade Laboratory to latest (v0.2.4)

Upgrade Laboratory to latest version (@graphql-hive/laboratory@0.2.4). This release includes the following changes:

  • Schema documentation: browse root types, types and fields, search across the whole type map (including input objects and enum values), and read descriptions, deprecations and argument defaults.
  • Builder rows gain an "Open in Docs" context menu entry, and the GraphQL editor hover gains an "Open in Docs" link.

hive-router-plan-executor 7.0.4 (2026-08-12)

Choose a tag to compare

@knope-bot knope-bot released this 12 Aug 13:39
69752b7

Fixes

Add WebSocket connection reuse and execution mode configuration

WebSocket-enabled subgraphs can now configure connection reuse and choose how queries and mutations are transported.

Configure defaults for all subgraphs under traffic_shaping.all.websocket:

subscriptions:
  enabled: true
  websocket:
    subgraphs:
      reviews:
        path: /reviews/ws

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

reuse_connections defaults to true:

  • true multiplexes matching operations over initialized pooled WebSocket connections
  • false opens a dedicated connection for each WebSocket operation

execute_mode defaults to http and supports:

  • http: queries and mutations always use HTTP
  • reuse_existing: queries and mutations use an initialized matching WebSocket when available, otherwise they immediately use HTTP
  • websocket: queries and mutations use WebSocket, creating or joining a pooled connection when reuse is enabled

Settings can be overridden per subgraph. Omitted WebSocket fields inherit the global value:

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

  subgraphs:
    payments:
      pool_idle_timeout: 5s
      websocket:
        reuse_connections: false
        execute_mode: websocket

In this example, other WebSocket-enabled subgraphs opportunistically reuse initialized connections. payments sends each operation over a dedicated WebSocket.

Pooled WebSockets use the effective pool_idle_timeout. A per-subgraph value overrides traffic_shaping.all.pool_idle_timeout for both HTTP and WebSocket pools. Active WebSocket operations do not expire.

Connection matching uses the inbound headers selected by traffic_shaping.router.dedupe.headers, even when router request deduplication is disabled. Include every header that can affect connection-scoped authentication, authorization, cookies, or tenant identity:

traffic_shaping:
  router:
    dedupe:
      headers:
        include: [authorization, cookie, x-tenant]

Improve variable coercion error messages

Variable coercion errors (invalid scalar/enum/object values, missing required fields, non-null violations) reports clear and informative error messages.

This only changes error text - error codes and HTTP status codes are unchanged.

Propagate all multi-instance headers from a single subgraph response

When a subgraph responded with multiple instances of a never-join header (Set-Cookie or WWW-Authenticate), the router only forwarded one of them to the client and silently dropped the rest.

The fix is to propagate all values of a never-join header as separate header fields end-to-end, rather than just the first value.

Fixes #1388

hive-router-internal 0.0.42 (2026-08-12)

Choose a tag to compare

@knope-bot knope-bot released this 12 Aug 13:39
69752b7

Fixes

Add WebSocket connection reuse and execution mode configuration

WebSocket-enabled subgraphs can now configure connection reuse and choose how queries and mutations are transported.

Configure defaults for all subgraphs under traffic_shaping.all.websocket:

subscriptions:
  enabled: true
  websocket:
    subgraphs:
      reviews:
        path: /reviews/ws

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

reuse_connections defaults to true:

  • true multiplexes matching operations over initialized pooled WebSocket connections
  • false opens a dedicated connection for each WebSocket operation

execute_mode defaults to http and supports:

  • http: queries and mutations always use HTTP
  • reuse_existing: queries and mutations use an initialized matching WebSocket when available, otherwise they immediately use HTTP
  • websocket: queries and mutations use WebSocket, creating or joining a pooled connection when reuse is enabled

Settings can be overridden per subgraph. Omitted WebSocket fields inherit the global value:

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

  subgraphs:
    payments:
      pool_idle_timeout: 5s
      websocket:
        reuse_connections: false
        execute_mode: websocket

In this example, other WebSocket-enabled subgraphs opportunistically reuse initialized connections. payments sends each operation over a dedicated WebSocket.

Pooled WebSockets use the effective pool_idle_timeout. A per-subgraph value overrides traffic_shaping.all.pool_idle_timeout for both HTTP and WebSocket pools. Active WebSocket operations do not expire.

Connection matching uses the inbound headers selected by traffic_shaping.router.dedupe.headers, even when router request deduplication is disabled. Include every header that can affect connection-scoped authentication, authorization, cookies, or tenant identity:

traffic_shaping:
  router:
    dedupe:
      headers:
        include: [authorization, cookie, x-tenant]

hive-router-config 0.1.12 (2026-08-12)

Choose a tag to compare

@knope-bot knope-bot released this 12 Aug 13:39
69752b7

Features

Add WebSocket connection reuse and execution mode configuration

WebSocket-enabled subgraphs can now configure connection reuse and choose how queries and mutations are transported.

Configure defaults for all subgraphs under traffic_shaping.all.websocket:

subscriptions:
  enabled: true
  websocket:
    subgraphs:
      reviews:
        path: /reviews/ws

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

reuse_connections defaults to true:

  • true multiplexes matching operations over initialized pooled WebSocket connections
  • false opens a dedicated connection for each WebSocket operation

execute_mode defaults to http and supports:

  • http: queries and mutations always use HTTP
  • reuse_existing: queries and mutations use an initialized matching WebSocket when available, otherwise they immediately use HTTP
  • websocket: queries and mutations use WebSocket, creating or joining a pooled connection when reuse is enabled

Settings can be overridden per subgraph. Omitted WebSocket fields inherit the global value:

traffic_shaping:
  all:
    pool_idle_timeout: 50s # default
    websocket:
      reuse_connections: true
      execute_mode: reuse_existing

  subgraphs:
    payments:
      pool_idle_timeout: 5s
      websocket:
        reuse_connections: false
        execute_mode: websocket

In this example, other WebSocket-enabled subgraphs opportunistically reuse initialized connections. payments sends each operation over a dedicated WebSocket.

Pooled WebSockets use the effective pool_idle_timeout. A per-subgraph value overrides traffic_shaping.all.pool_idle_timeout for both HTTP and WebSocket pools. Active WebSocket operations do not expire.

Connection matching uses the inbound headers selected by traffic_shaping.router.dedupe.headers, even when router request deduplication is disabled. Include every header that can affect connection-scoped authentication, authorization, cookies, or tenant identity:

traffic_shaping:
  router:
    dedupe:
      headers:
        include: [authorization, cookie, x-tenant]

hive-router 0.0.88 (2026-08-10)

Choose a tag to compare

@knope-bot knope-bot released this 10 Aug 10:05
baf8056

Features

Add apollo_graphos supergraph source

Adds a new apollo_graphos supergraph source that fetches the supergraph schema from Apollo GraphOS's managed federation Uplink, for routers migrating from Apollo Router/Gateway without needing a separate schema-delivery pipeline.

Configure it with graph_ref and key (or the APOLLO_GRAPH_REF/APOLLO_KEY environment variables), and optionally endpoint (defaults to Apollo's GCP and AWS Uplink endpoints, tried in order), timeout and accept_invalid_certs.

Closes #505

Expose log correlation to the plugin system

Plugins can now attach a custom correlation (e.g. a tenant or project ID) to every log line of the current request via hive_router::set_log_correlation(key, value), callable from any hook, alongside the built-in request_id and trace_id.

Fixes #1350

Expose the request summary to the plugin system

Plugins can now enrich the request summary log line with custom attributes via hive_router::set_summary_attribute(key, value), callable from any hook (e.g. on_http_request, on_graphql_analysis).

Fixes #1368

Expose the summary message to the plugin system

Plugins can now override the request summary log line's message via hive_router::set_summary_message(message), callable from any hook.

Fixes #1378

Fixes

Report persistedDocumentHash in usage reports

Usage reports now include the resolved persisted document id, so Hive Console can match
requests to app deployments and populate their "Last used" data. Previously the router
resolved the document id but always omitted it from the usage report.

Closes #1343

hive-router-plan-executor 7.0.3 (2026-08-10)

Choose a tag to compare

@knope-bot knope-bot released this 10 Aug 10:05
baf8056

Fixes

Add apollo_graphos supergraph source

Adds a new apollo_graphos supergraph source that fetches the supergraph schema from Apollo GraphOS's managed federation Uplink, for routers migrating from Apollo Router/Gateway without needing a separate schema-delivery pipeline.

Configure it with graph_ref and key (or the APOLLO_GRAPH_REF/APOLLO_KEY environment variables), and optionally endpoint (defaults to Apollo's GCP and AWS Uplink endpoints, tried in order), timeout and accept_invalid_certs.

Closes #505

Expose log correlation to the plugin system

Plugins can now attach a custom correlation (e.g. a tenant or project ID) to every log line of the current request via hive_router::set_log_correlation(key, value), callable from any hook, alongside the built-in request_id and trace_id.

Fixes #1350

Expose the request summary to the plugin system

Plugins can now enrich the request summary log line with custom attributes via hive_router::set_summary_attribute(key, value), callable from any hook (e.g. on_http_request, on_graphql_analysis).

Fixes #1368

Expose the summary message to the plugin system

Plugins can now override the request summary log line's message via hive_router::set_summary_message(message), callable from any hook.

Fixes #1378