ContentsThe library

Moving Data Without Losing Any

Start the Stream Before You Read the Old Rows

Last timeReading Only What Changed

Loading history and following live changes are two jobs, and the join between them is where records vanish. The fix is an order, and a deliberate overlap.

Two jobs, one table

The last lesson ended with a limitation worth taking seriously: the log has no

history. It begins wherever the database currently keeps it from, typically hours

or days back, and the rows that existed before that point appear in it nowhere.

So standing up a new consumer means two jobs. Read the rows that already exist,

which is a query against the table. Follow the changes from now on, which is a

read of the log. Neither does the other job, and no amount of configuration makes

one of them do both, because the information is not there to do it with.

Two jobs means a boundary, and the boundary is the whole problem. Every row has

to be covered by at least one of the two paths, and the obvious way of arranging

them leaves a set of rows covered by neither.

The window that loses

The natural order is to load the history and then start following changes. It is

how everybody does it the first time, and it reads as obviously correct: finish

the old, begin the new.

FIG 1The obvious order, and the rows it drops
steptimeactionrow 7781in the destinationwhat happened
109:00snapshot query beginsstatus packednot yetThe snapshot reads the table as it was at this instant. Row 7781 is read early, with status packed.
209:40the row is shippedstatus shippedpackedThe snapshot has already passed this row. The stream is not running yet. This change is observed by nothing.
311:20snapshot finishesstatus shippedpackedTwo hours and twenty minutes of changes have happened during the snapshot, none of them captured.
411:20stream subscribes from nowstatus shippedpackedThe stream starts here and will carry every future change. It carries nothing from before.
5next yearnothing further happens to the rowstatus shippedpacked, wrong foreverThe destination says packed. Nothing will ever correct it, because a correction requires a change event and the change already happened.
5 steps
The loss is silent in the way lesson one described: both counts match, because the destination has the row, and nothing is comparing values. It is also permanent for any row that is never touched again, which in most tables is the majority of them.

Three things about that window are worth drawing out, because each one defeats a

tempting shortcut.

It is proportional to the snapshot. A hundred million rows take hours, and every

minute of those hours is a minute of changes nobody captures. The more data you

have, the more you lose, which is precisely the wrong direction.

Shrinking it does not fix it. A faster snapshot, a read replica, a maintenance

window at four in the morning: each makes the window smaller and none makes it

zero, and a window that loses data silently is not safe at any size. Teams have

run this design for years and discovered the gap when a customer asked why a

closed account was still receiving reports.

And doing it the other way round is no better. Subscribe first, then snapshot,

discarding the stream output while the snapshot runs, and the same changes fall

in the same hole.

The lesson stops here

3 more paragraphs to go

You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.

The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.

See the planThe contents

This is the reading half

Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.

The contents

The rest of this course

  1. 01Nothing Crashed, Nothing Alerted, and the Total Is Short by Nine Hundred
  2. 02The Sender Cannot Tell Which Half of the Journey Failedopening only
  3. 03Run It Twice on Purpose and See What Breaksopening only
  4. 04Two Writes, and the Order Between Them Is the Whole Designopening only
  5. 05The Row Was Saved at 10:04 and Became Visible at 10:06opening only
  6. 06Start the Stream Before You Read the Old Rowsyou are here
  7. 07Tuesday's Number Arrived on Friday and Tuesday Is Already Publishedopening only
  8. 08The Check Takes Four Minutes a Day and Almost Nobody Runs Itopening only

Read alongside