| title | Router YAML Configuration Reference |
|---|---|
| subtitle | |
| description | Reference of YAML configuration properties for Apollo GraphOS Router and Apollo Router Core. |
import RouterYaml from '../../../shared/router-yaml-complete.mdx'; import RouterConfigTable from '../../../shared/router-config-properties-table.mdx';
import Apq from '../../../shared/config/apq.mdx'; import Authn from '../../../shared/config/authentication.mdx'; import Authz from '../../../shared/config/authorization.mdx'; import Batching from '../../../shared/config/batching.mdx'; import Connectors from '../../../shared/config/connectors.mdx'; import Coproc from '../../../shared/config/coprocessor.mdx'; import Cors from '../../../shared/config/cors.mdx'; import Csrf from '../../../shared/config/csrf.mdx'; import DemandCtrl from '../../../shared/config/demand_control.mdx'; import ExperimentalChaos from '../../../shared/config/experimental_chaos.mdx'; import ExperimentalHoistOrphan from '../../../shared/config/experimental_hoist_orphan_errors.mdx'; import ExperimentalType from '../../../shared/config/experimental_type_conditioned_fetching.mdx'; import FleetDetector from '../../../shared/config/fleet_detector.mdx'; import ForbidMut from '../../../shared/config/forbid_mutations.mdx'; import Headers from '../../../shared/config/headers.mdx'; import HealthChk from '../../../shared/config/health_check.mdx'; import Homepage from '../../../shared/config/homepage.mdx'; import IncludeSubErr from '../../../shared/config/include_subgraph_errors.mdx'; import LicenseEnf from '../../../shared/config/license_enforcement.mdx'; import Limits from '../../../shared/config/limits.mdx'; import OverrideSubUrl from '../../../shared/config/override_subgraph_url.mdx'; import PersistedQueries from '../../../shared/config/persisted_queries.mdx'; import Plugins from '../../../shared/config/plugins.mdx'; import PreviewEntityCache from '../../../shared/config/preview_entity_cache.mdx'; import ResponseCache from '../../../shared/config/response_cache.mdx'; import PreviewFileUploads from '../../../shared/config/preview_file_uploads.mdx'; import Rhai from '../../../shared/config/rhai.mdx'; import Sandbox from '../../../shared/config/sandbox.mdx'; import Server from '../../../shared/config/server.mdx'; import Subscription from '../../../shared/config/subscription.mdx'; import Supergraph from '../../../shared/config/supergraph.mdx'; import Telemetry from '../../../shared/config/telemetry.mdx'; import Tls from '../../../shared/config/tls.mdx'; import TrafficShaping from '../../../shared/config/traffic_shaping.mdx';
This reference covers the YAML configuration file properties for configuring an Apollo Router.
The router can be configured by a YAML configuration file. This file enables you to declaratively configure various runtime properties of your router's behavior.
At startup, you set the config file for your router by providing its path with the --config option:
./router --config router.yamlEnable your text editor to validate the format and content of your router YAML configuration file by configuring it with the router's configuration schema.
Expand the code block to view an example YAML config file containing all properties.
Learn more in Automatic Persisted Queries.
-
To learn about JWT authentication, go to JWT authentication in the GraphOS Router.
-
To learn about subgraph authentication with AWS SigV4, go to a subgraph authentication configuration example.
-
To configure authorization directives, see Authorization directives.
-
To configure the authorization plugin, see Configuration options.
Learn more in query batching.
Learn more in Working with router for Apollo Connectors.
Learn more in External coprocessing in the GraphOS Router.
By default, the router only allows GraphOS Studio to initiate browser connections to it. If your supergraph serves data to other browser-based applications, you need to update its Cross-Origin Resource Sharing (CORS) configuration.
Learn more in CORS.
Learn more in CSRF prevention in the router.
With demand control, the router analyzes the cost of operations and rejects requests with operations that exceed customizable cost limits.
Learn more in Demand Control
When the entity-resolution process for a subgraph returns errors that apply to multiple entities in a list, the router defaults to propagating each error to every matching entity path. That results in a multiplicative increase in the size of the returned error array.
The experimental_hoist_orphan_errors option changes that behavior on a per-subgraph basis. When enabled, the router attaches each orphaned subgraph error to a single parent path instead of duplicating the error across every entity path, which can significantly reduce the number of errors in the response.
The experimental_hoist_orphan_errors option isn't compliant with the GraphQL spec. The option changes how errors are associated with paths in the response, compared to the behavior described in the GraphQL specification. Only use the feature for your subgraphs when the reduction in error volume is more desirable than strict compliance.
To target a specific subgraph:
experimental_hoist_orphan_errors:
subgraphs:
my_subgraph:
enabled: trueTo target all subgraphs:
experimental_hoist_orphan_errors:
all:
enabled: trueTo target all subgraphs except one:
experimental_hoist_orphan_errors:
all:
enabled: true
subgraphs:
spec_compliant_one:
enabled: falsePer-subgraph settings override all.
Although the experimental_hoist_orphan_errors option can reduce the number of propagated errors, the option doesn't limit the total number of errors. If a subgraph returns a large number of errors, the router still processes all of them. For subgraphs that are likely to produce an unbounded number of errors, consider additional mitigation strategies at the subgraph level.
Learn more in Sending HTTP headers to subgraphs.
Learn more in Health Checks.
The router can serve a landing page to browsers that visit its endpoint path (supergraph.path):
-
A basic landing page that displays an example query
curlcommand (default)# This is the default behavior. You don't need to include this config. homepage: enabled: true
-
No landing page
homepage: enabled: false
-
Sending users to Apollo Explorer
homepage: graph_ref: my-org-graph@production
When you specify a
The `graph_ref` value should match the format `organization-name@variant-name`, which is the same format used with the `APOLLO_GRAPH_REF` environment variable. Note that the router does not automatically use the value from the `APOLLO_GRAPH_REF` environment variable for this setting - you must explicitly set `graph_ref` in your YAML configuration even if you're already using the environment variable.graph_ref, the router's landing page includes an option for users to redirect to Apollo Explorer. Users can check a box that will remember their preference and automatically redirect them to Explorer on subsequent visits.
Learn more in Request Limits.
By default, the router obtains the routing URL for each of your subgraphs from the composed supergraph schema you provide it. In most cases, no additional configuration is required. The URL can use HTTP and HTTPS for network access to subgraph, or have the following shape for Unix sockets usage: unix:///path/to/subgraph.sock
Unix socket paths should be absolute (starting with /). The URL format is unix:// followed by the absolute path, resulting in three slashes: unix:///var/run/subgraph.sock.
Because .sock is not required as a file extension, the router cannot determine if a path is appended to the base URL. Specify a custom HTTP path using the path query parameter:
override_subgraph_url:
my_subgraph: "unix:///tmp/subgraph.sock?path=/graphql/v1"This configuration also applies to subgraph URLs defined in your supergraph schema (using the url argument of the @join__graph directive).
However, if you do need to override a particular subgraph's routing URL (for example, to handle changing network topography), you can do so with the override_subgraph_url option:
override_subgraph_url:
organizations: http://localhost:8080
accounts: "${env.ACCOUNTS_SUBGRAPH_HOST_URL}"In this example, the organizations subgraph URL is overridden to point to http://localhost:8080, and the accounts subgraph URL is overridden to point to a new URL using variable expansion. The URL specified in the supergraph schema is ignored.
Any subgraphs that are omitted from override_subgraph_url continue to use the routing URL specified in the supergraph schema.
If you need to override the subgraph URL at runtime on a per-request basis, you can use request customizations in the SubgraphService layer.
You can enhance your graph's security with GraphOS Router by maintaining a persisted query list (PQL), an operation safelist made by your first-party apps. As opposed to automatic persisted queries (APQ) where operations are automatically cached, operations must be preregistered to the PQL. Once configured, the router checks incoming requests against the PQL.
Learn more about safelisting with persisted queries.
You can customize the router's behavior with plugins. Each plugin can have its own section in the configuration file with arbitrary values:
plugins:
example.plugin:
var1: "hello"
var2: 1Learn more in Native Plugins for router.
For new projects, Apollo recommends using Response Caching instead.
Learn more in Entity Caching.
Learn more in Response Caching.
Learn more in File Uploads.
Learn more in Rhai customization for router.
Apollo Sandbox is a GraphQL development environment. It runs a graph via introspection queries on the router's supergrpah schema, and it provides an IDE for making queries to the graph.
Running Sandbox in router requires configuring sandbox.enabled, supergraph.instrospection, and homepage.enabled:
sandbox:
enabled: true
# Sandbox uses introspection to obtain your router's schema.
supergraph:
introspection: true
# Sandbox requires the default landing page to be disabled.
homepage:
enabled: falseDo not enable Sandbox in production. Sandbox requires enabling introspection, which is strongly discouraged in production environments.
Learn more in Apollo Sandbox.
The header read timeout is the amount of time the Router will wait to receive the complete request headers from a client before timing out. It applies both when the connection is fully idle and when a request has been started but sending the headers has not been completed.
By default, the header read timeout is set to 10 seconds. A longer timeout can be configured using the server.http.header_read_timeout configuration option.
The TLS handshake timeout determines how long the router waits to complete a TLS handshake with a client.
The default timeout is ten seconds. You can configure the server.http.tls_handshake_timeout option to change this duration.
Learn more in Subscriptions.
As the gateway and single endpoint to your supergraph, an Apollo Router has a socket address and port that it listens for client requests. This listen address is configurable in YAML as supergraph.listen.
By default, the router starts an HTTP server that listens on 127.0.0.1:4000. You can specify a different address by setting supergraph.listen for IPv4, IPv6, or Unix sockets.
supergraph:
# The socket address and port to listen on (default: 127.0.0.1:400)
listen: 127.0.0.1:4000supergraph:
# The socket address and port to listen on. (default: [::1]:4000)
# Note that this must be quoted to avoid interpretation as an array in YAML.
listen: "[::1]:4000"supergraph:
# Absolute path to a Unix socket
listen: /tmp/router.sockListening on a Unix socket is not supported on Windows.
The path of the HTTP endpoint of the supergraph that the router runs is configured by supergraph.path.
By default, the router starts an HTTP server that exposes a POST/GET endpoint at path /.
supergraph:
# The path for GraphQL execution
# (Defaults to /)
path: /graphqlThe path must start with /.
A path can contain parameters and wildcards:
-
/{parameter}matches a single segment. For example:/abc/{my_param}/defmatches/abc/1/defand/abc/whatever/def, but it doesn't match/abc/1/2/defor/abc/def
-
/{*parameter}matches all segments in the rest of a path. For example:/abc/{*wildcard}matches/abc/1/defand/abc/w/h/a/t/e/v/e/r, but it doesn't match/abc/or/not_abc_at_all
-
Both parameters and wildcards require a name, even though you can’t use those names anywhere.
-
The router doesn't support wildcards in the middle of a path (e.g.,
/{*wild}/graphql). Instead, use a path parameter (e.g.,/{parameter}/graphql).
The router normalizes trailing slashes automatically. For example, if you configure the path as /graphql, the router accepts requests to both /graphql and /graphql/. This applies regardless of whether your configured path includes a trailing slash.
In GraphQL, introspection queries are used during development to learn about a GraphQL API's schema. The router can resolve introspection queries, based on the configuration of supergraph.introspection.
By default, the router doesn't resolve introspection queries.
To enable introspection queries during development, set the supergraph.introspection flag:
# Do not enable introspection in production!
supergraph:
introspection: trueThe schema-introspection schema is recursive: a client can query the fields of the types of some other fields, and so on arbitrarily deep. This can produce responses that grow much faster than the size of the request.
To prevent this, the router is configured by default to not execute introspection queries that nest list fields that are too deep, instead returning an error. The criteria matches MaxIntrospectionDepthRule in graphql-js, and it may change in future versions.
In case the router rejects legitimate queries, you can disable the limit by setting the limits.introspection_max_depth flag:
# Do not enable introspection in production!
supergraph:
introspection: true
limits:
router:
introspection_max_depth: falseQuery validation errors might reveal information about your schema structure, such as field names, types, and required arguments. Although this is not typically a significant security concern (especially with persisted queries), you can redact these error details in production environments.
Apollo Router returns detailed validation error messages by default. To redact validation errors and return a generic error message, set the supergraph.redact_query_validation_errors flag:
supergraph:
redact_query_validation_errors: trueWhen you enable this setting, Apollo Router replaces query validation errors with a single generic error:
{
"message": "invalid query",
"extensions": {
"code": "UNKNOWN_ERROR"
}
}Enabling this option will make debugging more difficult, as clients won't receive specific information about what's wrong with their queries. Consider enabling it only in production environments where schema details should remain private.
Up until Apollo Router Core v1.43.1, when the client closed the connection without waiting for the response, the entire request was cancelled and did not go through the entire pipeline. Since this causes issues with request monitoring, the router introduced a new behavior in 1.43.1. Now, the entire pipeline is executed if the request is detected as cancelled, but subgraph requests are not actually done. The response will be reported with the 499 status code, but not actually sent to the client.
To go back to the previous behavior of immediately cancelling the request, the following configuration can be used for supergraph.early_cancel:
supergraph:
early_cancel: trueAdditionally, since v1.43.1, the router can show a log when it detects that the client canceled the request. This log can be activated with:
supergraph:
experimental_log_on_broken_pipe: trueWhen the Router schema or configuration updates all connections must be closed for resources to be freed.
To ensure that long-lived connections do not hang on to resources, a maximum graceful shutdown timeout can be configured with supergraph.connection_shutdown_timeout:
supergraph:
connection_shutdown_timeout: 60sThe default value is 60 seconds.
Note that if early_cancel is false (default), then requests in progress will still hold onto pipeline resources.
In that case, traffic shaping request timeouts should be used to prevent long-running requests:
traffic_shaping:
router:
timeout: 60sBy default, the router compresses subgraph requests by generating fragment definitions based on the shape of the subgraph operation. In many cases this significantly reduces the size of the query sent to subgraphs.
Opt out of this behavior by specifying supergraph.generate_query_fragments:
supergraph:
generate_query_fragments: falseBy default, the router validates input variables strictly. It validates each input object value against its type definition, and any unknown fields result in a request error.
supergraph:
strict_variable_validation: enforceIf your implementation requires unknown fields on a defined type, you can opt out of stricter validation by specifying strict_variable_validation: measure.
In this case, the router will not error when encountering unknown fields, but will log the field for reference.
The router supports enhanced operation signature normalization in the following versions:
- General availability in v1.54.0 and later
- Experimental in v1.49.0 to v1.53.0
Apollo's legacy operation signature algorithm removes information about certain fields, such as input objects and aliases. This removal means some operations may have the same normalized signature though they are distinct operations.
Enhanced normalization incorporates input types and aliases in signature generation. It also includes other improvements that make it more likely that two operations that only vary slightly have the same signature.
Configure enhanced operation signature normalization in router.yaml with the telemetry.apollo.signature_normalization_algorithm option:
telemetry:
apollo:
signature_normalization_algorithm: enhanced # Default is legacyOnce you enable this configuration, operations with enhanced signatures might appear with different operation IDs than they did previously in GraphOS Studio.
Enhanced signatures include input object type shapes, while still redacting any actual values.
Legacy signatures replace input object type with {}.
Given the following example operation:
query InlineInputTypeQuery {
inputTypeQuery(
input: {
inputString: "foo"
inputInt: 42
inputBoolean: null
nestedType: { someFloat: 4.2 }
enumInput: SOME_VALUE_1
nestedTypeList: [{ someFloat: 4.2, someNullableFloat: null }]
listInput: [1, 2, 3]
}
) {
enumResponse
}
}The legacy normalization algorithm generates the following signature:
query InlineInputTypeQuery {
inputTypeQuery(input: {}) {
enumResponse
}
}The enhanced normalization algorithm generates the following signature:
query InlineInputTypeQuery {
inputTypeQuery(
input: {
inputString: ""
inputInt: 0
inputBoolean: null
nestedType: { someFloat: 0 }
enumInput: SOME_VALUE_1
nestedTypeList: [{ someFloat: 0, someNullableFloat: null }]
listInput: []
}
) {
enumResponse
}
}Enhanced signatures include any field aliases used in an operation. Legacy signatures remove aliases completely, meaning the signature may be invalid if the same field was used with multiple aliases.
Given the following example operation:
query AliasedQuery {
noInputQuery {
interfaceAlias1: interfaceResponse {
sharedField
}
interfaceAlias2: interfaceResponse {
... on InterfaceImplementation1 {
implementation1Field
}
... on InterfaceImplementation2 {
implementation2Field
}
}
inputFieldAlias1: objectTypeWithInputField(boolInput: true) {
stringField
}
inputFieldAlias2: objectTypeWithInputField(boolInput: false) {
intField
}
}
}The legacy normalization algorithm generates the following signature:
query AliasedQuery {
noInputQuery {
interfaceResponse {
sharedField
}
interfaceResponse {
... on InterfaceImplementation1 {
implementation1Field
}
... on InterfaceImplementation2 {
implementation2Field
}
}
objectTypeWithInputField(boolInput: true) {
stringField
}
objectTypeWithInputField(boolInput: false) {
intField
}
}
}The enhanced normalization algorithm generates the following signature:
query AliasedQuery {
noInputQuery {
interfaceAlias1: interfaceResponse {
sharedField
}
interfaceAlias2: interfaceResponse {
... on InterfaceImplementation1 {
implementation1Field
}
... on InterfaceImplementation2 {
implementation2Field
}
}
inputFieldAlias1: objectTypeWithInputField(boolInput: true) {
stringField
}
inputFieldAlias2: objectTypeWithInputField(boolInput: false) {
intField
}
}
}The router supports extended reference reporting in the following versions:
- General availability in v1.54.0 and later
- Experimental in v1.50.0 to v1.53.0
You can configure the router to report enum and input object references for enhanced insights and operation checks. Apollo's legacy reference reporting doesn't include data about enum values and input object fields, meaning you can't view enum and input object field usage in GraphOS Studio. Legacy reporting can also cause inaccurate operation checks.
Configure extended reference reporting in router.yaml with the telemetry.apollo.metrics_reference_mode option like so:
telemetry:
apollo:
metrics_reference_mode: extended # Default is legacyThe router supports extended error reporting in the following versions:
- Preview in v2.1.2 and later
- Experimental in v2.0.0
You can configure the router to report extended error information for improved diagnostics. Apollo's legacy error reporting doesn't include the service or error code, meaning you can't easily attribute errors to their root cause in GraphOS Studio.
Configure extended reference reporting in router.yaml with the telemetry.apollo.errors.preview_extended_error_metrics option like so:
telemetry:
apollo:
errors:
preview_extended_error_metrics: enabled # Default is disabledOnce you configure extended reference reporting, you can view enum value and input field usage alongside object field usage in GraphOS Studio for all subsequent operations.
Configuring extended reference reporting automatically turns on enhanced operation checks, though you won't see an immediate change in your operations check behavior.
This delay is because operation checks rely on historical operation data. To ensure sufficient data to distinguish between genuinely unused values and those simply not reported in legacy data, enhanced checks require some operations with extended reference reporting turned on.
Thanks to extended reference reporting, operation checks can more accurately flag issues for changes to enum values and input object fields. See the comparison table below for differences between standard operation checks based on legacy reference reporting and enhanced checks based on extended reference reporting.
|
Standard Check Behavior (Legacy reference reporting) |
Enhanced Check Behavior (Extended reference reporting) |
|
|---|---|---|
You can configure checks to ignore default values changes. |
You won't see an immediate change in checks behavior when you first turn on extended reference reporting. Learn more.
Learn more in TLS for the router.
Learn more in Traffic Shaping.
You can reference variables directly in your YAML config file. This is useful for referencing secrets without including them in the file.
Currently, the router supports expansion of environment variables and file paths. Corresponding variables are prefixed with env. and file., respectively.
The router uses Unix-style expansion. Here are some examples:
${env.ENV_VAR_NAME}expands to the value of environment variableENV_VAR_NAME.${env.ENV_VAR_NAME:-some_default}expands to the value of environment variableENV_VAR_NAME, or falls back to the valuesome_defaultif the environment variable is not defined.${file.a.txt}expands to the contents of the filea.txt.${file.a.txt:-some_default}expands to the contents of the filea.txt, or falls back to the valuesome_defaultif the file does not exist.
Variable expansions are valid only for YAML values, not keys.
You can reuse parts of your configuration file in multiple places using standard YAML aliasing syntax:
headers:
subgraphs:
products:
request:
- insert: &insert_custom_header
name: "custom-header"
value: "something"
reviews:
request:
- insert: *insert_custom_headerHere, the name and value entries under &insert_custom_header are reused under *insert_custom_header.
To include a literal $ character, double it as $$. The router converts each $$ to a single $:
- Config value:
prefix$$suffix - Result:
prefix$suffix