Limits
Every figure here comes from a named constant; when the code and this page disagree, the code wins.
Execution limits
Section titled “Execution limits”VMLimits::default (crates/runtime/src/logic.rs) bounds one run. Exceeding a
limit traps the run, which then leaves an empty diff.
| Limit | Default |
|---|---|
| Memory | 1024 pages = 64 MiB |
| Stack | 200 KiB |
| Gas | 1 000 000 000 (one point per executed WASM operator) |
| Host calls | 1 000 000 |
| Registers | 100; 100 MiB each; 1 GiB in all |
| Logs | 1024 lines of at most 16 KiB (a longer line traps) |
| Events | 100; kind 100 bytes; data 16 KiB |
| Cross-app calls | 8; function name 100 bytes; parameters 16 KiB |
| Storage key / value | 1 MiB / 10 MiB |
| Storage writes | 100 000, and 128 MiB in all |
| Blob handles | 100; chunk 10 MiB; 512 MiB written in all |
| Ordered-index scan | 100 000 entries |
| Return value | 16 MiB |
| Commit artifact | 16 MiB |
| Method name | 256 bytes |
| WASM module | 128 MiB (256 MiB precompiled) |
| Table elements | 100 000 |
A run’s result also has to fit the log: its whole entry — arguments, diff, events — must stay under 1 MiB.
Node limits
Section titled “Node limits”| Limit | Value | Constant |
|---|---|---|
| One log entry | 1 MiB | calimero_log::MAX_ENTRY_BYTES |
| One sealed request, one HTTP body | 64 MiB | MAX_SEALED_BYTES, DefaultBodyLimit |
| A raw development bundle | 16 MiB | bundle_put |
One blob (an uploaded file, a package .mpk, uploaded or fetched from a registry) |
47 MiB: it reaches the other nodes base64-encoded in one sealed request | MAX_BLOB_BYTES, MAX_MPK_BYTES |
| Metadata (organization, member, team, app) | 16 KiB of JSON | MAX_METADATA_BYTES |
| Passkeys per account | 10 | AddPasskey |
| Registered web origins | 8 per package, 4096 per cluster, 255 bytes each | MAX_ORIGINS_PER_PACKAGE, MAX_PACKAGE_ORIGINS, MAX_ORIGIN_BYTES |
| Aliases per account | 1000, each 1–64 characters | MAX_ALIASES |
| Passkey label | 64 characters | MAX_LABEL_CHARS |
| Upgrade runs kept per organization | 20 | UPGRADE_RUNS_KEPT |
| Follow-up depth | 3 | MAX_FOLLOWUP_DEPTH |
| Events kept per app | 10 000 | EVENT_RING |
| Entries whose touched entities search remembers | 4096 | TOUCHED_RING |
| Presence | 512 authors per app, 4 KiB state, 7 s TTL | MAX_AUTHORS_PER_APP, MAX_STATE_BYTES, PRESENCE_TTL_MS |
| Event and presence streams per node | 4096 | MAX_EVENT_STREAMS |
| Open passkey ceremonies per node | 10 000, each 5 minutes | MAX_PENDING_CHALLENGES |
| Sealed sessions per node | 16 384; 1 h lifetime, 10 min idle | MAX_SESSIONS, SESSION_LIFETIME |
| Forward to an app’s leader | 5 s, then retry | FORWARD_TIMEOUT |
| Compute runs, files and job nodes | See Compute actions | MAX_COMPUTE_WALL_SECS, MAX_COMPUTE_MEMORY_MIB, MAX_COMPUTE_FUEL |
| Replicas per app | --replicas, 3 by default; moves keep at least 3 |
A body past a limit is answered 413, error code TOO_LARGE, with the limit
in the message. Under 64 MiB the node’s own check answers, sealed like any
answer. Past 64 MiB the sealed envelope is refused before it can be opened, so
its 413 ({"error":{"code":"too_large",...}}, which calimero-client
reports as TOO_LARGE) comes back in the clear: sealing it would mean spending
the request id on bytes nobody has authenticated, letting a relay make the node
vouch for a refusal of a request the client never sent. The node reads and drops
the rest of such a body before it answers, up to 1 GiB and 120 s
(MAX_DISCARDED_BYTES, SEALED_READ_TIME), because a client that sends its
whole body before reading would otherwise meet a reset, not the answer; past
that, or for a declared length past 1 GiB or a client waiting on
Expect: 100-continue, it answers at once and closes.
Time limits
Section titled “Time limits”| What | Lifetime |
|---|---|
| Session token | 15 minutes |
| Refresh token | 30 days; exchanged by the first refresh once an hour old |
| Session-signing key rotation | 6 hours by default, at least 30 minutes |
| API key | Up to 1 year |
| Invite | 7 days by default; 1 use by default |
| Client idempotency record | 24 hours; the newest 10 000 kept regardless; at most 1 000 000 |
Node idempotency record (node:…) |
10 minutes; the newest 1000 kept regardless |
| Revoked session remembered | 1 hour |
sys_until / read-index wait |
2 seconds |
Quotas
Section titled “Quotas”Per account, set by the operator (POST /ops/quotas), checked at apply
(The system group); a refusal is
429 QUOTA_EXCEEDED.
| Quota | Default |
|---|---|
| Apps owned | 100 |
| Bundle and package bytes uploaded | 1 GiB |
| API keys | 50 |
| Organizations owned | 20 |
| Accounts on the cluster | 100 000 |
Stored file bytes per organization (maxFileBytesPerOrg) |
50 GB |
Concurrent compute runs per organization (maxConcurrentRunsPerOrg) |
4 |
Reserved compute fuel per organization (computeFuelPerOrg) |
10 times MAX_COMPUTE_FUEL |
Fuel per developer per UTC day (maxFuelPerDeveloperPerDay; the developer usage is billed to: a deployment’s owner for its instances, else the app’s org or owner, D78) |
0 (no limit); checked before a client’s call or an xcall to any of its apps runs, not at apply: init, timer ticks and event handlers still run and count (D76) |
The fuel cap is approximate by at most one refresh interval (5 s). A call never
asks a peer: the node reads the apps it replicates from its own replicas, and the
others from what every peer answered at its last refresh, which asks all peers at
once every 5 s while a cap is set. A developer can so run past its cap for up to one
interval. A peer that stops answering keeps the figures it last reported. An app no
peer has reported yet counts as nothing, so the cap fails open rather than closed:
refusing every call to all of a developer’s apps whenever one replica of one of them
is unreachable would be worse than a developer briefly exceeding a daily cap. The cap is a
decimal string in JSON (D20); a node writes a non-zero cap only once every node runs
its release or newer (409 UPGRADE_PENDING).
Roles and capabilities
Section titled “Roles and capabilities”Organization roles (guest < member < admin < owner), team row roles (lead,
member, read-only) and the capability bits are on
Organizations, teams & access. The storage crate’s
per-entity write mask (OpMask: WRITE, DELETE, ADMIN) is unchanged; it is
checked inside the run, on the leader.