Streaming's hardest problems are not throughput but time: events arrive out of order, delayed, and duplicated, yet the questions we ask ("how many orders in the 10:00–10:05 window?") are about when things happened, not when they showed up. This page is the semantics course beneath every stream processor — the concepts are engine-independent and transfer verbatim between Flink, Kafka Streams, Spark, and the streaming databases.
Event time is the timestamp carried by the event (when the order was placed); processing time is the clock on the machine handling it (when your operator saw it). The gap between them — skew — is unbounded in real systems: mobile clients buffer offline, producers retry, partitions lag, a stalled consumer replays an hour in a minute. Processing-time results are therefore non-reproducible: rerun the same data tomorrow and every window changes. The streaming discipline in one sentence: compute in event time, monitor in processing time. Reprocessing history (the log's replay superpower) only yields correct results if your logic was event-time-based to begin with.
The open question every window scheme faces: when may a window close? Waiting forever is complete but useless; closing immediately is fast but wrong. Watermarks are the mechanism that answers it.
A watermark at event-time T is the system's claim: "expect no further events with timestamps ≤ T." Watermarks flow through the pipeline with the data; when the watermark passes a window's end, the window fires. They are generated at the sources — typically as observed-max-timestamp minus a bounded-delay allowance (e.g., 30 seconds) — and multi-input operators take the minimum of their inputs' watermarks, so one slow or idle partition holds back the whole pipeline's clock (the classic "my windows never fire" bug: an idle source; the fix: idleness timeouts).
The watermark is a bet, not a fact. Set the allowed delay small and you fire fast but declare stragglers late; set it large and results are complete but slow. That latency-vs-completeness dial is irreducible — the streaming version of a conclusion every distributed-systems course reaches: you cannot know a distributed input is complete; you can only decide when to stop waiting.
Events arriving behind the watermark need an explicit decision:
Production systems commonly pair fast approximate streaming results with periodic batch correction — honest about the bet the watermark made. Choose per use-case: billing tolerates latency but not loss; alerting tolerates loss but not latency.
Every streaming computation answers four questions (the Dataflow/Beam model): What are you computing (the aggregation)? Where in event time (the window)? When in processing time do you emit (triggers/watermarks)? How do refinements relate (discard/accumulate/retract)? Engines differ in syntax and defaults; the four questions — and the watermark bet — are the invariant core worth actually understanding.