> ## Documentation Index
> Fetch the complete documentation index at: https://unkey.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Unkey is two separate products. Compute builds, deploys, and runs apps behind a gateway. API Management issues API keys, enforces rate limits, manages identities and permissions, and reports usage. Say which product a page belongs to; a reader can use either without the other.
> Every Unkey API endpoint is an HTTP POST to https://api.unkey.com/v2/{service}.{procedure} with a root key in the Authorization: Bearer header. Root keys are workspace scoped.
> Error codes have the form err:{system}:{category}:{specific} and each has a page at /errors/{system}/{category}/{specific}.
> The word environment means production or preview in Compute. Rate limiting has four meanings on this site; the glossary lists them.

# Analytics restrictions and quotas

> The limits every analytics query runs under and the error each one returns.

Every analytics query runs under these limits. Most queries never hit them. When you do, find the error code here to see which limit you hit. For what SQL is allowed, see [Analytics query language](/docs/api-management/analytics/query-language).

## Query shape limits

These are checked before the query runs. Going over one returns HTTP 400, except nesting depth.

| Limit | Value | Error code |
| - | - | - |
| Query text | 16 KiB | `err:user:bad_request:invalid_analytics_query` |
| Projected columns across all `SELECT`s | 64 | `err:user:bad_request:invalid_analytics_query` ("Analytics query projects too many columns") |
| Query complexity (parsed expression nodes) | 2,000 | `err:user:bad_request:invalid_analytics_query` ("Analytics query is too complex") |
| Nesting depth | 100 | The query fails when it runs, not before |
| Statements | exactly one `SELECT` with `FROM` | `invalid_analytics_query` or `invalid_analytics_query_type` |
| Tables | public aliases only | `err:user:bad_request:invalid_analytics_table` |
| Functions | the allow-list | `err:user:bad_request:invalid_analytics_function` |

## Execution limits

These apply while the query runs. Hitting one returns HTTP 422.

| Limit | Value | Error code |
| - | - | - |
| Execution time | 10 seconds | `err:user:unprocessable_entity:query_execution_timeout` |
| Memory per query | 1 GB | `err:user:unprocessable_entity:query_memory_limit_exceeded` |
| Result rows | 10,000,000. Also applied as a `LIMIT` on every `SELECT`. | `err:user:unprocessable_entity:query_rows_limit_exceeded` |
| Encoded response size | 4 MiB | `err:user:unprocessable_entity:query_memory_limit_exceeded` ("Query result exceeds the maximum response size.") |

The 4 MiB response size is the limit people hit first. To stay under it, page with `LIMIT` and `OFFSET`, aggregate instead of selecting raw rows, or narrow the time window. `NaN` and infinity come back as `null`.

## Quota per workspace

By default, each workspace can run 1,000 queries and 1,800 seconds of total query time per rolling hour. Going over either returns HTTP 429 with `err:user:too_many_requests:query_quota_exceeded`. Wait for the window to roll over, or contact [support@unkey.com](mailto:support@unkey.com) if you need more.

## Retention

Queries only return rows inside your plan's log retention. If your time filter starts earlier than that, the query fails with HTTP 400 and `err:user:bad_request:query_range_exceeds_retention`, and the detail names the earliest date you can query. A filter written with `toIntervalDay(N)` instead of `INTERVAL N DAY` doesn't fail. It just leaves the older rows out. See [Working with time](/docs/api-management/analytics/query-language#working-with-time).

| Plan | Log retention |
| - | - |
| Free, no Compute plan | 1 day |
| API Pro, any tier | 7 days |
| Compute Starter | 3 days |
| Compute Pro | 7 days |
| Compute Business | 14 days |

Plans agreed with sales have their own retention. Your actual value is the `Log retention` row on **Settings > Limits**. See [Limits](/docs/platform/billing/limits).

Each table also has a maximum age, whatever your plan:

* **Verifications:** raw, per-minute, and per-hour 90 days; per-day 365 days; per-month 3 years.
* **Rate limits:** raw one month; per-minute 7 days; per-hour 30 days; per-day 100 days; per-month 3 years.

## Other errors

| Status | Code | Meaning |
| - | - | - |
| 412 | `err:unkey:data:analytics_not_configured` | Analytics is not enabled for this workspace yet. See [Analytics](/docs/api-management/analytics/overview). |
| 403 | `err:unkey:authorization:insufficient_permissions` | The root key lacks `read_analytics` (or `read_gateway_requests` / `read_runtime_logs`) for the endpoint. |
| 503 | `err:unkey:data:analytics_connection_failed` | Analytics is temporarily unavailable. Retry with backoff. |

All errors use the standard [API error format](/docs/platform/api/errors), and each error's `type` field links to its page.
