Skip to main content
Version: 3.9.x

Configure GraphQL Proxying

API7 Gateway can proxy GraphQL traffic like any other HTTP API. In environments where the GraphQL-aware plugins are available, you can also apply GraphQL-specific rate limiting and caching policies.

Prerequisites

  • An API7 Enterprise instance is running.
  • A Gateway Group is created and a Gateway instance is running.
  • A token from the Dashboard.

Basic GraphQL Proxying

Start with a standard HTTP route that forwards GraphQL requests to the upstream.

The following examples use https://countries.trevorblades.com/ as an upstream. When proxying to an HTTPS upstream that expects its own hostname, set scheme: https and pass_host: node.

adc.yaml
services:
- name: graphql-service
upstream:
scheme: https
pass_host: node
nodes:
- host: countries.trevorblades.com
port: 443
weight: 1
routes:
- name: graphql-route
uris:
- /graphql
methods:
- POST
adc sync -f adc.yaml

In the local validation environment, the basic Admin API example worked end to end after configuring the upstream with scheme: https and pass_host: node.

GraphQL Rate Limiting

The graphql-limit-count plugin provides GraphQL-aware rate limiting based on query depth.

Configure GraphQL Rate Limiting

Enable the graphql-limit-count plugin on a route that proxies to your GraphQL upstream. This plugin only supports the POST method.

This plugin requires additional fields beyond count, time_window, key_type, and key. At minimum, include policy. For example, the local policy uses policy: local.

curl -k "https://localhost:7443/apisix/admin/routes/graphql-limit-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "graphql-limit-route",
"paths": ["/graphql"],
"service_id": "graphql-service",
"methods": ["POST"],
"plugins": {
"graphql-limit-count": {
"count": 6,
"time_window": 60,
"rejected_code": 429,
"policy": "local",
"key_type": "var",
"key": "remote_addr"
}
}
}'

GraphQL Caching

The graphql-proxy-cache plugin provides GraphQL-aware caching for query operations while bypassing mutations.

Configure GraphQL Caching

Enable the graphql-proxy-cache plugin on your route.

In the local validation environment, both GraphQL-aware plugin configurations were validated end to end. graphql-limit-count returned 429 after the configured quota was exceeded, and graphql-proxy-cache returned Apisix-Cache-Status: MISS on the first request and Apisix-Cache-Status: HIT on the second identical request.

curl -k "https://localhost:7443/apisix/admin/routes/graphql-cache-route?gateway_group_id={gateway_group_id}" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"name": "graphql-cache-route",
"paths": ["/graphql"],
"service_id": "graphql-service",
"methods": ["POST"],
"plugins": {
"graphql-proxy-cache": {}
}
}'

Purge Cache

You can purge the cache for a specific GraphQL query by sending a DELETE request to the plugin's control endpoint.

curl -X DELETE http://localhost:9080/apisix/plugin/graphql-proxy-cache/*

Validate the Configuration

You can test the basic GraphQL proxying by sending a POST request with a GraphQL query.

curl -X POST http://localhost:9080/graphql \
-H "Content-Type: application/json" \
-d '{"query": "query { countries { code } }"}'

The gateway proxies the GraphQL request and returns the response from the upstream:

{"data":{"countries":[{"code":"AD"},{"code":"AE"}]}}

If graphql-limit-count is enabled with count: 6 and you repeat the following query four times, the first three requests should succeed and the fourth should return 429 Too Many Requests:

for i in $(seq 1 4); do
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:9080/graphql \
-H "Content-Type: application/json" \
-d '{"query":"query { continents { code } }"}'
done

If graphql-proxy-cache is enabled, repeat the same query twice and confirm the cache status headers:

curl -i -X POST http://localhost:9080/graphql \
-H "Content-Type: application/json" \
-d '{"query":"query { continents { code } }"}'

curl -i -X POST http://localhost:9080/graphql \
-H "Content-Type: application/json" \
-d '{"query":"query { continents { code } }"}'

The first response should include Apisix-Cache-Status: MISS and the second should include Apisix-Cache-Status: HIT.

Next Steps