ONESHOTGEMS

For game developers

Migrate old save shapes deliberately

Save-state testing asks whether the intended values persist. Versioning answers a different question: what should happen when a later game build reads data written by an older build? If version one stored a best score as a number and version two stores a profile object, reading the old shape as if it were new can break the menu or silently discard progress. Put a version beside saved data and write an explicit migration for known earlier shapes.

Wrap values in a small versioned envelope

Instead of saving a bare score such as 240, store a JSON object such as { version: 2, bestScore: 240, settings: { sound: true } }. On load, parse the text, check that it is an object, and inspect its version before using fields. JSON.parse can throw a SyntaxError for invalid JSON, so handle malformed text with a defined fallback rather than allowing startup to stop before the player can begin.

Keep the envelope narrow and document what each version means. Avoid treating the version alone as validation: a value tagged version two can still be incomplete or have the wrong type. Check the fields the current build actually relies on, such as a finite nonnegative bestScore and a boolean sound preference.

Write one migration for each supported old shape

A migration from version one can transform the old number into the new envelope, fill in a default setting, and then save the version-two form. Make migrations sequential when multiple historical versions are supported: version one to two, then two to three. Test each fixture independently, including missing keys, malformed JSON, an unknown future version, and a partially written value. Decide whether unknown data is preserved, ignored, or reset and communicate a recovery message when it matters.

Keep browser storage limitations in scope

MDN describes localStorage as origin-scoped data that can persist across browser sessions, but storage availability and contents should not be treated as a guaranteed account backup. Do not put secrets or trust-sensitive decisions there. If a game cannot read a save, allow a defined fresh start and avoid repeatedly retrying the same broken migration on every launch.

Questions about localStorage game data versioning

Should I clear all saves when the format changes?

Only when that is an explicit product decision. If important values can be mapped safely, a small tested migration can preserve them; otherwise define a clear fallback and explain the reset.

Does a version field make localStorage data reliable?

No. It identifies the expected shape so the game can migrate or reject it. Data can still be missing, malformed, stale, or unavailable, so validate before using it.

Sources and further reading

Report a correction · How these guides are made

Follow your curiosity