Lesson 98 of 170

A save change is a compatibility decision

Martinez AI Studios Academy

Identify the migration obligation created when a saved-game field changes, using schema versions, compatibility, preservation, and the distinction between build identity and schema identity.

1424. Lesson identity

Module
3.17 — Save migrations
Lesson
1 — A save change is a compatibility decision
Academic type
Concept
Schema type
text
Order
1 in the module
Estimated time
30–45 minutes, including practice

This lesson establishes how to identify the migration obligation created by a saved-data field change. It also distinguishes the identity of the game build from the identity of the saved-data schema. It does not yet design the complete migration procedure.

1425. Learning objective

After this lesson, you can identify the migration obligation created by one saved-data schema change, distinguish the reading build's identity from the save's schema identity, and state the player meaning that must be preserved.

1426. Why this matters

A save file is a contract between one version of a game and a later version. Changing a field can make an older save unreadable or silently alter player progress. Before writing migration code, you need to identify the compatibility obligation created by the change. You also need to know which identity describes the program doing the reading and which identity describes the data format being read. This gives the next lesson a precise problem to solve instead of an assumed default.

1427. Prior knowledge

You should be able to:

  • distinguish persistent state from temporary runtime state;
  • describe the fields in a small save payload;
  • use the reproduce, narrow, validate method from 3.16 L2 — Reproduce, narrow, validate;
  • distinguish a data value from the rule that interprets it.

No engine-specific migration API is required for this lesson.

1428. Core concept

A saved-data field change creates a compatibility obligation to assess whenever a save written under the old schema may be read under the new schema. That assessment may conclude that no migration code is needed if the new reader can interpret the old representation safely and preserve its meaning. Migration work is required only when the compatibility assessment identifies a transformation, default, rejection, or other handling decision that the new schema cannot avoid.

Keep these two identities separate:

  • Build identity: identifies the program or game build attempting to load the save.
  • Schema identity: identifies the structure and rules of the saved data, usually through a save schema version.

A build may be able to read several schema identities, and the same schema identity may be read by more than one build. A build number does not automatically tell you which fields a save contains. Conversely, a schemaVersion does not identify the executable that is reading it. Compatibility analysis needs both facts when they are relevant: which build is loading, and which schema the save uses.

To identify the migration obligation, establish three facts about the data change:

  1. Source representation: What did the old save contain, and which schema version produced it?
  2. Preserved meaning: What valid player state does that data represent and need to retain?
  3. Destination change: What new field, type, name, unit, or structure must represent that meaning?

A field rename, type change, unit change, removal, or change in meaning can require migration work when the old representation cannot be interpreted directly while preserving valid player meaning. Adding a field does not automatically require migration work: if the new field has a valid, semantics-preserving default for every older save, the compatibility decision may be handled by the reader without rewriting the save. It creates a migration obligation when older saves lack a valid value, or when preserving the field's meaning requires an explicit transformation or other handling.

A useful distinction is:

  • Representation: how the value is stored.
  • Meaning: what the value represents in the game.
  • Invariant: what must be true for the value to be valid.

This lesson uses those distinctions to identify the obligation. Choosing a null policy, defining failure behavior, and specifying the complete transform-and-validation procedure belong to 3.17 L2 — Design a safe migration.

1429. Mental model

Use the BUILD IDENTITY → SCHEMA IDENTITY → CHANGE → MEANING model to identify one migration obligation:

Step Question Evidence to record
BUILD IDENTITY Which program build is attempting to read the save? Build or application identity, when provided
SCHEMA IDENTITY Which saved-data format does the file claim to use? Source schema version or detection rule
CHANGE What field representation changed? Old and new field definitions
MEANING What valid player state must remain equivalent? The progress, value, or state to preserve

The first two steps must not be merged. The build identifies the reader; the schema identifies the data. The last two steps prevent a common shortcut: starting with the new field and guessing a value. Start with the old data and its meaning, then state the compatibility obligation created by the destination schema.

You can summarize the result as:

reading build + old schema representation + known meaning → compatibility obligation for the new representation

The next lesson will turn that obligation into an ordered procedure and decide how the transformed result is validated.

1430. Concrete example

Suppose a build identified as build-5 reads a save written with schema version 4:

{
  "schemaVersion": 4,
  "credits": 1200,
  "inventory": ["medkit"]
}

Version 5 replaces the scalar credits field with an economy object:

{
  "schemaVersion": 5,
  "wallet": {
    "credits": 1200,
    "debt": 0
  },
  "inventory": ["medkit"]
}

build-5 is the identity of the program doing the reading. schemaVersion: 4 is the identity of the saved-data format. They answer different questions; neither one alone proves compatibility.

The migration obligation is not simply “add a wallet key.” It is:

  • Change: credits moves into wallet.credits, and wallet.debt is new.
  • Source schema: saves with schema version 4 have the old representation.
  • Meaning: the player’s existing credit balance must remain 1200, and the inventory must remain unchanged.
  • Reader context: the current build must decide how it handles schema 4 while expecting schema 5.

The destination structure is version 5, but the detailed procedure for creating it, validating it, and handling exceptional values is deferred to L2.

