DEV Community

Serguey Asael Shinder
Serguey Asael Shinder

Posted on

Two Sources of Truth Will Always Disagree

Somewhere in your system
the same fact is stored twice.

A count in a column
and the rows it is counting.

A status on the order
and a status on the payment.

An email in the profile service
and the same email
in the list you send from.

Today they agree.

They will not agree forever.

Drift does not need a bug.

It needs one write that lands
and one that does not,
one job that failed quietly at three in the morning,
one migration that touched
the table and not the cache.

After that the two numbers
are simply different,
and nothing in the system
is unhappy about it.

The report is unhappy.

The customer is unhappy.

You find out weeks later
in a message that says
"these two screens do not match",
and you cannot tell
which one is lying.

So decide who owns the fact.

One place holds it.

Everything else derives it,
or asks for it,
or caches it with an obvious expiry
and an obvious name.

A field called total is a claim.

A field called cached_total_at_midnight
is a confession,
and confessions are easier to debug.

Sometimes you cannot avoid the copy.

Two services, two databases,
a boundary you do not control.

Then do not pretend.

Write the reconciliation job
on the same day
you write the copy,
not after the first mismatch.

And make it report the difference
before it corrects it.

A job that silently repairs drift
hides the thing
you most need to see:
how often, and from where.

The version of this that hurts most
is the one nobody designed.

Somebody denormalised a column
for a slow page in 2022.

It was a performance fix
and it worked,
and it quietly became
a second truth
that nobody agreed to maintain.

Every duplicated fact
is a promise
that two pieces of code
will stay in step
for as long as the system lives.

They will not.

Store it once.

Everything else is a copy,
and copies age.

– Serguey Asael Shinder

Top comments (0)