Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Forward Compatibility
HLD

Forward Compatibility

Old code reading new data — the harder direction, and the design tricks that make it possible.

The Definition

 FORWARD COMPATIBLE change:
   OLD version of code handles data from the NEW version

   new producer ──► [ messages / responses ] ──► old consumer ✓

 why it's hard: you cannot patch deployed old consumers.
 mobile apps ship weeks late; third parties never upgrade.
 forward compatibility is a PROMISE YOU MAKE to software
 you don't control

Why Bother

 scenario: producers deploy before consumers (rolling updates,
 event queues, partner feeds):
 
 t0: producer v2 starts emitting extra fields
 t1: consumer v1 still running for hours/weeks
     → must not crash on unknown fields
 
 without forward compat, EVERY producer change requires
 synchronized consumer deploys — coordination cost that
 scales with team count. with it, independent deploys.

Techniques That Buy Forward Compatibility

 1. SKIP-UNKNOWN encoding:
    protobuf/thrift: old readers skip unseen field numbers natively
    JSON convention: readers ignore unrecognized keys
    
 2. NEVER repurpose meaning silently:
    "count" stays a count forever; semantics changes = new field
    old_field meaning-shift breaks old readers SILENTLY (worst class)
    
 3. RESERVED vocabulary:
    document that unknown enum values map to UNKNOWN, not error;
    clients branch on classes of values where possible
    
 4. VERSIONED WRAPPERS for breaking eras:
    { "v": 2, "payload": {...} } → old readers route by v,
    both shapes coexist during migration

Protobuf’s Native Gift

 message Trip {
   string trip_id = 1;
   reserved 2;                 // retired forever, never reused
   int64  fare_cents = 3;
 }
 
 old binary reader meets new message:
   reads tags 1,3; skips tag 7 it doesn't know → succeeds
   forward AND backward compatible BY ENCODING DESIGN
 
 this is the deep reason protobuf dominates internal RPC:
 compatibility isn't convention, it's wire format physics

The Limits

ChangeForward compatible?
Add field✓ with tolerant readers
Remove field✓ if old readers tolerate absence
Change type✗ old reader misparses
Split/merge fields✗ semantic break
Reorder positional formats✗ never (avoid positional encodings)

Truly breaking changes still need versions — forward compatibility buys additive freedom only.

Combining Both Directions

 FULL compatibility = backward + forward simultaneously:
   tolerant readers + additive writers + stable identities

 achieved state: any producer version talks to any consumer version
 → rolling deploys without locks, queues drain across upgrades,
   mobile apps lag years harmlessly
 
 cost: discipline everywhere, reserved-tag hygiene,
       deprecation telemetry — cheap compared to the alternative:
       org-wide synchronized releases

Interview Framing

The differentiator question after backward-compat answers: “and the reverse direction?” Scored shape: define it, explain who forces you to care (mobile lag, queue replay, partners), credit protobuf’s skip-unknown mechanics, and close on full compatibility as the enabler of independent deploys. Candidates who call it “impossible” miss that tolerant-reader conventions deliver it in practice.

My Private Notes

Notes are auto-saved locally to this device.