The Permanence Problem
events written TODAY get consumed for YEARS:
[2024 topic data] ──► consumed by services deployed in 2026,
replayed in 2027, audited in 2030.
you cannot UPDATE history. old payloads stay as-is.
every consumer ever written must keep reading them.
so the question isn't "what schema?" but
"how does the schema CHANGE SAFELY, repeatedly, forever?"
The Compatibility Directions
BACKWARD compatible: new consumers read OLD events.
(required when topics retain/replay history — always!)
FORWARD compatible: old consumers read NEW events.
(required during rolling deploys — always!)
FULL: both. the production default for shared topics.
concrete rules that preserve compatibility (avro/protobuf-style):
SAFE ✓ BREAKING ✗
add field w/ DEFAULT add required field
remove field (was optional) remove field w/ consumers of it
widen numeric types (i32→i64) narrow types (i64→i32)
add union branch remove union branch
rename ONLY via aliases plain rename
golden rule: ADDITIVE with defaults; deletions only after
a full consumer-census confirms nobody reads the field.
The Rolling-Deploy Window
during ANY deploy, old and new versions coexist LIVE:
t0: all consumers v1 producer v1
t1: some consumers v2 ← producer STILL v1
t2: producer v2 ← consumers mixed v1+v2 ← danger zone!
t3: all consumers v2
forward-compat needed at t2: v1 consumers must not explode
on v2 events. this is why "add optional field" is safe
("unknown fields ignored" semantics) and
"change field meaning" never is.
Versioning Strategies
| Strategy | Mechanism | Tradeoff |
|---|---|---|
| In-place evolution | additive-only changes | cleanest; discipline required |
| Envelope version | {v: 2, data: {…}} | explicit; dual-code paths |
| New topic per major | orders.v2 topic | clean breaks; fan-out migration |
| Upcasting layer | transform old→current at read | hides versions from consumers |
pragmatic combo:
minor changes: evolve in place (additive)
breaking needs: new MAJOR type/topic + overlap window +
deprecation timeline for v1
upcasting when history-replay demands uniform current shape
(event-sourced systems especially).
Governance That Actually Works
□ SCHEMA REGISTRY enforces compatibility at publish time
(bad schemas rejected BEFORE they poison streams)
□ CI contract tests: producers validated against registered
schemas; consumers pinned to compatibility mode
□ CONSUMER CENSUS before any removal: who reads field X?
(registry usage tracking answers this)
□ DEPRECATION windows communicated like API deprecations —
because events ARE APIs with worse rollback stories.
Interview Framing
“We need to add tax_amount to OrderPlaced without downtime” scored walk-through: classify change (additive+default = backward&forward safe), rolling-deploy window explained, registry enforcement mentioned, and the removal-later path sketched (census → deprecate). Candidates who treat event schemas like internal function signatures fail this question everywhere it appears.
Premium Content
Unlock Event Schema Evolution and all premium lessons with a subscription.
All premium lessons
Ad-free experience
Priority support
From ₹199.99/year — See plans