---
title: "API Gateway for GraphQL: Federation, Proxying, and Best Practices"
description: "Learn how API gateways handle GraphQL APIs — from proxying and federation to rate limiting, security, and best practices for production."
canonicalUrl: "https://zuplo.com/learning-center/api-gateway-for-graphql"
pageType: "learning-center"
authors: "nate"
tags: "GraphQL, API Gateway, API Security"
image: "https://zuplo.com/og?text=API%20Gateway%20for%20GraphQL%3A%20Federation%2C%20Proxying%2C%20and%20Best%20Practices"
---
GraphQL gives frontend teams the power to request exactly the data they need —
no more over-fetching, no more chaining three REST calls to render a single
page. But that flexibility comes with a cost. A single GraphQL endpoint can
accept arbitrarily complex queries, which means authentication, rate limiting,
and abuse prevention all work differently than they do with REST. That is where
an API gateway comes in.

An API gateway for GraphQL sits between your clients and your GraphQL server (or
servers), enforcing security policies, managing traffic, and providing
observability — without requiring changes to your application code. Whether you
are running a single GraphQL service or stitching together a federated
supergraph, a gateway layer gives you the operational controls that production
APIs demand.

## Why GraphQL Needs an API Gateway

REST APIs expose discrete endpoints with predictable resource consumption. A
`GET /users/123` request always fetches roughly the same data. GraphQL is
different. A client can request a deeply nested query that fans out across
dozens of resolvers, or craft a query that fetches a few scalar fields. The
server cannot predict the cost of a request just by looking at the URL.

This creates several challenges that an API gateway is uniquely positioned to
solve:

- **Unpredictable query cost** — A malicious or careless client can send a query
  that consumes disproportionate backend resources. Without depth limiting and
  complexity analysis at the gateway, your origin server bears the full load.
- **Authentication at a single endpoint** — Unlike REST, where you can apply
  different auth rules per route, GraphQL typically exposes one `/graphql`
  endpoint. You need a centralized layer to verify tokens, API keys, or OAuth
  credentials before queries reach your resolvers.
- **Rate limiting by identity, not just IP** — GraphQL APIs need rate limiting
  that accounts for authenticated consumers, not just raw request counts. A
  gateway can tie rate limits to API keys or user identities across all queries.
- **Introspection control** — GraphQL's introspection system exposes your entire
  schema. In production, you likely want to disable or filter introspection to
  prevent attackers from mapping your data model.
- **Observability blind spots** — With one endpoint handling all traffic,
  traditional HTTP monitoring tools cannot distinguish between lightweight and
  expensive operations without GraphQL-aware instrumentation.

## How API Gateways Handle GraphQL

API gateways interact with GraphQL APIs in several ways, ranging from simple
proxying to full schema composition. The right approach depends on your
architecture and team structure.

### Query Proxying

The simplest pattern is transparent proxying. The gateway receives a GraphQL
request, applies policies (authentication, rate limiting, logging), and forwards
the request to your GraphQL server. The gateway does not need to understand your
schema — it treats the GraphQL endpoint like any other HTTP backend.

This is the most common starting point. You get gateway-level security and
traffic management without modifying your GraphQL server or schema.

### Schema Federation

Federation is an architectural pattern where multiple GraphQL services
(subgraphs) each own a portion of the overall schema. A gateway composes these
subgraphs into a single unified schema (the supergraph) that clients query
against.

