THIS EXPLANATION
THE ROOM
CDA·249 Computing, Data & AI 6 MIN · 8 STATIONS

Two systems, one record

A Socratic walk-through of two systems, one record — reasoned out one step at a time, not lectured.

abcdefgh
a

The question we started with

THE QUESTION #

How can two systems both own the same record for a year without drifting apart?

A replacement goes live alongside the system it replaces. For the next year both are in use — some channels write to the old one, some to the new — and both hold the same customer records. The plan says they will be kept in sync.

Pause on that phrase. Two independent stores accepting independent writes, connected by a link that takes some non-zero time, are not synchronised; they are two states that occasionally agree. So the honest question is not how to keep them identical, but what weaker guarantee is achievable, and what has to be true for that guarantee to be enough.

b

Reasoning it through

REASONING #

Notice the trouble starts with something more basic than conflict. Send every change from A to B, and B applies it — which is itself a change in B, which the link then sends back to A, which applies it, which sends it back. The replication loop is the first thing that breaks, and it breaks immediately. Fixing it requires each change to carry where it came from, so a system can recognise an echo of its own write and decline to bounce it. Origin tagging is not an optimisation; without it nothing works at all.

With echoes suppressed, the real problem surfaces: both sides can change the same record before either has heard about the other. What are the options?

You can decide after the fact, with a resolution rule. Last-writer-wins is the usual choice and is worth being clear-eyed about: it does not merge, it discards. One user's change silently vanishes, and if the two systems' clocks disagree it may not even be the later one that survives. Field-level merging is better where the fields are genuinely independent, but it can compose two half-valid updates into a record that neither party intended and no rule ever validated.

Or you can arrange that the conflict cannot arise. Give every record exactly one owner at a time — for this customer, the old system is authoritative and the new one holds a read-only copy; for that customer, the reverse. Writes to the non-owning side are refused or routed. Now the link is one-directional per record even though it is bidirectional in aggregate, and migration becomes a matter of moving ownership record by record rather than switching everything on one night. This is why coexistence periods are usually structured around ownership rather than around clever merging: avoiding a conflict is cheaper and more honest than adjudicating one.

Does that dissolve the problem entirely? No, and the residue is instructive. Ownership must be recorded somewhere both sides consult, and that register is itself a shared piece of state. Transfers of ownership need a moment when neither side accepts writes, or a version fence, or you have simply relocated the race. And reads still hit whichever side the channel points at, so a caller can read a stale copy even where writes never conflict — which matters enormously if the read informs a decision that is then written back.

Now ask what makes the arrangement survivable over a year, since correctness of the mechanism is not the same as health of the deployment. The answer is that you measure divergence directly. Not "is the pipeline running" — a pipeline can be perfectly healthy while dropping a class of records it cannot map. A reconciler walks both stores on a cycle and counts records that differ, producing a number that should be small and should return to zero. That number is the actual service level, and drift that is bounded and detected is a working system, while drift that is unmeasured is a discovery waiting for year-end.

One more asymmetry deserves attention. The two models are not the same shape, or there would be no project. The old system has fields the new one has no home for; the new one has fields the old cannot represent. A record that round-trips through the narrower model loses whatever the narrower model cannot hold — so a change made in the new system, replicated to the old, and later replicated back can come home diminished. Preserving unmapped fields untouched rather than reconstructing the record wholesale is what prevents that.

c

The analogy

THE ANALOGY #
THE FIGURE

Two branch offices of a bank keeping ledgers for the same customers before any wire connected them, exchanging updates by courier. The courier makes conflicts possible, so the practical arrangement was that each customer belonged to a home branch: the other branch could read the balance from the last delivery and take instructions, but only the home branch posted. Periodically the two ledgers were compared line by line, and the size of the discrepancy — not the punctuality of the courier — was what told the manager whether the arrangement was working.

WHERE IT BREAKS DOWN

