Notes
Events
Everything starts as events: a user clicked, an order was placed, a payment went through, each with a timestamp. A log like Kafka stores them durably, in order, and lets many consumers read the same events independently. What you do next is either batch or stream.
- events: something happened,
- with a timestamp
- {user: 42, action: "order",
- amount: 999, ts: 10:42:07}
- Kafka keeps them in order,
- durably, for days
- many consumers read the
- same events independently
Batch
Batch processing stores the events, in a data lake or warehouse, and processes big chunks on a schedule: every night, crunch yesterday. Tools are Spark, MapReduce or plain SQL in a warehouse. It's simple, efficient and easy to re-run if you find a bug. The cost is latency: results arrive hours later.
- collect data, then process a
- whole chunk: last day, last hour
- MapReduce, Spark, SQL in a
- warehouse (BigQuery, Snowflake)
- + simple, efficient, easy to
- re-run when code has a bug
- − results arrive hours later
- e.g. daily revenue, invoices,
- model training, search indexes
Stream
Stream processing runs a job continuously that handles each event within seconds of it happening. Tools are Flink, Kafka Streams or Spark's streaming mode. You get fraud alerts, live dashboards, surge pricing and trending topics in seconds. The price is complexity: state, failures and ordering are much harder than in batch.
- a job runs forever, handling
- events as they arrive
- Flink, Kafka Streams,
- Spark Structured Streaming
- + results in seconds
- − state, failures and ordering
- are harder
- e.g. fraud checks, live
- dashboards, surge pricing,
- trending topics
Windows
A stream never ends, so 'total orders' has no final answer. Instead you aggregate over windows: fixed five-minute buckets, a sliding last-ten-minutes window, or sessions that end after a quiet period. 'More than five payments on one card in ten minutes' is a sliding-window fraud rule.
- streams never end, so group
- events into windows:
- tumbling: 10:00–10:05, 10:05–…
- sliding: last 5 min, every 1 min
- session: until 30 min of quiet
- "orders per city per minute"
- "payments per card in the
- last 10 minutes > 5 → flag"
Late events
A subtle problem: a phone goes offline and sends its two-minutes-past events at nine past. Event time, when it happened, differs from processing time, when it arrived. Count by event time, or reports drift. Stream engines use watermarks, an estimate of 'all events up to now have probably arrived', and a policy for events that come later still.
- a phone goes offline, sends
- its 10:02 events at 10:09
- event time: when it happened
- processing time: when it arrived
- count by event time, or
- reports are wrong
- watermarks: "probably all
- events up to 10:05 are in"
- late events: update or drop
Exactly once
When a stream job crashes, it restarts from a checkpoint and replays some events. Modern engines save their state and input positions together, so results inside the pipeline are effectively exactly once. But side effects outside it, like sending an email or charging a card, still need to be idempotent.
- failures cause replays →
- duplicates
- engines checkpoint state and
- input offsets together
- (Flink, Kafka transactions)
- effectively exactly-once
- INSIDE the pipeline
- external side effects still
- need idempotency (ep. 29)
Architectures
Two classic architectures. Lambda runs both: an accurate batch layer and a fast stream layer, merged at query time, but you maintain the same logic twice. Kappa streams everything and fixes mistakes by replaying the log through new code. In practice, many teams stream for live features and use warehouse SQL for reports.
- lambda: batch layer (accurate,
- slow) + speed layer (fast,
- approximate), merged
- − two codebases to keep equal
- kappa: stream only; to fix a
- bug, replay the log through
- new code
- + one codebase
- many teams: stream for live,
- warehouse SQL for reports
Say it like this
In an interview: send events into Kafka. Anything that needs results in seconds, like fraud checks, live counters or alerts, goes to a stream job with windows on event time. Anything that can wait, like reports, billing and training data, lands in a data lake and runs as batch. Keep sinks idempotent and the log replayable.
- events → Kafka
- needs seconds? (fraud, live
- counts, alerts) → Flink job,
- windows, event time
- can wait? (reports, billing,
- ML features) → lake + Spark /
- warehouse, nightly
- idempotent sinks, replayable log