Limits
PerSQL is pay-as-you-go. There are no per-token throughput caps and no monthly request quotas — the prepaid balance is the spend control, and each database is its own Durable Object so tenants can’t crowd each other. The limits below are platform safety nets and protocol contracts.
Per request
Section titled “Per request”| Limit | Value |
|---|---|
batch statements per call | 100 |
| Idempotency key length | 200 chars |
| Idempotency cache TTL | 24 hours |
| Public endpoint input body | 1 MB |
ask endpoint result rows | askConfig.maxRows, default 100 |
| Question text length | 500 chars |
Edge protections
Section titled “Edge protections”A coarse per-IP flood control sits in front of /v1 and /api
to short-circuit anonymous floods before they reach auth. A real
customer never hits this; an attacker scripting from one host does.
When it fires the response is 429 with a Retry-After header —
the SDK throws a RateLimitError you can catch and retry.
Per-endpoint public endpoints (/p/:ns/:db/:slug) can also be
configured with their own per-IP rate limits in the endpoint spec.
See Endpoints overview.
Caching
Section titled “Caching”| Cache | TTL | Invalidation |
|---|---|---|
| Bearer token validation | 5min | Token revoke |
Endpoint resolution (/p/*) | 60s | Publish / pause / delete |
| Custom hostname → (ns, db) | 60s | Refresh / delete |
| Better Auth session | per-request | Sign-out |
Headers we set / honour
Section titled “Headers we set / honour”| Header | Direction | Notes |
|---|---|---|
Authorization: Bearer … | request | Required on /v1/*, MCP, session-auth endpoints |
Idempotency-Key | request | Optional on /v1/query + /v1/batch, 24h replay |
Idempotency-Replayed: true | response | Set on cache hit |
Retry-After | response | Seconds, set on 429 |
Cache-Control: public, max-age=30 | response | .well-known/endpoints.json |
Access-Control-Allow-Origin | response | Per-endpoint cors allow-list, or * on discovery |
Platform constraints
Section titled “Platform constraints”- Per-row size cap. SQLite’s defaults apply (~1 GB / row). Don’t store blobs you wouldn’t put in a real Postgres column.
- Long-running queries. Cloudflare Workers have a 30s CPU budget; queries that exceed it are killed. Use indexes.
- Concurrent writers. Each database is single-threaded for writes. Heavy concurrent write workloads serialise — fine for typical SaaS, bad for high-throughput logging.