couriers deliver in order and rarely duplicate, whereas a replication link reorders, retries, and delivers the same change twice, so every applied change must be safe to apply again and safe to apply late — a demand no clerk ever faced.

d

Clarifying the model

THE MODEL #

Three refinements.

First, "eventually consistent" is a real guarantee, not a euphemism, but it only holds if the link makes progress. Eventual consistency plus a poison message that halts the stream is not eventual anything. The property people rely on is really bounded staleness with a detector, and both halves have to be engineered.

Second, identity is prior to synchronisation. The two systems have different key spaces, and a durable mapping between them — surviving restarts, replays, and merges of duplicate records — is the foundation everything else stands on. A great deal of coexistence pain traces back to identity mapping treated as a lookup table rather than as the shared authority it actually is.

Third, an idempotent, version-checked apply is what makes the whole thing operable. If applying a change twice is harmless and applying an older version is a no-op, then the recovery procedure for almost any failure is to replay, and replay is a procedure people can execute at three in the morning. Without it, every incident becomes bespoke.

e

A picture of it

THE PICTURE #
Two systems, one record
Two systems, one record the write enters at the owning side only, which is why no conflict appears in this exchange -- the refusal in the middle is the design working, not an error. The version on the event is what makes a repeated or late delivery harmless. The note marks the echo suppression. The final three messages are the part usually left out: an independent comparison of both stores, whose divergence count -- not the health of the link -- is what tells you the arrangement is holding. {"generator":"[email protected]","source":"../Socrates/.diagram-cache/_src/two-systems-one-record.md","sourceIndex":1,"sourceLine":4,"sourceHash":"620e774538bf566f2bc92a41ce464ef3c7ff629f7662fe3bcba0130c0e373ee1","diagramType":"sequence","layoutVariant":"source","repairedDuplicateIds":[],"motion":"entrance-with-reduced-motion-fallback","presentation":"editorial","attempt":1,"viewBox":{"x":0,"y":0,"width":1392,"height":782},"qa":{"passed":true,"findings":[]}} Reconciler 01 Replacement 02 Relay 03 Legacy 04 Teller 05 origin tag stops the echo returning update address on record 4471 1 change event, version 8, origin legacy 2 apply if version is newer 3 applied at version 8 4 local edit refused, record owned by legacy 5 read record 4471 6 read record 4471 7 divergence count for the cycle 8
KINDSlifelineparticipantmessage

How to readthe write enters at the owning side only, which is why no conflict appears in this exchange — the refusal in the middle is the design working, not an error. The version on the event is what makes a repeated or late delivery harmless. The note marks the echo suppression. The final three messages are the part usually left out: an independent comparison of both stores, whose divergence count — not the health of the link — is what tells you the arrangement is holding.

f

What became clearer

WHAT CLEARED #
WHAT CLEARED

Two systems cannot be kept identical, so the workable designs either remove the conflict rather than resolve it — one owner per record, migrated piece by piece — or accept a resolution rule and are clear that it discards data. Around whichever choice is made sit three unglamorous requirements that decide whether the year is survivable: origin tags so changes do not echo, versioned idempotent application so replay is a safe recovery, and a reconciler whose divergence count makes drift a measurement rather than a surprise.

g

Where to go next

ONWARD #
  • How ownership of a record is transferred without opening a window in which both sides accept writes.
  • What conflict resolution can honestly offer when two updates touch genuinely dependent fields.
  • How to choose a reconciliation cycle when a full comparison is too expensive to run often.
h

Key terms

TERMS #
TermWhat it means
Change data capturederiving a stream of changes from a database's own log rather than by polling.
Idempotencethe property that applying the same change more than once has the same effect as applying it once.
Origin taga marker on a replicated change identifying where it came from, used to stop echo loops.
Last-writer-winsa conflict rule that keeps the change with the highest timestamp and discards the other.
Reconciliationan independent comparison of two stores that reports how many records differ.

Every term the collection defines is gathered in the glossary.

Nearby on the shelf

4