1431. Common mistake

The common mistake is treating a schema change as a constructor problem: add the missing field, assign a convenient value, and continue. This skips the question of what the old data means and can change the player’s state without a declared compatibility obligation.

A related mistake is treating the build number and schema version as interchangeable. A build number identifies software; a schema version identifies saved data. Confusing them can cause a loader to apply the wrong interpretation or to assume that a particular build can read a format without evidence.

Another mistake is assuming that a version number makes a save compatible automatically. A schema version identifies the source format; it does not identify the preserved meaning or complete the migration.

1432. Guided practice

Analyze this proposed change without writing code. Assume the current reader is build build-3.

Version 2 stores a player’s best time in milliseconds:

{
  "schemaVersion": 2,
  "bestTimeMs": 90500,
  "level": 6
}

Version 3 stores the same result in seconds as a decimal and renames the field:

{
  "schemaVersion": 3,
  "bestTimeSeconds": 90.5,
  "level": 6
}

Write a four-part identification of the migration obligation:

  1. BUILD IDENTITY: identify the program attempting to read the save: build-3.
  2. SCHEMA IDENTITY: identify the saved-data version containing the old form: schema version 2.
  3. CHANGE: name the field, representation, and unit changes.
  4. MEANING: state what player result must remain equivalent, including the fact that 90500 milliseconds represents 90.5 seconds, and that level must remain unchanged.

Explicitly state why build-3 and schema version 2 are not the same identity. Do not design the transform procedure, choose a policy for null, or specify failure handling. Those decisions are deferred to 3.17 L2 — Design a safe migration.

1433. Validation / evidence

Your response is sufficient when it contains:

  • the reader build identity build-3;
  • the source schema identity 2;
  • the old field bestTimeMs and the new field bestTimeSeconds;
  • the change from milliseconds to seconds and the field rename;
  • an explicit statement that the build identifies the reader while the schema version identifies the saved-data format;
  • a statement that the player’s recorded best-time meaning and level must be preserved;
  • the interpretation of 90500 milliseconds as 90.5 seconds.

You are identifying one migration obligation, not implementing the migration. Do not add a null or failure policy at this stage. The next lesson will use this identified obligation to define the transform and its validation.

1434. Key takeaways

  • A saved-data change creates a migration obligation when older saves may be read by newer code.
  • Build identity identifies the reader; schema identity identifies the saved-data format.
  • A schema version identifies the source representation; it does not perform the migration or prove compatibility.
  • Identify the changed representation before deciding what player meaning must be preserved.
  • Detailed transform, validation, null, and failure-policy decisions belong to the safe-migration procedure in L2.

1435. Next lesson

Continue to 3.17 L2 — Design a safe migration / Diseñar una migración segura.

1436. Knowledge check

Answer these items for yourself before reading the answers.

What is the correct conclusion when an old save may be read by new code after a field change?

  • A. Migration code is always required as soon as the field changes.
  • B. No compatibility analysis is needed if the game can open the save.
  • C. The change creates a compatibility assessment; migration work is needed only if the old representation cannot be safely interpreted and preserved without explicit handling.
  • D. Migration is needed only when loading causes a crash.
Show answer and feedback

Answer: The change creates a compatibility assessment; migration work is needed only if the old representation cannot be safely interpreted and preserved without explicit handling.

Why: An old save that may be read by new code requires a compatibility assessment, not automatically a migration implementation. If the new reader can safely interpret the old representation and preserve its meaning, explicit migration code may not be necessary. Migration work is required when transformation, defaulting, rejection, or other handling is needed.

What should a migration preserve first when identifying its obligation?

  • A. The meaning of the player's valid game state.
  • B. The exact spelling and layout of every old field.
  • C. The implementation convenience of the new loader.
  • D. Any invalid value, without considering the new schema.
Show answer and feedback

Answer: The meaning of the player's valid game state.

Why: The representation may change. The first preservation question concerns the valid game meaning represented by the old data.

In the best-time example, what migration obligation is created by changing from milliseconds to seconds?

  • A. Copy 90500 unchanged into the seconds field.
  • B. Identify the source version and preserve the recorded time meaning while changing its representation to seconds.
  • C. Discard the old time because units are implementation details.
  • D. Reject every old save because unit changes cannot create obligations.
Show answer and feedback

Answer: Identify the source version and preserve the recorded time meaning while changing its representation to seconds.

Why: The change affects representation and units, but the recorded best-time meaning should remain equivalent. The source schema must also be identified so the later migration procedure can target the correct saves.

Which statement correctly distinguishes build identity from schema identity?

  • A. They are two names for the same version number.
  • B. Build identity describes the reader program, while schema identity describes the saved-data format.
  • C. Schema identity identifies the executable, while build identity identifies the save fields.
  • D. Neither identity is relevant to compatibility analysis.
Show answer and feedback

Answer: Build identity describes the reader program, while schema identity describes the saved-data format.

Why: The build identity tells you which program is attempting to load the data. The schema identity tells you which saved-data structure and rules the file claims to use. They are related but not interchangeable.

Put this lesson into practice

Related free templates and checklists

Support