Back to Blog
save systemsmechanicsuxproduction

Checkpoints, Autosaves and Lost Progress: Designing a Save System Players Trust

Save design is a design problem, not plumbing. Set a worst-case lost-progress budget, pick a save model that hits it, sort state into three buckets, and version your files before you need to.

GameDesignerX TeamSeptember 16, 20268 min read

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:

  1. Run state — position, health, inventory, quest flags, enemy spawn states, elapsed time. Dies with the run or the slot.
  2. Profile state — unlocks, currency, achievements progress, best times, tutorial-seen flags, cosmetics. Survives everything, including a deleted save slot.
  3. 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 over save.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.