Lesson 5 / 25
Schemas and Evolution
Evolve event schemas without breaking existing consumers.
Events are a public API
Once other teams consume an event, its shape is a contract, often longer-lived than a REST API because old events may be replayed years later. Describe events with a schema (JSON Schema, Avro or Protocol Buffers) and store schemas in a schema registry that checks compatibility when a producer registers a new version. Compatibility modes: backward compatible (new consumers can read old events, so you may delete fields or add optional fields with defaults), forward compatible (old consumers can read new events, so you may add fields they ignore), and full (both). Safe changes: adding an optional field, adding a new event type. Breaking changes: renaming or removing a required field, changing a type, changing meaning. For a breaking change, publish a new version (OrderPlaced.v2) alongside the old one, migrate consumers, then retire the old version.
An additive, compatible change in Avro
The new field has a default, so old and new readers both cope.
{
"type": "record",
"name": "OrderPlaced",
"namespace": "com.shop.orders",
"fields": [
{ "name": "orderId", "type": "string" },
{ "name": "customerId", "type": "string" },
{ "name": "totalMinor", "type": "long" },
{ "name": "currency", "type": "string" },
{ "name": "channel", "type": "string", "default": "web" }
]
}Adding a column to a printed form
Adding an optional box at the bottom of a form is fine; old clerks ignore it. Renaming the "Amount" box to "Total" means every clerk in every branch must be retrained at once.
Quick check: Which change is usually safe for existing consumers?
- Renaming orderId to id
- Adding an optional field with a default value
- Changing totalMinor from long to string
- Removing the currency field
Answer
Adding an optional field with a default value — Adding optional fields with defaults is compatible; renames, type changes and removals break readers.