# Limits

Source: https://capacms.com/docs/api/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`](https://capacms.com/docs/errors/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`](https://capacms.com/docs/errors/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`](https://capacms.com/docs/errors/count_unavailable) |
| Database time                                              | 5 seconds by default, for the whole request                                                           | [`query_timeout`](https://capacms.com/docs/errors/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](https://capacms.com/docs/api/graphql#limits), and how a document's cost is counted is in [Cost](https://capacms.com/docs/api/graphql#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`](https://capacms.com/docs/errors/rate_limit_exceeded); when the API is full of other projects' reads it is [`503 service_unavailable`](https://capacms.com/docs/errors/service_unavailable).
