voxal docs
Platform

Limits and quotas

The platform defaults that bound every app's deploy size, compute, timers, terminal I/O, and outbound fetch

Every voxal app runs inside its own sandbox with a fixed set of limits. These bound deploy size, compute, timers, terminal output, and outbound fetch. The values below are the platform defaults.

Why these exist

Many apps and many users share one box. These limits keep one app, or one runaway connection, from starving everyone else, so every app gets a fair, predictable share of memory, CPU, and bandwidth.

Deploy and bundles

Your app, the SDK, and your pure-JS dependencies are bundled into a single file by the CLI. See voxal deploy and voxal build.

LimitValueNotes
Bundle hard limit5 MiB (5,242,880 bytes)Measured as UTF-8 bytes of the built bundle. Deploy or build fails over this.
Bundle warning4 MiBA warning prints when the bundle exceeds 4 MiB.
DependenciesPure JavaScript onlyNo native npm modules.
IntegrityChecksum-verified end to endThe bundle is integrity-checked from build to boot, so the bytes that run are exactly the bytes you built.

For app design: keep dependencies lean and tree-shakeable. If you are near the warning, audit large libraries before you hit the hard limit.

Compute and memory

Each app runs in its own isolate: a separate heap and event loop. One bad app cannot affect another or the host.

LimitValueNotes
Memory per app64 MiBThe whole app's budget, shared across all of its connections.
CPU per bootabout 1000 msSynchronous JS only. Awaiting does not count against it.
CPU per eventabout 100 msEach connect, key, resize, close, or timer fire. Synchronous JS only.
Idle timeout2 minutesAn app with no connections is dropped after 2 minutes idle.
Cold bootabout a few millisecondsThe app is booted again on the next connection.

Long synchronous work is interrupted when it exceeds the per-call budget, so keep per-keystroke work small and avoid blocking the event loop. App memory is not retained across a drop: treat each boot as a fresh start and reload any state you need.

Timers

setTimeout and setInterval inside an app create real host timers, so they are bounded.

LimitValueNotes
Live timers per app1024Exceeding this throws.
Minimum delay4 msShorter delays are clamped up to 4 ms.
Aggregate fire rateabout 2000 fires/second per appExceeding this throws.

Tip

If you animate with the UI layer, useAnimation shares a single timer across your component tree, which stays well within these limits. See the UI layer.

Terminal I/O

Output you write to the terminal and input you receive from the user are both rate limited.

LimitValueNotes
Single conn.write1 MiBThe cap on one write call.
Sustained outputabout 2 MiB/s, 4 MiB burstExcess is dropped. Redraw efficiently.
console.log per lineabout 2048 charactersTruncated and rate limited. Goes to server logs, not the user's terminal.
Terminal columnsmax 1000Default 80 when unknown.
Terminal rowsmax 1000Default 24 when unknown.
Keyboard inputabout 256 KiB/s sustained, 1 MiB burstPer connection. Far above human typing; only affects pathological floods.

For app design: diff your frames instead of repainting the whole screen, so you stay under the output cap. The UI layer does this for you. Because output past the cap is dropped, not buffered, an inefficient redraw can visibly corrupt the screen under load.

fetch

fetch is host-bridged and SSRF-guarded. The full reference, including options and the response shape, is in the fetch docs.

LimitValueNotes
Schemeshttp, https onlyAll other schemes are refused.
Request timeout10 secondsTotal, per request.
Response size cap5 MiBThe body is truncated or aborted past this.
Redirectsup to 5 hopsEach hop re-validated.
Per-app rate limit30 requests per 10 secondsShared across the app's connections.
Concurrencyat most 6 in-flightPer app.

Private, loopback, link-local, and cloud-metadata addresses are refused, so a deployed app cannot reach internal services. See Sandbox and security for the full guard list.

The response is { status, headers (names lower-cased), body (UTF-8 string) }. A non-2xx status does not throw, and errors are sanitized so no host details leak.

On this page