[Apollo Federation](https://www.apollographql.com/docs/graphos/schema-design/federated-schemas/federation)
popularized this approach. Each subgraph extends shared types using directives
like `@key` and `@external`, and the gateway handles query planning — splitting
an incoming query across the relevant subgraphs and merging the results.

Federation works well for large organizations where separate teams own different
parts of the data graph. It does add operational complexity: you need a schema
registry, composition validation in CI/CD, and careful attention to
cross-service dependencies.

### Schema Stitching

Schema stitching predates federation and takes a different approach: the gateway
merges schemas from multiple GraphQL services by defining explicit relationships
between them at the gateway layer. Unlike federation, the individual services do
not need to be aware of each other or use special directives.

Some gateways, like Tyk, offer built-in stitching capabilities through features
like their Universal Data Graph, which can combine GraphQL and REST endpoints
into a unified GraphQL API without code changes to the underlying services.

### Persisted Queries

Persisted queries (also called trusted documents) let you register allowed
queries ahead of time and reference them by hash at runtime. The gateway only
executes pre-approved queries, which eliminates the risk of arbitrary query
injection and reduces payload sizes.

This pattern pairs well with gateway-level enforcement. The gateway can reject
any query that does not match a registered hash, providing a strong security
boundary.

## Key Gateway Features for GraphQL

Not every gateway feature maps cleanly to GraphQL. Here are the capabilities
that matter most for GraphQL workloads.

### Rate Limiting

Standard rate limiting counts requests per time window, but a single GraphQL
request can vary enormously in cost. Some specialized gateways (like Kong's
GraphQL Rate Limiting Advanced plugin) can rate limit based on query complexity
scoring. More commonly, gateways combine standard per-consumer rate limiting
with a separate complexity limit policy that rejects overly expensive queries
before they execute.

At a minimum, your gateway should support per-consumer rate limiting tied to
authenticated identities (API keys or JWT claims) so that each consumer gets a
fair share of your API capacity.

### Query Depth Limiting

Depth limiting restricts how many levels deep a query can nest. This is a
straightforward defense against recursive queries that could overload your
resolvers:

```graphql
{
  # Level 0
  user {
    # Level 1
    friends {
      # Level 2
      friends {
        # Level 3
        friends {
          # Level 4 — blocked by depth limit
          name
        }
      }
    }
  }
}
```

A depth limit of 5–10 is reasonable for most APIs. Setting it at the gateway
means your application code does not need to handle this concern.

### Query Complexity Analysis

Complexity analysis assigns a cost to each field and enforces a maximum total
cost per query. A simple scalar field might cost 1 point, while a list field
that triggers a database query might cost 10. The gateway sums the cost before
executing the query and rejects anything over the threshold:

```graphql
{
  users {
    # Complexity: 10 (list query)
    name # Complexity: 1
    email # Complexity: 1
    posts {
      # Complexity: 10 (nested list)
      title # Complexity: 1
      comments {
        # Complexity: 10 (nested list)
        body # Complexity: 1
      }
    }
  }
}
# Total complexity: 34
```

This is more nuanced than depth limiting and catches queries that are wide (many
fields) rather than deep.

### Introspection Control

GraphQL introspection lets clients query `__schema` and `__type` to discover
your API's entire type system. This is essential during development but can be a
security risk in production. A gateway should let you:

- **Disable introspection entirely** for public-facing endpoints
- **Filter introspection responses** to hide internal types and sensitive fields
  while still exposing the public schema

### Authentication and Authorization

The gateway is the natural place to enforce authentication for GraphQL APIs. API
key validation, JWT verification, and OAuth token introspection all happen
before the request reaches your GraphQL server. This means your resolvers can
focus on data fetching, not credential validation.

Field-level authorization is a trickier problem. While some gateways support it
natively, many teams handle field-level permissions in their resolver logic or
through GraphQL directives. The gateway handles coarse-grained access (is this
consumer allowed to call the API at all?), and the application handles
fine-grained access (can this user see this specific field?).

## GraphQL Federation at the Gateway Layer

Federation has become the dominant architecture for large-scale GraphQL
deployments. Understanding how it works at the gateway layer helps you evaluate
whether you need a dedicated GraphQL gateway or can use a general-purpose API
gateway.

### How Federation Works

In a federated architecture, each team owns a subgraph that defines its portion
of the schema. A composition step (typically in CI/CD) validates that all
subgraphs are compatible and produces a supergraph schema. The gateway uses this
supergraph to plan and execute queries across subgraphs.

For example, a `User` type might be defined in a users subgraph, while `Order`
is defined in an orders subgraph. When a client queries for a user's orders, the
gateway fetches the user from one subgraph and the orders from another, then
merges the results.

If you are running a federated architecture, you will need to decide between a
dedicated GraphQL gateway (like the Apollo Router) that handles query planning
natively, or a general-purpose API gateway that provides security and traffic
management at the edge. Many organizations use both — see
[Comparing Gateway Approaches](#comparing-gateway-approaches) below for a
detailed breakdown, including the
[defense-in-depth approach recommended by Apollo](https://www.apollographql.com/docs/graphos/routing/router-api-gateway-comparison).

## REST-to-GraphQL at the Gateway

One common use case is wrapping existing REST APIs with a GraphQL interface at
the gateway layer. Instead of rewriting your backend services, the gateway
translates incoming GraphQL queries into REST calls and assembles the results.

This approach lets you offer a GraphQL API to consumers without changing your
existing services. It is particularly useful when migrating incrementally from
REST to GraphQL, or when you want to provide a unified GraphQL interface over
multiple REST backends.

Some gateways handle this translation natively. Others, like Zuplo, focus on
proxying and securing your GraphQL endpoints while providing the tooling to
connect REST and GraphQL APIs within the same gateway. For a detailed
walkthrough of this pattern, see
[How to Access a REST API Through GraphQL](/learning-center/how-to-access-a-rest-api-through-graphql).

## Security Checklist for GraphQL at the Gateway

GraphQL's flexibility makes it a larger attack surface than typical REST APIs.
Here is a quick checklist of the security controls your gateway should enforce —
each maps back to the features covered in
[Key Gateway Features for GraphQL](#key-gateway-features-for-graphql) above.

- **Disable or filter introspection in production** — Prevent attackers from
  mapping your schema. Use an introspection filter if trusted partners need
  partial schema access.
- **Enforce depth and complexity limits** — Depth limits catch recursive abuse;
  complexity limits catch wide, resource-intensive queries. Apply both.
- **Validate inputs at the gateway** — Reject requests with invalid GraphQL
  variables or unexpected fields before they reach your resolvers.
- **Use persisted queries for public APIs** — Limit execution to pre-approved
  query hashes, effectively turning your GraphQL API into a fixed set of
  operations while keeping the schema-driven development experience.
- **Require authentication on all GraphQL routes** — The gateway should verify
  API keys, JWTs, or OAuth tokens before any query reaches your server.

## How Zuplo Handles GraphQL APIs

[Zuplo](https://zuplo.com) is an edge-native API gateway that provides a
comprehensive set of policies for securing and managing GraphQL APIs alongside
REST endpoints. Rather than reimplementing GraphQL at the gateway layer, Zuplo
focuses on what gateways do best: security, traffic management, and developer
experience.

### GraphQL Security Policies

Zuplo offers three dedicated GraphQL policies:

- **[GraphQL Complexity Limit](https://zuplo.com/docs/policies/graphql-complexity-limit-inbound)**
  — Enforces both depth limits and complexity scoring on incoming queries. You
  configure a maximum depth and a maximum complexity score, and the gateway
  rejects queries that exceed either threshold.
- **[GraphQL Disable Introspection](https://zuplo.com/docs/policies/graphql-disable-introspection-inbound)**
  — Blocks introspection queries (`__schema` and `__type`) with a 403 response.
  Apply it to production routes while keeping introspection available in
  development environments.
- **[GraphQL Introspection Filter](https://zuplo.com/docs/policies/graphql-introspection-filter-outbound)**
  — Selectively hides types and fields from introspection responses. Useful when
  you want to expose a subset of your schema to external consumers while keeping
  internal types hidden.

### Rate Limiting and Authentication

Zuplo's [rate limiting](https://zuplo.com/docs/policies/rate-limit-inbound)
works with GraphQL endpoints the same way it works with REST. You can rate limit
by IP address, authenticated user, API key, or a custom function that inspects
any property of the request. Multiple rate limiting policies can stack — for
example, a broad hourly limit combined with a tighter per-minute burst limit.

Authentication policies including API key validation, JWT verification, and
OAuth support all apply transparently to your GraphQL routes. Configure them
once in the gateway, and every query to your `/graphql` endpoint is
authenticated before reaching your server.

### GraphQL Proxying at the Edge

Zuplo deploys to over 300 data centers worldwide using its edge-native
architecture. For GraphQL APIs, this means the gateway's security policies
(authentication, rate limiting, introspection control) execute at the edge
closest to your users, reducing latency for policy enforcement.

Setting up a GraphQL proxy in Zuplo is straightforward. You create a route that
forwards to your GraphQL backend using the URL rewrite or forward handler:

```json
{
  "paths": {
    "/graphql": {
      "post": {
        "operationId": "graphql-proxy",
        "x-zuplo-route": {
          "handler": {
            "export": "urlRewriteHandler",
            "module": "$import(@zuplo/runtime)",
            "options": {
              "rewritePattern": "https://api.example.com/graphql"
            }
          },
          "policies": {
            "inbound": [
              "api-key-auth",
              "rate-limit",
              "graphql-complexity-limit"
            ]
          }
        }
      }
    }
  }
}
```

### Developer Portal and Documentation

Zuplo automatically generates a developer portal from your OpenAPI
specification. GraphQL endpoints appear alongside REST routes, and consumers can
discover your API and manage their API keys from a single portal. This unified
experience is valuable for teams that operate mixed API architectures where
GraphQL and REST coexist.

### GraphQL-to-MCP Server

Zuplo also supports exposing GraphQL APIs as
[Model Context Protocol (MCP) servers](https://zuplo.com/docs/mcp-server/graphql),
enabling AI assistants to discover and query your GraphQL schema automatically.
The gateway generates introspection and execution tools that AI agents can use
to interact with your GraphQL API — with all the same authentication and rate
limiting policies applied.

## Comparing Gateway Approaches

There are two broad categories of gateways for GraphQL: dedicated GraphQL
gateways and general-purpose API gateways with GraphQL support. Each has
trade-offs.

### Dedicated GraphQL Gateways

Tools like the Apollo Router and Grafbase are purpose-built for GraphQL. They
excel at federation, query planning, and schema composition. If your entire API
surface is GraphQL and you are running a federated supergraph, these tools
provide the deepest integration.

The trade-off is specialization. Dedicated GraphQL gateways do not manage REST
APIs, gRPC services, or other protocols. You will need a separate gateway (or no
gateway at all) for non-GraphQL traffic.

### General-Purpose API Gateways

General-purpose gateways handle GraphQL alongside REST, gRPC, and other
protocols, giving you a single control plane for your entire API surface. Among
these, Zuplo stands out for GraphQL workloads with purpose-built policies,
edge-native deployment across 300+ data centers, and a built-in developer portal
— all without the operational overhead of managing plugins or infrastructure.

Zuplo ships dedicated GraphQL policies for complexity limiting, introspection
control, and schema filtering out of the box. Combined with first-class API key
management, JWT authentication, and automatic developer portal generation, Zuplo
is the fastest path from a GraphQL endpoint to a production-ready, fully-managed
API.

Other general-purpose options include Kong, which handles GraphQL through
separate plugins for validation and caching, and Tyk, which offers a Universal
Data Graph feature for stitching GraphQL and REST sources together. Both are
capable but require more configuration and infrastructure management compared to
Zuplo's hosted, edge-native approach.

For a broader comparison of API management platforms, including their GraphQL
capabilities, see
[Best API Management Platforms for Developers (2026)](/learning-center/best-api-management-platforms-2026).

### The Hybrid Approach

Many production architectures use both. A general-purpose API gateway sits at
the edge, handling authentication, rate limiting, and observability for all
traffic. Behind it, a dedicated GraphQL gateway handles federation query
planning and subgraph routing. This gives you the best of both worlds:
consistent edge-level policies and deep GraphQL-specific optimization.

## Best Practices for GraphQL at the Gateway

Choosing the right architecture depends on your team size, API complexity, and
operational requirements. Here are guidelines for common scenarios.

### Start with Proxying

If you have a single GraphQL server, a proxy gateway that adds authentication,
rate limiting, and introspection control is all you need. Do not introduce
federation or stitching until your team structure demands it.

### Add Complexity Limits Early

Query complexity abuse is the most common GraphQL-specific operational issue.
Configure depth and complexity limits at the gateway before your first
production deployment, not after an incident.

### Keep Authentication at the Gateway

Do not duplicate authentication logic in your GraphQL resolvers. Let the gateway
verify credentials and pass the authenticated identity to your server via
headers or context.

### Use the Gateway for Observability

The gateway sees every request before it reaches your server. Use it to log
query patterns, track per-consumer usage, and alert on unusual traffic — all
without instrumenting your application code.

### Evaluate Federation Honestly

Federation solves an organizational problem (multiple teams contributing to a
shared graph), not a technical one. If your team is small or you have a single
GraphQL service, federation adds complexity without meaningful benefit.

### Secure the Surface Area

Disable introspection in production, enforce persisted queries for public APIs,
and apply depth and complexity limits. GraphQL exposes more surface area than
REST by default, so layer your defenses.

## Getting Started

Ready to secure your GraphQL API with an edge-native gateway?
[Sign up for Zuplo](https://portal.zuplo.com/signup) to get started in minutes,
or explore these resources:

- [GraphQL Security Guide](https://zuplo.com/docs/articles/graphql-security) —
  Set up complexity limiting and introspection control for your GraphQL
  endpoints
- [GraphQL API Design Patterns](/learning-center/graphql-api-design) —
  Schema-level best practices for building production-grade GraphQL APIs
- [GraphQL MCP Server Example](https://zuplo.com/examples/mcp-server-graphql) —
  Expose a GraphQL API as an MCP server with authentication and rate limiting