Skip to main content

GraphQL Gateway

The GraphQL gateway is the single entry point for all frontend GraphQL traffic. It composes six domain subgraphs into one federated supergraph using Apollo Gateway, runs on Fastify, and handles cross-cutting concerns like authentication, caching, and observability.

Stack

ComponentVersion
Apollo Gateway2.11.2
Apollo Server5.0.0
Fastify5.6.0
GraphQL Hive0.40.0

Supergraph composition

The gateway loads its supergraph schema from one of two sources:

  • Production: Hive CDN, polling for updates every 15 seconds
  • Development: a local supergraph.generated.graphql file

Hive CDN is activated when both HIVE_CDN_ENDPOINT and HIVE_CDN_ACCESS_TOKEN are set. Otherwise the gateway falls back to the local file.

Two composition profiles ship with the platform, differing only in which CMS subgraph they include:

ProfileFile
Contentfulsupergraphs/commercetools-contentful.yaml
Storybloksupergraphs/commercetools-storyblok.yaml

Subgraphs

SubgraphDefault dev URLDomain
accounthttp://localhost:4001/graphqlAuthentication & customer data
cataloghttp://localhost:4002/graphqlProducts, categories, search
checkouthttp://localhost:4003/graphqlCart, orders, payments
cmshttp://localhost:4004/graphqlCMS content (Contentful or Storyblok)
orderhttp://localhost:4005/graphqlOrder history & management
quoteshttp://localhost:4006/graphqlB2B quote requests

Endpoints

PathMethodPurpose
/graphqlPOSTMain GraphQL endpoint
/auth/graphqlPOSTGraphQL with refresh-token cookie path
/healthcheckGETReturns {"status": "OK"}

The /auth/graphql endpoint exists for cookie path separation. The refresh-token cookie is scoped to /auth/graphql so it is never sent on regular queries, reducing request size and limiting exposure.

Authentication

The gateway handles all token lifecycle management: reading tokens from cookies or headers, propagating them to subgraphs, and writing updated tokens back. It also provides the @requiresSession directive that creates anonymous sessions on the fly for first-time visitors.

See Authentication & tokens for the full details on token types, the session flow, and the @requiresSession directive.

Trusted documents

Persisted queries are enforced through @labdigital/apollo-trusted-documents. In production, only pre-registered query hashes are accepted. The document store is backed by Hive CDN with a local LRU cache (1 000 entries).

During development you can bypass the check by sending the X-TrustedDocument-BypassSecret header with the value from the TRUSTED_DOCUMENT_BYPASS_SECRET environment variable.

Caching

The gateway uses a KeyvAdapter backed by Keyv for Apollo's response cache. When REDIS_URL is set, the cache is backed by Redis. Without Redis, caching is effectively disabled (a no-op store is used). See Caching for how response caching interacts with the CDN layer.

Custom fetcher & retries

Subgraph requests use make-fetch-happen with custom retry logic:

  • Retries on 502 and 503 responses
  • Up to 6 retries with 250 ms base delay

Each retry is tracked with an OpenTelemetry span so you can see retry behaviour in traces.

CORS

In development the gateway allows requests from localhost:3000, localhost:4000, localhost:3010, and *.evolve.labdigital.nl. In production, set CORS_ORIGIN to a comma-separated list of allowed origin suffixes. Credentials are always included.

Observability

The gateway reports schema usage to GraphQL Hive when HIVE_TOKEN is set. A custom sampler guarantees every unique operation name is reported at least once per 24 hours, then samples at 10 % thereafter.

An ApolloObservabilityPlugin sets OpenTelemetry span attributes for graphql.operationName and graphql.query, and logs gateway-level errors while filtering out downstream subgraph errors. See Observability for the broader tracing setup.

Automatic Persisted Queries (APQ) are enabled for all subgraph connections to reduce bandwidth between the gateway and subgraphs.

Store context

The gateway extracts store context from incoming request headers and makes it available as a lazy-loaded value on the GraphQL context:

HeaderContext field
X-StoreContext-StoreKeystoreKey
X-StoreContext-Localelocale
X-StoreContext-Currencycurrency

The CustomRemoteGraphQLDataSource propagates these headers to every subgraph request. See Store context for how services consume and validate these values.

Environment variables

All variables use the GRAPHQL_GATEWAY_ prefix via @labdigital/enviconf.

VariableDefaultPurpose
COMPONENT_NAMEgraphql-gatewayService identifier
HTTP_HOST0.0.0.0Bind host
HTTP_PORT4000Bind port
COOKIE_DOMAINlocalhostCookie domain for auth tokens
JWT_ISSUERhttp://localhost:4000JWT issuer claim
JWT_AUDIENCEhttp://localhost:4000JWT audience claim
ACCOUNT_SERVICE_ENDPOINT(required)Account service URL for @requiresSession
REDIS_URLRedis connection for caching
HIVE_TOKENHive usage reporting token
HIVE_CDN_ENDPOINTHive CDN endpoint for supergraph
HIVE_CDN_ACCESS_TOKENHive CDN access token
TRUSTED_DOCUMENT_BYPASS_SECRETBypass persisted query enforcement
ENDPOINTSSubgraph URL overrides (object)
CORS_ORIGINlocalhost + *.evolve.labdigital.nlComma-separated allowed origins