Unit 03.04: Schemas that survive a model change
Schemas change. Which direction they change in determines whether in-flight data still validates.
Optional additions, and the enum trap
Adding an optional field is backward compatible. Widening an enum is not, in the direction people expect it to be.
The code validates old output against a new schema and a new value against an old one.
from pydantic import BaseModel
from typing import Literal, Optional
class TriageV1(BaseModel):
category: Literal["billing", "technical", "other"]
class TriageV2(BaseModel):
"""Added a category and an optional field. Old outputs still validate."""
category: Literal["billing", "technical", "account", "other"]
confidence: Optional[float] = None
old_output = {"category": "billing"}
print("old output against V2:", TriageV2(**old_output))
try:
TriageV1(**{"category": "account"})
except Exception as exc:
print("new value against V1: rejected -- widening is not backward compatible")
print("""
Two rules that keep a schema survivable:
- new fields are optional with a default, so old responses still validate
- widening an enum breaks OLD code reading NEW data, so deploy readers first
""")
The old output validates fine against V2 because the new field is optional. The new value is rejected by V1 - which means the breakage is in *old code reading new data*, not the other way round.
That has a deployment consequence worth remembering: deploy the readers before the writers. If a new category starts being produced while some instances still run the old schema, those instances reject valid data, and the failure looks like a model problem.
The mistake this prevents
The mistake is treating a schema change as a code change and deploying it everywhere at once. During any rolling deploy both versions run simultaneously, and the schema has to be valid for both for the length of that window.
Takeaway
New fields optional with defaults; widened enums need readers deployed first. During a rolling deploy both schema versions run at once, and both must accept the data in flight.
