Appearance
Shipping Checklist
Written: 2026-10-14
Learning objectives
- You can keep a test place and a live place strictly separate.
- You can enable API access on the test place only.
- You can gate every publish on clean output, clean analysis, and a two-client repro.
- You can smoke-test DataStore budgets before launch.
- You can monitor stores and throttle errors after publish.
Prerequisites
One test place, one live place
Studio touches the same data stores as the live game. The data stores guide warns: enabling API access for a live game risks overwriting production data, so enable it on a separate test version instead. Publish the place twice, once for players and once for testing, and never mix them.
Open File, then Experience Settings, then Security, and enable the Studio Access to API Services toggle on the test place only. Every save, purchase, and wipe test runs there. The live place keeps the toggle off until the test place proves the build. Restores confirm by rejoining the test place with the same account and comparing coins and inventory, exactly like the data system tests.
Gate every publish
No publish goes out with errors showing. Press Play and watch the whole session: Output stays clean, Script Analysis shows zero errors, and every touched system gets exercised once. Type warnings flag lines without stopping the script, so read them as strictly as errors before shipping.
Reproduce multiplayer from Security and Production: two clients, one acting badly. The second client buys without funds, fires stale keys, and walks through walls. The server rejects all three and both Outputs stay readable. Commit through version control with a clean tree, lockfiles tracked, and builds ignored, per Format, Lint, and Version Control.
Smoke the budgets
Launch traffic exposes unbudgeted calls. Before publishing, read the limits reference again and check the three numbers against it. Each key holds at most 4,194,304 characters. Experience reads allow 300 plus 40 per player each minute, writes allow 300 plus 20 per player each minute, and each UpdateAsync spends from both. Per-key throughput caps reads at 25 MB per minute and writes at 4 MB per minute.
Ask whether joins, autosaves, and leave saves fit inside those budgets at the target player count, and check the current request budget with the rate-limit APIs if tuned. Throttle errors in the 301 to 306 range mean queues filled and requests dropped, which means batch, cache, or slow the timer instead of retrying harder. The data system caching, snapshotting, and 60-second autosave follow these habits.
Publish and watch
Publish the test place first and play it like a stranger: new account, no knowledge, phone-sized viewport. Watch the Data Stores Manager in Creator Hub to confirm keys appear with sane sizes. Only then publish live.
After publish keep watching. Throttle errors, failed receipt grants, and leave-save misses show up in Output and logs first, while players notice them second. Fix forward in the test place, re-verify the full gate, and publish again. Never patch live data by hand to cover a code bug; fix the code and let migration handle old shapes.
Common mistakes
Mistake 1: testing in the live game.
Wrong: API access on, experimenting with real player data. Why: Studio writes to the same stores players use. Fix: test place only, separate keys, separate verification.
Mistake 2: shipping with warnings.
Wrong: Script Analysis warnings ignored because the script still runs. Why: warnings are the strict checker telling you the next outage. Fix: zero errors and zero warnings before publish.
Mistake 3: retrying through throttle.
Wrong: tighter retry loops when 301 errors appear. Why: throttle means the queue is full, so more calls drop faster. Fix: batch reads, cache rows, slow the timer, shrink values.
Mistake 4: hand-editing live data.
Wrong: fixing a corrupt row directly in production. Why: the next save or migration re-applies the bug, and you have no record. Fix: fix code, add a migrate path, publish through the gate.
Exercises
- Audit one project build against the publish gate: clean Output, zero analysis errors, two-client repro. Write down every failure before fixing.
- Compute your join cost: count DataStore calls per join across all Services, multiply by your target concurrent players, and compare against the read budget. Confirm the margin or add caching.
- Sketch a rollback plan: what you publish, what you watch in the first hour, and what triggers a revert to the previous version.
Solution 1
Run the gate in order and record honestly:
txt
Output clean: yes
Analysis errors: 0, warnings: 0
Two-client repro: bad client rejected 3/3Expected behavior: a written pass record exists before the publish, not after.
Solution 2
Count calls, not systems. One GetAsync per player per Service adds up fast:
txt
joins: 3 reads x 50 players = 150/min against 300 + 50 x 40 = 2300/minExpected behavior: a written margin, or a caching change that creates one.
Solution 3
A plan names the version, the watch, and the trigger:
txt
publish: test place v9 verified, then live
watch: throttle errors, grant failures, leave-save misses
revert: any grant failure or sustained 301s in hour oneExpected behavior: the trigger is a number, not a feeling.
Summary
Separate test from live and enable API access on test only. Gate publishes on clean output, clean analysis, and a two-client repro. Smoke-test budgets against the limits reference. Publish test first, watch the manager, and fix forward. Next, build with Utility Library.