Limits
Defaults and limits in one place. What a product may spend is in Spending; what a tenant may use is its own limits, set by your product (see Tenants).
Names
| Product | lower-case letters, digits and single dashes, starting with a letter, at most 30 characters |
| Environment | the same, at most 20 characters (prod, staging, pr-42) |
| Service | the same, at most 40 characters |
| Database | lower-case letters and digits, at most 10 characters |
Services
| Default | Limit | |
|---|---|---|
| Memory of each box (reserved and limit) | 256Mi | 32Mi to 2Gi; billed as reserved |
Boxes (max_replicas) |
1 | 50 |
CPU of a request or invocation (box.toml cpu_ms) |
300,000 (5 minutes) | 900,000 |
Duration of a request or invocation (duration_ms) |
600,000 (10 minutes) | 3,600,000 (an hour) |
Subrequests (fetch) of one |
10,000 | 100,000 |
Request body (body_bytes) |
100 MiB | 100 MiB |
| Rows read, written in a transaction | 1,000,000, 500,000 | 10,000,000, 5,000,000 |
Asleep after idle (idle_seconds) |
300 | 3,600 |
| Requests in flight before another box takes them | 20 a box | |
| Requests at the edge | 1,000 a second and in flight per name | |
| Release handler | its box's duration_ms |
|
| A release's checks (its handler, then each service's health) | 3 minutes |
WebSockets stay open while a box sleeps (scaledbox holds them); server-sent events and streamed answers keep their box awake.
Data
| Default | At its size or allowance | |
|---|---|---|
| Postgres database | 1Gi | read-only |
| Bucket | 5Gi | nothing more can be written |
Bucket object ([bucket] max_object) |
25 MB, at most 100 MB (100,000,000 bytes) | a larger upload, multipart part or multipart total is refused (400 EntityTooLarge) |
| Bucket requests | 1,000,000 a month per environment | 5 requests a second at each of the S3 gate's two replicas until the next month (503 SlowDown, which S3 SDKs retry) |
| Bucket transfers at once | 16 per environment or tenant at each of the S3 gate's two replicas | 503 SlowDown with Retry-After |
| Database dumps | nightly, kept 14 days | download links last 15 minutes |
| Logs | kept 14 days | scaledbox logs shows up to 1000 lines at a time |
Environments
| Previews | sleep after 15 idle minutes; deleted after a week without a deploy |
| Tenants' apps | sleep after 5 idle minutes by default (idle_seconds); previews pr-<n> deleted after a week without a deploy |
Tenants' apps
Each environment of a tenant's app is one box. Its caps are the tenant's box limits, which its
box.toml may lower, never raise; unset ones are the defaults (see Tenants).
Per box and per invocation (box) |
Default | Least | Most |
|---|---|---|---|
memory_mb: the box's memory |
128 | 32 | 512 |
cpu_ms: CPU time of one invocation (I/O waits excluded) |
200 | 10 | 5,000 |
duration_ms: one invocation, until its answer begins |
60,000 | 100 | 900,000 |
subrequests: fetch calls of one invocation |
1,000 | 1 | 10,000 |
body_bytes: a request's body (413 beyond) |
10 MiB | 1 KiB | 100 MiB |
A box writes at most 100 log lines (64 KiB) a second, in bursts of 10 seconds' worth; beyond, its lines
are dropped and a line of level runtime says how many. A line's message and stack are cut at 32 KiB
each. Logs are kept 14 days.
| rows_read_per_tx, rows_written_per_tx: one transaction's | 32,000, 16,000 | 1 | 1,000,000, 500,000 |
| idle_seconds: asleep after this long with nothing in flight | 300 | 10 | 3,600 |
A month (month) |
Default | Most | Past it |
|---|---|---|---|
invocations: requests, queue batches, scheduled runs, workflow steps, WebSocket messages |
1,000,000 | 10⁹ | 5 requests a second per app (429) |
cpu_ms |
3,600,000 (an hour) | 10⁹ | new invocations refused (429) |
memory_gb_s: each box's memory × its time awake |
400,000 | 10⁹ | sleeping apps don't wake (503) |
rows_read, rows_written: its own tables' |
25,000,000, 1,000,000 | 10¹⁰, 10⁹ | its apps' database statements slowed to 5 a second per app |
kv_read_units (4 KiB), kv_write_units (1 KiB) |
10,000,000, 1,000,000 | 10¹⁰, 10⁹ | kv operations slowed to 5 a second per app |
class_a (bucket writes and lists), class_b (reads) |
1,000,000, 10,000,000 | 10⁸, 10⁹ | the bucket answers 5 requests a second (either, or both together; 503 SlowDown) |
messages (per 64 KB: queue sends and deliveries, webhooks) |
1,000,000 | 10⁹ | new queue sends, webhook messages and ingests refused (429); deliveries go on |
egress: what its apps send (their fetch calls, their answers, webhooks, static files) and its bucket's downloads |
100Gi | 1Ti | each app's calls out at 1 Mbit/s, its answers at 64 KiB a second, its bucket's downloads at 1 Mbit/s (never cut); new webhook messages refused |
log_events: console lines |
10,000,000 | 10⁹ | its apps' logs aren't kept (as past logs_per_day) |
emails: auth's emails (codes, invitations) |
10,000 | 10⁷ | more are refused (429) |
compile_cpu_ms: compiling its deploys' new modules |
600,000 (ten minutes) | 36,000,000 | deploys refused (409, tenant.quota_exceeded) |
ai_tokens: tokens at its product's AI gateway, every model and class |
1,000,000 | 10¹⁰ | new requests to the gateway refused (429); those under way finish |
Usage counts in the hour it happened; the edges come within a minute of reaching an allowance, and go the next month (or with a higher allowance). Nothing running is stopped.
| A tenant | Default | Most |
|---|---|---|
| Apps | 5 | 100 |
Environments per app (environments: prod, staging, previews) |
10 | 50 |
| Database | 1Gi (read-only beyond) | 4Gi |
| Bucket | 5Gi (nothing more written beyond) | 500Gi |
Bucket object (bucket_object) |
25M | 100M |
Scheduled runs: how often a schedule may fire (cron_interval) |
every hour | every minute |
Logs a day (logs_per_day, UTC): past it, its apps' output isn't kept until the next day |
no cap | |
| A deploy | 1,000 modules of at most 16 MiB (their bytecode 128 MiB in all), 20,000 assets of at most 25 MiB (1 GiB in all); finished within the hour | |
box.toml |
20 bindings, 50 hosts, 200 routes, 5 schedules | |
auth's emails (codes, invitations), all its apps (past it, 429) |
100 an hour |
| Apps awake at once, all of them (awake) | 10 | 100 |
| WebSockets open at once, all its apps (connections) | 200 | 10,000 |
| Requests a second to each of its apps' names (requests_per_second, bursts of 4 times it) | 50 | 1,000 |
| Requests open at once to each name (concurrent_requests) | 200 | 1,000 |
| Requests at once at its product's AI gateway, all its apps (ai_streams) | 20 | 1,000 |
Beyond its rates, 429; WebSockets and streamed answers count while open. The rates hold across the
platform's servers together, each holding its share, so a burst that reaches only one of them may meet a
429 a little before the rate. Its limits change without a redeploy. Each app's traffic to the internet: 50 Mbit/s and 100 new connections a second (bursts of
200); beyond, packets are dropped, so connections slow down.
An app that keeps its CPU busy (90% or more of its one CPU for 30 minutes in a row: mining, a runaway
loop) gets its tenant suspended; your product is told (tenant.suspended, reason cpu).
An app's JavaScript has three quarters of its memory_mb (its objects, strings and arrays): an
invocation that needs more is answered 503 (the app ran out of memory) and the box goes on. The
rest is the runtime's (request and answer bodies, Blobs) and what was freed and not yet given back.
Past nine tenths of memory_mb in all, the box gives back what it can; still past it, what it has in
flight is answered 503 (the box's memory passed 115 MB of its 128 MB (limits.memory_mb) …) and the
box ends: the next requests are served by a fresh one. Raise memory_mb (up to your tenant's cap) or
use less. A single built-in call that alone needs more than memory_mb ends the box without an answer.
An invocation past its cpu_ms is answered 503, the message saying how to give it more. 200 ms of
CPU is plenty for a request's work: waiting on the database, fetch or a bucket doesn't count, and
in a box 1 MiB of JSON parsed, grouped and written takes about 24 ms, a page of 1,000 rows from a
template 16 to 22 ms, a regex and two replaces on each line of a 1 MiB log 141 ms. More than that
(rendering 100 KiB of Markdown, about 1.6 s; image pixels in JavaScript, 0.1 to 0.6 s; a JavaScript
hashing library) needs a higher cap: your product raises its tenant's box.cpu_ms, up to 5,000 (an
app's box.toml may only ask less: one that sets a lower [limits] cpu_ms keeps it until it asks
more, within the tenant's). Or split the work into a queue's messages or a workflow's steps, each an
invocation with a cpu_ms of its own. An app's top level (its modules evaluated as its box wakes)
has a second of CPU, or its cpu_ms if more, as Workers' startup.
An invocation inside a single built-in call when it reaches its cap (a huge crypto.subtle PBKDF2 or RSA key generation, BigInt arithmetic on millions of bits,
some string searches) can't be stopped there: a second past its cpu_ms, its box ends, failing what
else it had in flight, and the next request wakes another. Apps' JavaScript is interpreted, not
compiled: work done by built-ins (JSON, crypto.subtle, Map, a typed array's sort) costs about
what it costs in Node, loops written in JavaScript 5 to 100 times more (pixel loops and hashing in
JavaScript the most), so hash with crypto.subtle, never a JavaScript hashing library. A box answers
one request at a time: a request that computes for a second holds the others to its box for that
second, so keep such work in a queue's consumer or a workflow step. Rendering long Markdown with a
library is slow (about 1.7 s of CPU for 100 KiB with marked): render it once and keep the HTML.
When a node's memory for apps is full, an app waking puts the least recently used idle app on it to
sleep (never one serving a request): a standard tenant's first; a priority tenant's only for
another priority tenant's app. If none may sleep, the wake is refused (503, Retry-After).
Crawlers and other bots (search engines, SEO and AI crawlers, link previews, scanners) get a 503
with Retry-After instead of waking a sleeping app; an awake app serves them. API clients, webhook
senders, uptime monitors and test tools wake apps as visitors do (a monitor checking every minute keeps
its app awake).
The API
| Requests per visitor (the API is behind Cloudflare's proxy) | 10 a second, bursts of 50 |
| A request's body | 1 MiB in 5 seconds; uploads (a build's source, 10 MiB) 10 minutes |
| A request | an answer within 100 seconds (Cloudflare's): long work (deploys, dumps, deletions) answers 202 and is polled |
| Requests per token | 10 a second, bursts of 100 |
| Idempotency keys | remembered for a day |
Past a rate limit the API answers 429 Too Many Requests: wait and retry.
Code
Your services and your tenants' apps are code, not images: your product builds their JavaScript modules and deploys them (see Deploying and Tenants); scaledbox compiles each module and runs it sandboxed. There is no image, Dockerfile or registry to push to.