Advanced path: production-grade multiplayer
For games that already work: make them smooth, efficient, hard to cheat, and deployed.
Step 1 — Bandwidth & smoothness
- Audit every
SpawnSync: issend_rateas low as the game feels good at? (8/s default; slow-moving objects are fine at 2–4/s — the dirty-check already silences idle objects) - Trim
synced_propertiesto what remote players actually render - Tune
interpolation_speedper object (snappier for players, smoother for props); for shots/dashes, prefer an event + local simulation over per-tick sync - Watch the rate-limited count on the Errors page during a stress playtest (limits)
Checkpoint: a 4-player session shows zero rate-limited errors.
Step 2 — Authority hardening
- Write down, per mechanic, who can lie about it (the best-practices authority section has the framework)
- Move abusable decisions to the host: victims applying their own damage is convenient; the host validating kills is sturdier
- Bound-check everything received in
event_received— never trust positions, damage numbers, or ids from the wire - Handle
host_changedmid-round: the new host must be able to take over any host-side logic (keep host state IN room state, not in host-local variables)
Checkpoint: a modified client that sends {"damage": 9999} events can't win.
Review my SpawnWeaver authority model. Architecture: clients exchange events
(relayed, sender-excluded), per-player entity state (owner-write-only), and host-only
room state; the platform has no server-side game logic. My mechanics and current
authority: <LIST THEM>. Which are exploitable by a modified client, and what's the
strongest mitigation available WITHOUT server-side code?
Step 3 — Resilience engineering
- Chaos-test:
simulate_connection_loss()at every game phase (menu, matchmaking, mid-round, round-end) — each must recover or fail with a clear message - Handle the permanent failure: grace expired, room gone —
room_left("disconnected")should land the player on a "match lost" screen, not a frozen arena - Queue-audit your
send_eventusage: everything queued during a blip flushes on resume — make sure replaying stale events (e.g. old ability casts) is harmless
Checkpoint: no phase of the game can dead-end from a network blip.
Step 4 — Launch readiness
- Split environments: create a production project separate from the one your playtests used, so live players never share rooms or storage with dev builds (set it on the project page; the key in your shipped build is the only switch)
- Sweep your key hygiene: the production public key is in the shipped build (fine — it's public by design), but it should appear nowhere else; rotate it if it ever leaked into a stream or screenshot alongside test data you care about
- Re-read Limits & quotas against your real traffic —
SpawnSyncrates, event bursts, storage writes — and fix anything that budgets over the caps before players find it - Expecting a launch spike (festival, streamer, Next Fest)? Contact us ahead of time so your project's connection cap is sized for the day
- Force-kill the game mid-match on a real device and relaunch: the reconnect flow from Step 3 is only done when it works outside the editor
Checkpoint: the launch build points at a clean production project and a mid-match kill + relaunch gets the player back into their room with identity intact.
Step 5 — Live operations
- Bookmark Sessions and Errors; check them after every playtest
- Add
create_debug_report_string()behind a debug key in your game; ask bug reporters to paste it — inspect via the dashboard's Debug bundle viewer - Track your usage on the Usage page as your playtests grow
Checkpoint: when a player says "it broke", you can see their session timeline.
You're production-grade. Go ship it — and tell us what you built via the feedback box on the landing page.