Your streaming aggregate reports 2% lower daily revenue than the batch reconciliation. Both are "correct". Explain what is happening and how you resolve it.
Show the full answer Hide the answer
The likely cause: silently dropped late data
The streaming job windows by event time and closes each window when the watermark passes. Records arriving after that are discarded — which is the default behaviour in several frameworks and produces exactly this symptom: a consistent small shortfall against a batch job that sees everything.
Two percent is a plausible tail for a mobile client population with intermittent connectivity.
Confirm before fixing
Instrument the drop. Count records arriving after their window closed, and record how late they were. That gives you both the confirmation and the distribution you need to choose the remedy — and it should have been there from the start, because a silent drop is the failure mode this design has.
Rule out the alternatives while you are there: a difference in timezone handling between the two jobs, a difference in what is included (refunds, cancellations, tax), and duplicate suppression differing between the paths. Any of those produces a similar-looking discrepancy and none is fixed by watermark changes.
The three remedies
Increase the watermark allowance. Measure the actual arrival delay distribution and set it at a percentile — p99 admits nearly everything at the cost of that much result latency. Simple, and it trades freshness directly.
Emit revisions. Allow late records to update an already-emitted window. Correct, and it requires every downstream consumer to handle a restatement — which is a contract change, not a configuration one.
Route late data to a side output and reconcile periodically. Keeps the streaming path fast and makes the correction explicit, at the cost of a second path.
What to tell the business
The streaming number is provisional and the batch number is final, and that is a property of unbounded data rather than a defect. Which one appears on a report should be a decision: real-time dashboards use the provisional figure with a stated staleness caveat; anything financial or externally reported uses the reconciled one.
Presenting a provisional figure as final is the actual error, and it is a design decision rather than a bug.