Last year’s pitch kit is still in a dozen inboxes, and last year’s SKU is still on a printed price list. Last year’s invoice fields are still what a buyer’s clerk types into their ERP. You want to rename “traction” to “proof”, or split a pack size, or retire a clause. Additive first. If the change cannot stay compatible, run both shapes until a date you have written down, and name the one person who is allowed to archive the old one.
Schemas are the API of the relationship. Do not rename “traction” to “proof” and delete the old field in one night.
Why these three models
The decision is how to add, retire, or replace a field while last year’s counterparties still read last year’s shape. Independently deployed readers. A signal that will be misread if you stay silent. Two contract regimes that cannot be averaged.
Starting small: treat the overlap as a reduced-stakes stretch, then cut to one shape on a published timetable. Noisy monitoring: a silent rename arrives as a missing old fact and a new unexplained one. Regime-switching: two contract states coexist, then one dies. Equilibrium, complex, cycle. LOOP is folded. They have a next period, but the lever is the window and the writer, not a patience inequality. The Dual Schema Upgrade Window is named in prose. It is not a fourth model ID.
Many of those readers are trapped. The memo is already in a committee pack. The till code is already printed. Do not negotiate with a trapped reader as if they chose not to upgrade.
1. Keep both shapes cheap, then cut on a date
The useful result from starting small is more specific than “go slowly.” Counterparties differ in patience, the difference is private, and the way through is to run at a reduced level for a stated number of periods, then move to full scale as long as the other side does too. Early periods are confidence building. They are not supposed to be the profitable ones.3
Translate that onto an offer. The reduced-stakes stretch is two live shapes. Last year’s readers keep working. This year’s readers can move. Then you cut. A night switch to v2-only is the full-scale opening that the model says will shut the good counterparties out with the slow ones.
Ben Stopford puts the same geometry on events. Schemas are the APIs used by a publisher and a subscriber. They have to agree on how the message is formatted. Most of the time you keep that agreement with additive changes: new fields, not moves or deletes. Periodically you will need a break. The common repair is a Dual Schema Upgrade Window: stand up the old shape and the new shape together (in his worked case, orders-v1 and orders-v2) and give every reader a window in which to move.1
He lists four ways to run that window. Dual-publish both shapes. Write only the new shape and generate the old one from it. Keep writing the old shape and generate the new one until every reader has moved, then repoint the writer. Convert your own store, republish the new view, and keep writing both until the window closes. All four buy time. The last two can rebuild history if conversion starts from the first record.1 If last year’s traction column still has to join this year’s proof column, use one of those two.
The schedule has to be known. A counterparty who cannot see that the old field dies on a date has no reason to move, and a window with no close date becomes the new permanent mess: two names for one fact, forever. Relationship value in the field record rises with age, and reliability at a shock predicts whether the relationship survives it.8 Smashing last year’s readers to look modern spends that stock on a synonym.
Starting small, the coexistence lens
- Assumes: readers differ in how fast they can move, and you can run two scales of the same offer at once.
- Fits because: last year’s counterparties are still live and you cannot halt them.
- Breaks when: sitting through two shapes is not worth it, or you can halt every reader tonight.
- Evidence: grade A. Formal separation, plus field evidence that relationship value rises with age.
- Counteracts: cutting over to the new name in one night.
- May reinforce: a window that never closes.
2. They will read the silent rename as a new fact
You know “proof” is what you used to call “traction.” They do not. They observe the published shape, not the meeting in which you decided the synonym.
Under imperfect public monitoring, the other side sees a noisy signal of what you did, and they act on the signal. Punishment phases occur along the equilibrium path, including in periods when both sides know nobody cheated.3 Applied here: an investor who had traction in their model now sees a blank cell and a new column. A shop that ordered on the old SKU now sees a code that does not scan. Neither of them is being theatrical. They are reading the only public object you left them.
A rename is not a synonym. It is a delete plus an add. Avro matches fields by name. If the writer sends a field the reader does not know, the reader ignores it. If the reader expects a field the writer did not send, it uses a default or it errors.6 Rename the field and you have done both at once. The old reader looks for traction and does not find it. The new reader looks for proof on last year’s files and does not find it.
Compatibility rules say the same thing in operator language. Adding an optional field with a default is the change that old and new readers can both survive. Deleting a field that was never optional, or that never had a default, is not a compatible change, however obvious the new name feels in your mouth.5, 9 Martin Fowler’s expand-and-contract sequence is the same rule written for interfaces: augment so both versions work, migrate the readers, then remove the old version. Contract first and you have done the break without the window.7
This is why you do not “just tell them.” An email that says we now say proof is cheap talk next to a file that no longer contains traction. The file is the signal. The email is commentary. They will update their model from the file.
Noisy monitoring, the signal lens
- Assumes: they observe the published shape, not your intention.
- Fits because: a silent rename arrives as a missing old fact and a new unexplained one.
- Breaks when: each reader sees a different private map, so they cannot even coordinate a complaint.
- Evidence: grade A. Structural, and confirmed wherever the object is visible and the intent is not.
- Counteracts: believing a synonym will be read as a synonym.
- May reinforce: treating every confused reply as bad faith.
3. Name the two regimes. Do not average them.
Hamilton’s point, used here as structure rather than as a forecast, is that some series live in discrete states. Shifts are occasional. The observer does not see the shift and has to infer it from the series.4 You do not need his filter. You need the refusal to treat a two-state stretch as one noisy month.
Two contract regimes coexist, then one dies. During the window, some counterparties are on v1 rules and some are on v2 rules. An average “traction / proof” column describes no one you actually deal with. A shop still scanning the old barcode and a shop on the new pack size are not two noisy draws from one offer. They are two offers. The chain is not one state.
Name the transition in writing. The Dual Schema Upgrade Window is that named stretch: both topics (or both columns, or both invoice templates) live, then v1 is archived.1 Stopford’s reason for a single writer sits here. If three services write orders, a non-compatible upgrade needs a conjoined release. One writer can schedule the cut. Three writers cannot.2 The same is true of a pitch kit that sales, fundraising, and the website can each publish.
The break test is honest. If you can halt the world (one shop you own, one printed list you control, one form nobody else has copied) a single release is legal. If last year’s counterparties are still reading, the chain has two states whether you named them or not.
Regime switching, the two-state lens
- Assumes: the offer occupies discrete contract states, and transitions are occasional and named.
- Fits because: v1 and v2 have different rules, and an average across them describes nobody.
- Breaks when: you can halt every reader for one release, or no single writer can schedule the cut.
- Evidence: grade B+. Discrete-shift machinery is solid. Applied to offers it is structural, not estimated.
- Counteracts: treating a two-shape month as one noisy month.
- May reinforce: calling a label change a regime change.
Where the two shapes sit
Draw the boundary first. Inside: every field you publish that someone else has already wired into a model, a till, a WhatsApp order form, or a forwarded memo. Outside: whether “proof” is a better word, whether the new pack size is a better product, and whether last year’s contract still binds. Those are real. They are not this week’s compatibility call.
The stock that matters is the count of counterparties still on v1. You cannot set that stock. You change its flows. Announcement is not an outflow. A completed migration is. They do not move when you decide. They move when their next cycle forces a rewrite: the next order, the next committee, the next reprint of the price list.
Left outside on purpose: Kafka internals, and whether two of your own dashboards agree this second. Adjacent, not this cut.
Moves that do not require a night cut
Cheapest and most reversible first. Ruin sits on money, identity, and anything already inside a counterparty’s model. A silent break there can end a raise, a facility, or a channel. Cap any rename so it cannot touch those classes until both shapes are live.
- Ask whether the change can be additive. If yes, add the field. Do not rename. Do not delete. “Proof” can sit next to “traction” with the same number in both.
- If it cannot, stand up both shapes. Pitch-kit-v1 and pitch-kit-v2. Sku-v1 and sku-v2. Invoice-v1 and invoice-v2. Same fact, two formats, for a window you will date.
- Prefer generating the new shape from the old one if last year’s records still have to join. That is the up-convert that can be started from the first row.1
- Publish a field map, not a manifesto. One page: old name, new name, default if the old file is missing the new field, date the old name dies. The map is the signal. The essay is not.
- Name the close date and the writer in the same act. Sales may request a new line. Fundraising may request a new line. Only one owner publishes the kit and only that owner archives v1.2
- Do not reprint the shop’s price list from v2 only while any till still holds v1 codes. Two invoice formats in the market for thirty days is a window. Halting the line tonight is a different company.
What to schedule from the day you decide
Do now, by T+3, one afternoon, effect visible the same day. Inventory every published field on the pitch kit, the invoice, and the SKU list. Mark each one additive or breaking. For every breaking item, add the new field beside the old one and stop any delete. Reversible: you can drop an unused new column tomorrow. Dominant across every story about whether the new word is nicer.
Hedge, by T+14, premium is a month of dual-publishing, cover live before the next kit goes out. Stand up both shapes with a written close date and a named writer. Send the field map with the next file, not as a later apology. The cover has to be live before the next forwarded memo, or the hedge is a note to self. If they were always going to move this week you have carried an extra column for a month, and that is the entire downside.
Defer and trigger, size declared when the trigger is set. Archiving v1 is the irreversible cut. Pre-commit the observable: every named counterparty has produced one accepted file or one accepted order on v2, or the close date has arrived and the remaining names are on a written exception list with an owner. When either is true, the writer archives v1. Not before. Not in a Friday cleanup.
Watch the arrivals. The inventory lands this week. What the window tells you lands only after a cycle in which a slow reader had to act, which is often the next order or the next committee, not the next standup.
How a field change usually goes wrong
Name the shape before you explain the week. A clean cut after a dated window is goal-seeking: the v1 stock drains to zero. A rename with no window is a break, and the first independent reader is where it shows. Two shapes with no close date is a stretch that never ends, which looks stable and is just an unowned transition.
Has a rule changed, has an actor entered or left, has a measurement become a target? The last one fires. If the new word is what the board now asks for, people will delete the old column to look current, and last year’s “we always sent traction” then describes a target, not a kit. If a regulator or a buyer has mandated a new field name on a date you do not control, the window still holds and the close date is theirs, not yours. Write that down. Do not pretend you chose it.
The class to match is any interface that other programs already call: a schema, a remote API, a till code, a memo field an associate has already coded into a model. Across that class the failure is the same. The publisher moves. The subscribers do not, on the same night. Parallel change exists because that pattern is old.7
The directional base rate does not need a percentage. Windows without a close date persist. Night cuts produce a period in which two honest people disagree about what the company just claimed. A counterparty who “adopted” after a rename may have ignored the new field and kept a local alias. Do not credit the cut for a migration that did not happen. Credit a completed file on v2.
What these three cannot tell you
These models can tell you to keep both shapes and to date the cut. None of them can tell you whether the last distributor will reprint, or whether “proof” will raise more money than “traction.” You have agreed to be surprised by both. The belief that everyone remembers the synonym is the behavioural layer. It adds no lever, so it stayed out. Single-writer ownership is governance and sits in the lever list for the same reason.
One property no member models: once two shapes exist, people treat both as the product. Sales keep sending v1 because one investor liked it. Ops keep v2 because the new scan needs it. The Dual Schema Upgrade Window assumes a close. It does not produce one. A second writer, or no writer, is how the stretch hardens into the offer.
The one action that survives the ignorance: before the next kit, invoice, or price list goes out, write the close date and the name of the one person who may archive v1. If you cannot name both, the window has no owner and no end. What you have is two offers and a hope they converge.
Who has to move
The person who needs this is the one who can publish the kit, the invoice template, or the SKU list, and they are usually measured on shipping the new language, not on last year’s readers still being able to parse it. The cheapest first test costs an hour: list the live readers of the field you want to change, mark each one trapped or choosing, and refuse any delete that still has a trapped reader. That converts an argument about taste into a count, which is easier to hold in the meeting where someone wants the old column gone tonight.
Sources and notes
- Ben Stopford, Designing Event-Driven Systems: Concepts and Patterns for Streaming Services with Apache Kafka, O’Reilly, 2018, chapter 13, printed pp. 123 to 125. “Schemas are the APIs used by event-driven services, so a publisher and subscriber need to agree on exactly how a message is formatted.” Backward compatibility is maintained most of the time through additive changes (new fields, not moves or deletes). A non-compatible upgrade is commonly handled by a Dual Schema Upgrade Window, with two topics (orders-v1 and orders-v2). Four approaches are listed: dual-publish both schemas; write v2 and down-convert to v1; keep writing v1 and up-convert to v2 until clients upgrade, then repoint the writer; migrate internally and republish the v2 view while continuing to write both. All four give services a window in which they can upgrade. The last two handle back-population if conversion starts from offset 0. Book landing (login-walled): oreilly.com. Printed pages follow the book’s own pagination, confirmed against the text layer of the first-release PDF (printed = PDF minus 15).
- Stopford, ibid., chapter 13, printed p. 125, and chapter 11, printed pp. 105 to 107. One reason to apply the single-writer principle is that it makes schema upgrades simpler: if three different services write orders, a non-backward-compatible upgrade is much harder to schedule without a conjoined release. Responsibility for events of a type sits with one service, producing local points of consistency connected by the stream.
- George J. Mailath and Larry Samuelson, Repeated Games and Reputations: Long-Run Relationships, Oxford University Press, 2006. Starting small is section 5.2.4, following Watson: impatient types shirk immediately even against grim trigger; a high enough share of that type produces perpetual shirking; the separating structure has patient players choose moderate effort for a stated number of periods before escalating, with early periods described as confidence building. Imperfect public monitoring, and the finding that punishments occur along the equilibrium path in periods when both sides know nobody deviated, are section 7.2.1.
- James D. Hamilton, A New Approach to the Economic Analysis of Nonstationary Time Series and the Business Cycle, Econometrica 57(2), 1989, pages 357 to 384. Abstract (verified on the Society page): the parameters of an autoregression are viewed as the outcome of a discrete-state Markov process; the mean growth rate of a nonstationary series may be subject to occasional, discrete shifts; the econometrician does not observe those shifts directly and must infer whether and when they occurred from the behaviour of the series. No transition probability is claimed here for any offer or market. Landing: econometricsociety.org.
- Confluent, Schema Evolution and Compatibility Types. BACKWARD means consumers using the new schema can read data produced with the last schema. FORWARD means data produced with a new schema can be read by consumers using the last schema. FULL is both. Adding an optional field is allowed under backward, forward, and full. Deleting a field and remaining compatible requires that the field was optional or carried a default in the original version. Default compatibility type is BACKWARD. docs.confluent.io/platform/current/schema-registry/fundamentals/schema-evolution.html.
- Apache Avro, Specification, 1.11.1, Schema Resolution. A reader can always parse data because the writer’s schema is provided with it, and may resolve that data into a different schema. For records, fields are matched by name. If the writer has a field the reader does not, the value is ignored. If the reader has a field the writer does not, the reader uses the field’s default, and an error is signalled if no default was declared. avro.apache.org/docs/1.11.1/specification/#schema-resolution.
- Martin Fowler, Parallel Change (also called expand and contract). A backward-incompatible interface change is broken into three phases: expand (support old and new), migrate the clients, then contract (remove the old version). Database refactorings and remote API evolution are named as applications of the same sequence. martinfowler.com/bliki/ParallelChange.html.
- Rocco Macchiavello and Ameet Morjaria, The Value of Relationships: Evidence from a Supply Shock to Kenyan Rose Exports, University of Warwick Economic Research Paper 1032, later the American Economic Review. The abstract states that the value of the relationship increases with the age of the relationship, that during an exogenous negative supply shock sellers prioritise relationships consistently with the model, and that reliability at the time of the shock positively correlates with future survival and relationship value. wrap.warwick.ac.uk.
- Confluent Developer, Schema Compatibility pattern. Backwards compatibility: newer readers can consume events written by older writers. Compatible changes include deletion of fields (old writers still include the field, new readers ignore it) and addition of optional fields with a default (old writers omit the field, new readers use the default). Forwards compatibility: newer writers can produce events that older readers can still read. developer.confluent.io/patterns/event-stream/schema-compatibility.
A note on what is held back. Dual Schema Upgrade Window is the operational form of a held card in the registry. This piece uses it as a named practice, not as a fourth model, because the three lenses already supply the coexistence, the misread, and the two-state cut. Adding the held ID would have restated the same argument under a fourth heading.
Joshua Agonya Pi’Rwot, Founder.