A tester reaches the second phase of your boss, dies, and the game drops them back before the two-minute elevator ride, the ammo crate they already looted, and the cutscene they cannot skip. They try once more. They die again. Then they put the controller down and say the thing every designer dreads: "I'll come back to it later." Nothing about your boss was unfair. Your save system was.
Save design gets treated as engineering plumbing, which is why it usually arrives late, undocumented, and tuned by whoever wired it up. It is a design system with its own failure modes, and it deserves the same treatment as your combat or your economy: a stated intent, numbers you can test against, and a written contract that programmers and level designers both read.
Start with one number: worst-case lost progress
Forget save file formats for a moment. The player-facing question is simple: if the game ends right now — death, crash, alt-F4, a phone call — how much of the player's time evaporates?
Call it the loss budget. It is measured in minutes of play, and it is a worst case, not an average. Pick the number before you pick the mechanism, because the mechanism is just whatever hits the number.
A reasonable starting point by genre:
| Genre | Loss budget (worst case) | Why |
|---|---|---|
| Precision platformer | 5–20 seconds | Death is the core loop; retries must be instant |
| Action / character action | 60–120 seconds | Encounter is the unit of progress |
| Survival horror | 3–8 minutes | Tension comes partly from stakes |
| Immersive sim / RPG | 2–5 minutes | Exploration is nonlinear; manual saves supplement |
| Roguelike run | Entire run, by design | But a suspended run must never be lost |
| City builder / grand strategy | 2–5 minutes | Long sessions, slow state changes |
| Mobile / handheld sessions | 15–30 seconds | The player will be interrupted mid-input |
Two important consequences fall out of this number immediately. First, it constrains level design: if your budget is 120 seconds and a corridor takes four minutes to traverse, that corridor needs a checkpoint in the middle or it needs to be shorter. Second, it constrains your autosave interval and your "what counts as progress" rules — more on both below.
Write the budget down as a design constraint, not a preference. In GameDesignerX, the natural home is a mechanic entry for the save system itself, cross-linked to the levels it constrains, so a level designer opening a blockout sees the number that applies to their space.
Five save models, and what each one actually costs
| Model | Example shape | Strengths | Costs |
|---|---|---|---|
| Checkpoint autosave | Invisible triggers at room or encounter boundaries | Zero player cognitive load; enforces pacing | Authoring burden per level; feels arbitrary if spacing is inconsistent |
| Save points | Bonfires, typewriters, campfire benches | Doubles as a pacing and safety beat; diegetic | Backtracking pressure; punishing if spacing is uneven |
| Save anywhere (slots) | Manual F5 in an immersive sim | Maximum player control; great for experimentation | Enables scum-and-reload play; huge QA surface (any state must serialize) |
| Suspend / quick-resume | Single-slot "continue" that deletes on load | Perfect for handheld and mobile interruption | Not a safety net; a crash mid-write can lose everything without care |
| Run-based commit | Roguelike run state written after each room | Permadeath stays meaningful, interruptions don't punish | Save-scumming prevention becomes a real problem to solve |
Most shipped games combine two: checkpoint autosave for the safety net plus manual slots for player agency, or run commits plus a profile save for meta-progression. Pick your primary model from the loss budget, then add a secondary only if it solves a specific problem you can name.
A rule that saves a lot of arguments: autosave on entering a safe state, not on leaving a dangerous one. Saving the instant a boss dies is correct. Saving the instant a boss fight begins, with the player at 12% health and no consumables, creates an unwinnable state that players will rightly call a bug.
The three buckets: what goes in the file
Most save bugs come from state that lives in the wrong bucket. Sort every piece of persistent data into exactly one of these, and document which:
- Run state — position, health, inventory, quest flags, enemy spawn states, elapsed time. Dies with the run or the slot.
- Profile state — unlocks, currency, achievements progress, best times, tutorial-seen flags, cosmetics. Survives everything, including a deleted save slot.
- Settings state — bindings, audio, accessibility options, language, subtitle size. Never gated behind a save slot, and always available at the title screen.
The classic bug is a tutorial flag in bucket 1: a player starts a new game and gets the "press A to jump" prompt for the fifth time. The mirror-image bug is quest progress in bucket 2: deleting a save and starting over leaves doors already unlocked.
A minimal serialization checklist
- Every persistent field has a declared default for when it is missing from an older file
- The save contains a version integer, written from day one
- Writes are atomic: write to
save.tmp, flush, then rename oversave.dat - At least one backup slot (
save.bak) that is only overwritten after a successful load - No absolute file paths, no raw pointers, no engine object references — IDs only
- Floats that matter (position, timers) are written with enough precision to avoid drift on repeated save/load cycles
- Save writes never block the main thread during gameplay, or they happen only at a hitch-tolerant moment
Versioning: the migration you will definitely need
You will change your item schema in month seven. If you are in early access, some player's 40-hour file depends on the old one. Plan for it now — it costs an afternoon before launch and a nightmare after.
The pattern is boring and reliable: store saveVersion in the file, keep an ordered list of migration functions, and run each one whose version is greater than the file's. migrate_3_to_4 renames gold to currency.soft. migrate_4_to_5 adds the new crafting block with its defaults. A file at version 3 walks through both.
Two rules make this survivable. Unknown fields are ignored, not fatal — a file from a newer build should degrade rather than crash a tester's older client. And every migration gets one save file committed as a fixture in your test suite: a real version-3 file that must still load in the current build. Log which migrations exist and when they landed next to your build-tracking entries, so a QA report of "corrupt save on build 412" can be matched against the schema change that caused it.
Where saves break: a test pass you can run in 30 minutes
Run this on every milestone build, not just at cert:
- Save, quit to desktop, relaunch, load — is the player in the same place with the same inventory?
- Kill the process during an autosave write (task manager). Does the game recover from the backup?
- Fill the disk, then save. Does it fail gracefully with a message, or silently lose the file?
- Load a save made three builds ago. Every migration path, every time.
- Save inside every "weird" state you support: mid-air, mid-dialogue, while a timed event runs, during a vehicle sequence, with a menu open.
- Start a new game with a completed profile. Are bucket-2 flags still respected and bucket-1 flags actually reset?
- Unplug the controller, change language, then load. Do settings survive independently?
- Two saves in quick succession — no duplicate or interleaved writes?
Half of these will pass forever. The other half will catch something the week you change your inventory code, which is exactly why the list belongs in your recurring build checklist rather than in someone's memory.
The design conversation, not the engineering one
When a save system feels bad, players almost never say "the save system feels bad." They say the boss is unfair, the level is too long, the game is tedious. Treat complaints about repetition after death as save-spacing data: in your playtest notes, record the time between the last checkpoint and the point of failure alongside the failure itself. A boss with a 40-second approach run is a different boss than the same fight with a checkpoint at the door — and it is usually cheaper to move the checkpoint than to retune the fight.
Pick your loss budget this week. Write it into your mechanics doc, check your three longest levels against it, and you will have removed an entire category of "this game is frustrating" feedback before it ever reaches a tester.