Skip to content

Budgets and tick rates ​

You'll learn: how much CPU, memory and storage you get, how fast your plot ticks, and who owns movement. You'll need this when: your plot does a lot per tick, or needs to feel snappy.

Status: Built (headless): CPU metering, memory caps, the storage quota, tick rates, client-owned movement checks. Buying higher tiers with Nimgots is Planned. Client code's frame budget per device tier is In progress, with client code.

Budgets are about fairness, not content ​

There are no caps on what you make: entities, blocks, particles. Devices draw what they can, and the engine degrades the rest (LODs, impostors, average colours). Budgets exist so one plot can't stall the world.

Budget (per plot)DefaultHard capOver it
CPU per tick2 ms8 msthe hook is cut off, its writes are discarded
CPU per rolling second20 ms80 mssustained: dropped to 10 Hz, then suspended for a while
Memory32 MB128 MBgrowth fails: a crash (below)
Storage1 MB plus your blocks16 MBstorage.set refused with storageFull
Bandwidth per viewer64 / 128 / 256 KB/s by device tierlower-priority updates wait a frame
Custom channels25% of a viewer's bandwidth, 32 messages a tick per channelunreliable messages dropped, reliable ones queued
Outbound networknonenonethere's no API

Higher tiers will cost Nimgots (Planned). All of a plot's packages share its budget, each with its own slice.

Crashes: a trap (an exception you didn't catch, running out of memory) discards that hook's writes. A mod that traps sits out alone and restarts after 1 s, 5 s, then 30 s; the runtime and the other mods carry on. A runtime that traps takes the plot down: players inside are released (stashed or tried-out items given back, as on leaving) and the plot restarts after the same delays. Five crashes in ten minutes stop it (a mod until the plot restarts, a runtime's plot until it's started again). Your blocks and entities stay as they were, and your code rebuilds from storage on restart.

Tick rate: 20 Hz by default, up to 60 ​

json
{ "tickRate": 30 }

or at run time (runtime only):

ts
time.setTickRate(60);    // refused with "overBudget" if it doesn't fit your CPU quota

Every lobby that isn't suspended gets tickLobby(dt) once per tick (or export tickAllLobbies(dt, ids): one call for all of them, the cheap path when there are many); tickPlot(dt) runs once per tick at plot level. Most games are fine at 20. Shooters and fast platformers want 30 to 60.

Who owns movement ​

"movement": "server" (default)"movement": "client"
Authoritythe room simulates every player; devices predict and reconcileeach device is authoritative for its own player
Feelfair; a little latency on correctionsRoblox-like responsiveness
Cheatinghardthe room sanity-checks speed, acceleration, teleports, flying and noclip, corrects violations, and moves repeat offenders back to server authority
Use forcompetitive gamesplatformers, exploration, co-op

Lag compensation (network.pastPositions, network.raycastAtTime: the last 500 ms) works with both. See the shooter guide.

Determinism ​

Use time.now(), time.tickNumber() and time.random() (seeded per plot, lobby and tick; recorded). In JS packages, Math.random and Date.now() are wired to those for you; for timers use time.startTimer, not setTimeout. Deterministic code replays exactly in tests and in moderation reviews.

Next ​

Drafts, hot reload and publishing.