Quotas & limits
The PV and UV budgets, the status codes they return, and how the counters are kept.
Two independent layers protect the real key. Both are scoped to a single key and both reset when the UTC day changes.
PV — requests per day
| Property | Value |
|---|---|
| Scope | One key |
| Ceiling | Your plan caps the sum of PV quotas you can allocate across all your keys |
| Warning | A pv_warning alert at 75% of the quota |
| Enforcement | The key stops forwarding at 100% |
| Response | 403 { "error": "pv quota fused" } |
UV — visitors per day
Each key caps two things at once:
| Property | Value |
|---|---|
| Distinct visitors | How many different visitors may use the key, so a shared key is bounded |
| Per-visitor calls | How many calls any single visitor may make, so one caller cannot consume the whole allowance |
| Visitor identity | sha256(user-agent + IP). The pair itself is never stored |
| Response | A new visitor over the cap: 429 { "error": "uv quota exceeded" }. One visitor over their own: 429 { "error": "per-visitor quota exceeded" } |
| Alert | The day's first blocked newcomer raises one uv_exceeded alert. Every newcomer after it is still blocked, and mails nobody |
A quota of 0 blocks every request of that kind: no requests for PV, no
newcomers for distinct visitors, and no calls at all for per-visitor.
Counters
| Property | Value |
|---|---|
| Storage | One row per key per UTC day, in D1 |
| Concurrency | Each cap is a WHERE guard on the statement that moves it, so concurrent requests cannot exceed it |
| Window | The day is part of the key, so a new day is a new row rather than a rollover |
| Retention | Kept per day; only today's rows count toward the limits |
Per-tier limits and how to raise them are on the pricing page.