Where the artifact stands
The order stream is deduplicated and honestly bucketed: 88.0% accurate, every bar in the right hour, 6 late events dropped on the floor. The drop was the strict window doing exactly what it promised. Tonight the promise gets renegotiated - and then, with the replay lever, outgrown.
★ What you walk out with: the watermark as a promise the system makes to itself about completeness, allowed lateness and the side output as the tools for keeping late money counted, and the replay move - the log-powered correction that turns "fresh but 93.6%" into "exact, end of day". Plus the reason no watermark setting can ever reach 100% at 2pm.
The watermark is a promise 8 min live
Event-time windows raised a question that processing time never faces: when is an hour FINISHED? Streaming systems answer with a watermark, and the Flink docs define it exactly: "A Watermark(t) declares that event time has reached time t in that stream, meaning that there should be no more elements from the stream with a timestamp t' <= t".
Live A promise about completeness, and who gets to make it 5 min ▶
Read the definition again slowly: a watermark is not a measurement, it is a declaration. The system announces "event time has reached t - nothing with a timestamp at or before t is still coming", and then acts on its own announcement: windows ending at or before t close and emit. A late event is what it sounds like when that promise turns out to be false. And the default consequence is unsentimental - late elements are dropped when the watermark is past the end of the window. That is precisely the mechanism behind session 4's six lost stragglers.
Which makes the watermark setting a business decision wearing an engineering costume. "How long does the lunch hour stay open for corrections?" is not a tuning knob - it is a question about how your data actually arrives, and about who would rather wait than restate a number. Somebody has to own the answer, and it is rarely the person writing the pipeline config.
A store's order tablet drops off wifi at 12:40 and syncs everything at 2:50pm. If the watermark allows three hours of lateness, the lunch-hour bar quietly corrects itself mid-afternoon and nobody notices. If it allows five minutes, lunch revenue is permanently understated in the live view - and the first person to discover it is whoever reconciles against the ledger.
Self-study Allowed lateness, and the side output for everything later 4 min ▶
Flink splits the decision into two levers. Allowed lateness keeps a window reopenable for a bounded time after the watermark passes its end: a straggler inside that grace period triggers the window to fire again, and those late firings are "updated results of a previous computation". Downstream consumers have to be ready for a number that was already published to change - which is exactly what a self-correcting hourly bar means.
And for events later than even THAT, there is sideOutputLateData: instead of vanishing, too-late events are captured to a side channel where they can be counted, monitored, and investigated. The professional standard is simple: late data may be excluded from a view, but it should never be invisible. A dropped-events counter you can see is a data-quality metric. A silent drop is a mystery you will meet again during an audit.
The log makes corrections possible 7 min live
Watermarks bound how long a LIVE view waits. But the events themselves never expired - they are sitting in the log, immutable and in order. That is where the real correction power lives, and two writers nailed it years apart.
Live Two sentences that carry the whole idea 4 min ▶
Nathan Marz compressed it to an equation: "Query = Function(All Data)". If the data is immutable - facts appended, never edited - then a bug in your query logic is a recoverable event: fix the function, recompute from the master dataset, and history itself is repaired. Mutable systems cannot do this, because the bug already overwrote the evidence.
Martin Kleppmann then flipped the mental model of where truth lives: "The database you read from is just a cached view of the event log." Replay the events in the same order and you reconstruct exactly what happened. And here is where session 4 pays off: event-time windows are deterministic - the same log through the same windows gives the same answer, every run. Determinism is what turns "replay" from a hopeful word into a guarantee that the rebuilt view CONVERGES.
This is what replay is for a stream: the batch job's old superpower, bought back. The nightly batch was complete because it waited for everything. A log-backed stream gets NOW from the live view and EXACT from the replay - off the same events, with no second data source to reconcile.
Self-study CDC and event sourcing - the deeper track 3 min ▶
Two named patterns take the log-as-truth idea further, and both live in chapter 11 of Kleppmann's Designing Data-Intensive Applications. Change data capture turns a database's own changes into a stream: every insert, update and delete becomes an event other systems can consume, so an existing application database becomes a log producer without being rewritten. Event sourcing goes further and stores the events AS the system of record - the application's state is always a view computed from them.
Same shape at two levels of commitment: CDC bolts the log onto a mutable database; event sourcing builds the whole system on the log from day one. The book is the canonical treatment, and it is the right next read once tonight's replay lever has made the idea physical.
Repair the dip, then replay the day ★ 22 min · everyone builds
Two new levers tonight. The watermark renegotiates how long an hour stays open. The replay reprocesses the whole log after the day ends. One buys back the stragglers; the other buys back everything.
Rebuild session 4's end state: Stream it ON, Idempotent consumer ON, Event-time windows ON. Confirm the headline reads 88.0% with 6 late events dropped - honest bars, leaking money.
Flip "Watermark: allow 3h lateness" and watch two numbers at once. The dropped counter falls back to 0 - the tablet-sync stragglers are caught and folded into their TRUE hours - and accuracy climbs to 93.6%. The dip is repaired without giving back the honest buckets: still event time, still the lunch rush in the lunch hour.
Now ask the obvious question: why not 100%? Read the counters. The dashboard shows $3,485 of the $3,723 that has truly happened by 2pm. The missing money has not ARRIVED yet - it is sitting on an offline tablet somewhere - and no semantics on earth can count an event the system has not received. Completeness is a moving target: 2pm's truth itself grows as stragglers land.
Find the replay lever. It is passport-gated at 4 stamps - and there is a visible bypass link for anyone who has not been collecting them, used honestly. Flip it: the view jumps to end of day, $6,115, accuracy 100.0%. Say precisely what happened: the FULL log was reprocessed through the SAME deterministic event-time windows, so the rebuilt view converged on the whole day's truth. Fresh view for now, replay for exact - both from one log.
Choosing the lateness number: session 4's homework asked how late an event can be before your business would rather drop it than restate the hour. That number IS your allowed lateness - the simulator's 3 hours is just the coffee shop's answer, because that is how long its tablets stay offline. Pick yours from arrival behavior and restatement tolerance, and write down who owns it.
Before session 6 15 min
- Turn your session 4 lateness number into one written sentence of policy: "windows for metric X stay open N hours; later events go to the side channel; owned by Y." Getting a name on that sentence is the hard part.
- Find out whether any pipeline you rely on has an actual replay path - not a belief, a tested procedure. If nobody knows, that is your answer.
- Count the tables your team streams (or plans to). Next to each, write how often its numbers change a decision: seconds, hours, or monthly. Bring the list - session 6 puts a price on it.
Three questions
1. What does a Watermark(t) actually declare?
Straight from the Flink docs: the watermark declares event time has reached t, meaning no more elements with a timestamp t' <= t are expected. It is a promise about completeness - not a measurement of it, which is why late events can still break it.
2. By default, what happens to an event that arrives after the watermark has passed the end of its window?
The Flink default is that late elements are dropped when the watermark is past the end of the window. Allowed lateness can keep a window reopenable for a bounded grace period, and sideOutputLateData can capture the rest - but both are choices you must make, not defaults.
3. Why can an end-of-day replay converge on the exact truth?
Two properties compound: the log preserves every fact in order (Kleppmann: replay the events and reconstruct exactly what happened), and event-time windows give identical answers on identical input. Fix code, reprocess, converge - Marz's Query = Function(All Data), made physical.
Answer all three to see your score.