DE//AGENT
Explore
Tutorial Lesson 5 of 10 · The Streaming Series community intermediate

Window a stream correctly — watermarks, dedupe, and late data

Stream processing in practice: start from the kafka-streaming template, pick event-time over processing-time windows, set a watermark you can defend, and prove what happens to late data. Checkpointing and an idempotent MERGE sink make the job restartable without duplicating output.

At a glance

When Aggregations over event streams — counts and sums per window; A streaming job that must survive restarts without duplicating output
Where Streaming
Why Windows turn infinite streams into finite, mergeable results — get the watermark wrong and you either drop late data silently or never emit.

Learning objectives

  • Choose event-time vs processing-time windows
  • Set a watermark and reason about late data
  • Run a structured-streaming job with checkpointing and an idempotent MERGE sink

What you need

  • The kafka-streaming template (checkpointing, watermarking, a dedupe stage, an idempotent MERGE sink)
  • [object Object]
  • A Kafka topic whose events carry an event timestamp and an event_id

Steps

  1. Start from the template — a structured-streaming job with checkpointing, watermarking, a dedupe stage and an idempotent MERGE sink to Delta/Iceberg. (from tpl-kafka-streaming )
  2. Decide time semantics first — choose event-time vs processing-time windows. (from project-kafka-spark-delta )
  3. Follow the reference architecture — Spark SS with watermark 2m and dedupe on event_id, raw_events appended to bronze, agg_5min as a windowed MERGE on the window key. (from project-kafka-spark-delta )
  4. Read with `startingOffsets=earliest` in dev only; latest in prod. (from project-kafka-spark-delta )
  5. Dedupe on `event_id` within the watermark; windowed aggregation to 5-minute tumbling windows, appended idempotently. (from project-kafka-spark-delta )
  6. Prove late-data behavior in tests — a late event beyond the watermark is dropped (documented, not silent), and replaying a batch yields the same aggregate. (from project-kafka-spark-delta )
  7. Watch the two classic failures — watermark too short means late data silently dropped; checkpoint lost means duplicates, fixed by making the sink idempotent. (from project-kafka-spark-delta )

Check yourself

  • An event arriving inside the 2-minute watermark joins its window; one beyond it is dropped — documented in the tests, not silent.
  • Replaying a batch yields the same aggregate because the MERGE is on the window key.

Worked example

Bring up the stack and produce events — from project-kafka-spark-delta

make up
make produce  # emits events, some deliberately late
make stream &

Implementation rules — from project-kafka-spark-delta

- Read with `startingOffsets=earliest` in dev only; latest in prod.
- Dedupe on `event_id` within the watermark.
- Windowed aggregation to 5-minute tumbling windows, appended idempotently.
- MERGE aggregates on the window key so replays converge.

The reference architecture — from project-kafka-spark-delta

Kafka (events) ─▶ Spark SS [watermark 2m, dedupe on event_id]
                  ├─▶ Delta: raw_events (append, bronze)
                  └─▶ Delta: agg_5min  (windowed, MERGE on window key)

Sourced from

Security scan

Last sweep 2026-10-24: 0 finding(s), 0 marked as examples.

Common gotchas

  • Watermark too short → late data silently dropped.
  • Read with `startingOffsets=earliest` in dev only; latest in prod.
  • Skewed key → one partition saturates; re-key.

Production considerations

  • Checkpoints on durable storage with lineage.
  • Lag + batch-duration metrics; alert on rising batch duration.

Diagram

windowed streaming job
   |
   |- Kafka events (event_id, event time)
   |
   |- watermark 2m --> dedupe on event_id
   |
   |- 5-minute tumbling windows --> aggregate
   |
   |- raw_events --> append (bronze)
   |- agg_5min  --> MERGE on window key (idempotent)
   |
    --> checkpoint on durable storage; alert on rising batch duration

Registry stats

Verification community · Oct 21, 2026
Completeness 81
Trust multiplier ×1.25
Composite 34.15 · adequate
Freshness 3 days since last source check
Difficulty intermediate
Version 0.1.0
License CC-BY-4.0
Security flags none