Cloudflare GraphQL Firewall Rules
This demo shows how Cloudflare's WAF custom rules can inspect parsed GraphQL queries at the edge and block oversized or deeply-nested requests before they ever reach your origin Worker.
Active WAF Custom Rules
-- Rule 1: Block oversized queries (cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.parsed_successfully) -- Rule 2: Block deeply nested queries (cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)
1
Benign Query
2 fields, depth 2 - below both limits. Neither WAF rule fires.
Leaf Fields
2 <= 30
Query Depth
2 <= 7
WAF Decision
ALLOW
curl -X POST https://graphql.simmsp.com/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ user(id: \"42\") { id name } }"}'
ℹ
cf.api_gateway.graphql.query_size = 2 and cf.api_gateway.graphql.query_depth = 2. Neither rule threshold is met. The WAF passes the request through to the Worker.
2
Oversized Query (40 leaf fields)
Requests 40 fields in a single selection set - exceeds the 30-field threshold.
Leaf Fields
40 > 30
Query Depth
2 <= 7
WAF Rule
Rule 1 fires
curl -X POST https://graphql.simmsp.com/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ user(id: \"42\") { f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 f20 f21 f22 f23 f24 f25 f26 f27 f28 f29 f30 f31 f32 f33 f34 f35 f36 f37 f38 f39 f40 } }"}'
ℹ
cf.api_gateway.graphql.query_size = 40. Rule 1 (query_size > 30) matches. The WAF blocks at the edge - the Worker is never reached. Without the WAF rule, the Worker's own fallback catches it.
3
Deeply Nested Query (depth 10)
10 levels of nesting, 1 leaf field. Exceeds the depth-7 threshold.
Leaf Fields
1 <= 30
Query Depth
10 > 7
WAF Rule
Rule 2 fires
curl -X POST https://graphql.simmsp.com/graphql \
-H "Content-Type: application/json" \
-d '{"query":"{ a { b { c { d { e { f { g { h { i { j } } } } } } } } } }"}'
ℹ
cf.api_gateway.graphql.query_depth = 10. Rule 2 (query_depth > 7) matches. The WAF blocks at the edge - the Worker is never reached. Without the WAF rule, the Worker's own fallback catches it.
How the edge blocks these requests
Client
POST /graphql
->
Cloudflare Edge
Parse GraphQL
->
WAF Rule
Evaluate Fields + Depth
->
If rule matches
BLOCK (403)
->
If allowed
Worker / Origin
Cloudflare parses the GraphQL query body before your application code runs. The fields
cf.api_gateway.graphql.query_size and
cf.api_gateway.graphql.query_depth
are populated automatically when parsed_successfully is true.
No Worker code required for the blocking logic.
Configure the WAF rules on your zone
1
Enable GraphQL Inspection - In your Cloudflare dashboard go to Security > API Shield > Schema Validation and enable GraphQL parsing for your endpoint path (
/graphql).2
Create Rule 1 (oversized queries) - Go to Security > WAF > Custom Rules, action: Block.
(cf.api_gateway.graphql.query_size > 30 and cf.api_gateway.graphql.parsed_successfully)
3
Create Rule 2 (deep nesting) - Add a second rule, action: Block.
(cf.api_gateway.graphql.query_depth > 7 and cf.api_gateway.graphql.parsed_successfully)
4
Test with the buttons above - With both rules active, scenarios 2 and 3 return 403 at the Cloudflare edge. The Worker is never invoked. Without the rules, the Worker's own fallback guards enforce the same limits.