1424. Lesson identity
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:
- Source representation: What did the old save contain, and which schema version produced it?
- Preserved meaning: What valid player state does that data represent and need to retain?
- 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:
creditsmoves intowallet.credits, andwallet.debtis 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:
- BUILD IDENTITY: identify the program attempting to read the save:
build-3. - SCHEMA IDENTITY: identify the saved-data version containing the old form: schema version
2. - CHANGE: name the field, representation, and unit changes.
- MEANING: state what player result must remain equivalent, including the fact that
90500milliseconds represents90.5seconds, and thatlevelmust 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
bestTimeMsand the new fieldbestTimeSeconds; - 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
levelmust be preserved; - the interpretation of
90500milliseconds as90.5seconds.
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?
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?
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?
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?
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.