Limits
Every size, cost, rate and concurrency limit on /api/, REST and GraphQL, in one place.
Every limit is checked before any SQL runs, and a refusal states what the request measured and the limit it passed. REST and GraphQL share the read limits, so a page ported from one to the other keeps working.
Reads
| Limit | Value | Over it |
|---|---|---|
| Entries per request | 5,000, counted before SQL and held to as rows are read | query_too_complex |
| Levels of entries | 5, the root counted, so relations nest 4 deep below it | query_too_complex |
| Relation expansions | 12 per request on REST, per root field on GraphQL | query_too_complex |
Page size (limit, first) | 1 to 200, 25 by default | invalid_parameter |
A related list (limit: inside select, nested first) | up to 200, 100 by default, counted as 10 for each entry above it when not given | query_too_complex |
| Cost of a scan | 500 entries for each total, filter or sort through a relation, and each text condition past the first | query_too_complex |
| Sort keys | 3 | invalid_parameter |
| Conditions in one filter | 50, nested at most 8 deep | query_too_complex |
Values in one in, nin, hasAny or hasAll | 200 | query_too_complex |
Text conditions in one or | 3 contains, startsWith, endsWith or ne | query_too_complex |
Totals (count=true, totalCount) with a relation filter | the filter may match up to 50,000 entries | count_unavailable |
| Database time | 5 seconds by default, for the whole request | query_timeout |
GraphQL documents
| Limit | Value |
|---|---|
Document (query) | 32,768 bytes |
| Variables (JSON) | 32,768 bytes |
| POST body | 65,536 bytes |
| GET URL | 8,192 bytes |
| Depth | 8 levels; edges, node, nodes and pageInfo count zero |
| Bracket nesting | 128 levels |
| Entry root fields | 10 per operation |
Ids in one nodes(ids:) | 100 |
| Connections | 25 per operation |
| Selected fields | 1,000 |
| Fragments | 100 defined, 50 spread side by side |
| Introspection | __schema 1 time and __type 10 times per operation, 20 levels deep |
Every GraphQL limit, with the exact message and hint for each, is in GraphQL limits, and how a document's cost is counted is in Cost.
Reads running at once
4 per project, across all of its keys, GraphQL documents and /api/entries reads counted together, and at most 7 for the whole API process, so connections always stay free for key checks and health checks. The last of the 7 is kept for a project with no read running, so two busy projects never hold every slot. One client, by its address, runs at most 3 of its key's 4, so a caller flooding a site's public key never takes the slot its other visitors read with. Up to 64 more per client, and 256 per key, wait for a slot as long as the database budget. A client at its 3 or with 64 waiting, a key at its 4 or with 256 waiting, or a project whose keys have 4 running is told 429 rate_limit_exceeded; a key held off because the process was full of other projects' reads is told 503 service_unavailable. Each carries Retry-After: 1. A read whose caller hangs up is stopped at once, the statement running included
Up to 64 reads per client, and 256 per key, wait for a slot. Every refusal carries Retry-After: 1. Past a key's or a project's share the answer is 429 rate_limit_exceeded; when the API is full of other projects' reads it is 503 service_unavailable.