Octopus
1.x
Docs/Octopus/GraphQL
Open

Reading4 min
Updated31 Jul 2026
Sourcev1/protocols/graphql.mdx

GraphQL

The gateway ships a GraphQL-aware layer that fronts a GraphQL upstream. When enabled it parses each incoming operation, enforces depth/complexity/introspection policy, serves a real GraphiQL IDE, and proxies valid queries to your GraphQL backend through the normal routing, auth, rate-limit, and load-balancing pipeline.

Note

This is single-graph support: the gateway puts a policy and IDE layer in front of one GraphQL upstream per endpoint. Multi-subgraph federation (schema composition, query planning, cross-subgraph entity resolution) is on the roadmap, not yet available.

How it works01

The GraphQL layer runs as a middleware inside the request pipeline — after authentication and rate limiting, before the proxy. For a request to the configured endpoint it will:

  • Serve a real GraphiQL IDE for browser requests — a GET whose Accept contains text/html and which has no query= parameter. The IDE is configured to talk to the same endpoint.

  • Read the operation from a POST JSON body ({"query": "..."}) or from the query URL parameter on a GET.

  • Parse the operation with a spec-compliant GraphQL parser and reject malformed queries.

  • Enforce query-depth and complexity limits, and introspection policy.

  • For a valid operation, hand the request back to the pipeline so it is proxied to the upstream declared by the matching route — with the gateway's routing, auth, rate limiting, and load balancing applied.

Policy rejections return a GraphQL error envelope ({"errors":[{"message": "..."}]}) so GraphQL clients handle them normally.

Enabling it02

Add a graphql: block to the gateway config and declare a normal route for the endpoint pointing at your GraphQL upstream. The middleware adds parsing and policy enforcement on top of that route; the route itself does the routing and proxying.

graphql:
  enabled: true
  endpoint: /graphql        # path the GraphQL layer intercepts
  playground: true          # serve GraphiQL on GET /graphql (HTML Accept)
  introspection: true       # allow __schema / __type queries
  max_depth: 15             # reject operations nested deeper than this
  max_complexity: 1000      # reject operations selecting more fields than this

upstreams:
  - name: graphql-backend
    instances:
      - id: graphql-1
        host: 127.0.0.1
        port: 4000

routes:
  - path: /graphql
    methods: [GET, POST]
    upstream: graphql-backend

The layer is disabled by default (enabled: false); existing deployments are unaffected until you turn it on. If graphql.enabled is true but no route matches the endpoint path, a request to it returns the gateway's normal "route not found" response — the route is what supplies the upstream.

Configuration reference

FieldDefaultDescription
enabledfalseTurn the GraphQL-aware layer on.
endpoint/graphqlPath the layer intercepts. Other paths pass straight through.
playgroundtrueServe the GraphiQL IDE on an HTML GET to the endpoint.
introspectiontrueWhen false, operations selecting __schema/__type are rejected.
max_depth15Maximum selection nesting depth (root selection set = depth 1).
max_complexity1000Maximum number of selected fields (an approximate query cost).

Subscriptions03

GraphQL subscriptions are typically delivered over WebSocket (graphql-ws / graphql-transport-ws). The WebSocket proxy forwards the Sec-WebSocket-Protocol subprotocol, so a subscription endpoint can be proxied as a normal WebSocket route. See WebSocket.

Limitations04

  • Single-graph only. No schema composition, query planning, or cross-subgraph entity resolution yet — point the endpoint at one GraphQL upstream. (Federation is planned. The gateway's existing "federation" machinery is part of FARP service discovery, not GraphQL.)

  • Complexity is a field count. max_complexity approximates cost by counting selected fields; it is not type-weighted.

  • Fragment spreads aren't expanded for depth/complexity analysis (named fragments are not resolved against a schema at this stage); inline fragments are analyzed at their enclosing level.

  • No query batching or persisted queries (APQ) yet.

  • Only the exact endpoint path is intercepted. Subpaths (e.g. /graphql/foo) pass through as ordinary HTTP and are routed normally.

See also Routes, Routing, and HTTP/1.1 & HTTP/2.