Batch + stream hybrids vs stream-only architectures, when to unify the two paths, and how to reprocess in streaming.
⏱ 17 min readTopics chapter readerLevel · Streaming & Real-Time
01 · Orientation
What You'll Master Here
You want fresh and accurate at once. Lambda gets there with two paths (batch + stream) merged; Kappa with one streaming path that you replay to reprocess.
⏱ 5 min · Topic 1 of 7
This chapter zooms out from individual streaming mechanics to whole-system architecture. The central question is timeless: you want data that is both fresh (streaming) and complete/accurate (batch), so how do you combine them? The two famous answers are the Lambda and Kappa architectures, and the modern streaming-first view.
Lambda runs batch and streaming side by side and merges their results. Kappa argues that is needless duplication and keeps a single streaming path, reprocessing by replaying the log. The debate between them is really a debate about complexity versus capability, and it teaches you how to think about freshness and reprocessing at the architecture level.
By the end you will be able to draw both architectures, explain the "two codebases" problem that motivated Kappa, reason about how reprocessing works in each, and make a sober recommendation, which, as usual, favours the simplest design that meets the requirement.
Core mental model
You want fresh and accurate at once. Lambda gets there with two paths (batch + stream) merged; Kappa with one streaming path that you replay to reprocess.
Why it matters
These architectures frame how real companies reconcile real-time and historical correctness. Understanding the trade-off lets you avoid the classic mistake of building and maintaining two parallel systems when one would do, or forcing everything into streaming when batch is simpler.
Lambda architecture
A design with a batch layer (accurate) and a speed layer (fast), merged into one serving view.
Kappa architecture
A streaming-only design that reprocesses history by replaying the log through the same code.
reprocessing
Recomputing results after a logic change or bug, the operation that distinguishes the two.
serving layer
Where query-ready results live for consumers, fed by the architecture above it.
Four real systems, described without their labelsName the architecture. Two of these four do not have a famous name, and that is the point.0 of 4 answered
A Flink job computes live counts into a serving store. Every night a Spark job recomputes the same counts from the warehouse, and the dashboard reads the batch numbers for anything older than today.
Everything lands in Kafka with a 30-day retention. One Flink job builds every table. When the logic changes they redeploy and replay the last 30 days.
Most tables are built by dbt on a nightly schedule. Two of them — fraud signals and live inventory — are built by a separate streaming job, and nothing recomputes those in batch.
A CDC stream keeps the warehouse within five minutes of the source. Everything downstream of the warehouse is scheduled SQL.
Common mistake
Adopting Lambda’s two-path complexity without needing both layers. You maintain and reconcile two codebases forever for freshness or accuracy you could get more simply.
Better habit
Frame the choice as freshness + accuracy versus complexity.
Prefer one path (Kappa-style) when a single engine can meet the need.
Treat reprocessing as a first-class design requirement.
The big idea
The whole debate is "one path or two?". Lambda accepts two paths for capability; Kappa keeps one for simplicity. The right answer is the simplest architecture that delivers the required freshness and accuracy.
How to study this chapter
Read Lambda, then Kappa, then reprocessing (the crux), then choosing. The reprocessing topic is what really separates the two architectures.
Remember this
Lambda and Kappa are two answers to "fresh and accurate at once": two merged paths versus one replayable stream; the choice is capability versus complexity.
Practice2 prompts
State the core difference between Lambda and Kappa in one sentence.
Explain why wanting both freshness and accuracy creates this architectural problem.
02 · Architecture 1
Lambda: Batch + Speed Layers
batch (accurate, slow) + speed (fast, approximate), merged at serving. Power at the price of duplicated logic.
⏱ 6 min · Topic 2 of 7
The Lambda architecture, named by Nathan Marz, runs two parallel pipelines over the same incoming data. The batch layer reprocesses all the data periodically to produce accurate, complete results, slow but correct. The speed layer processes the same data as a stream to produce fast, approximate, up-to-the-second results. A serving layer merges them: recent data comes from the speed layer, older data from the batch layer.
The appeal is that you get the best of both: real-time freshness from the speed layer and eventually-corrected accuracy from the batch layer, which overwrites the approximate results as it catches up. For years this was the standard way to build systems that needed both, and many large platforms ran it.
The cost is the defining problem of Lambda: two codebases. The same business logic (say, "count active users") must be implemented twice, once in batch (Spark/SQL) and once in streaming (Flink/Kafka Streams), and kept perfectly in sync. Any divergence means the two layers disagree, and maintaining two implementations of every metric is a heavy, bug-prone burden.
Core mental model
Lambda = two pipelines over the same data: batch (accurate, slow) + speed (fast, approximate), merged at serving. Power at the price of duplicated logic.
Why it matters
Lambda is still common and worth understanding, but its two-codebase tax is exactly the pain that motivated Kappa and the streaming-first movement. Recognising that tax is key to not paying it unnecessarily.
batch layer
The accurate, complete pipeline that periodically reprocesses all data.
speed layer
The real-time streaming pipeline producing fast, approximate results.
serving layer
Where batch and speed results are merged for queries.
two-codebase problem
Maintaining the same logic twice (batch and streaming), kept in sync, Lambda’s core drawback.
Lambda · one metric, two implementationsThe bet is that you can keep two implementations agreeing. Change the logic and see the bill.0 places to change
The business asks for
layer
what it reports today
batch (Spark / dbt)
£40,076.50
speed (Flink)
£40,076.50
the gap somebody has to explain
£0
The two layers agreeBoth layers agree.
What Lambda actually costsNot compute — compute is the cheap part. It costs a permanent obligation to change two codebases in two languages on two release cadences and keep them producing the same number. That obligation is affordable when the logic is stable and expensive when it is not, which is why “how often does this logic change?” is the first question to ask before naming an architecture.
Common mistake
Letting the batch and speed implementations of the same metric drift apart. The two layers disagree, and the merged result is inconsistent and untrustworthy.
Better habit
If using Lambda, keep batch and speed logic rigorously in sync.
Weigh the permanent cost of two codebases before choosing it.
Treat the batch layer as the source of eventual truth.
Production reality
Many data platforms historically ran Lambda and felt the two-codebase pain acutely, computing every metric twice and chasing discrepancies between the layers. That pain is precisely what the next architecture set out to remove.
Remember this
Lambda runs an accurate batch layer and a fast speed layer merged at serving; it delivers freshness and accuracy but at the steep, permanent cost of maintaining the same logic in two codebases.
Practice2 prompts
Explain how the serving layer combines batch and speed results.
Describe the two-codebase problem and why it causes discrepancies.
03 · Architecture 2
Kappa: One Streaming Path
Kappa = one streaming path. To reprocess, replay the retained log through the same code. Batch is just streaming over history, so there is no second codebase.
⏱ 6 min · Topic 3 of 7
The Kappa architecture, proposed by Jay Kreps (a Kafka creator), makes a bold simplification: delete the batch layer. Keep only the streaming pipeline. There is one codebase, one engine, one set of logic. This removes the two-codebase problem entirely.
The obvious objection is "but how do you reprocess history without a batch layer?". Kappa’s answer is elegant: reprocessing is just replaying the log. Because the streaming platform retains events (Chapter 13), you can rewind a consumer to the beginning and re-run the same streaming code over all of history, producing corrected results, then cut over to the new output. The stream code is the only code; batch is just streaming over old data.
Kappa became practical because stream processors grew powerful enough (Flink especially) to handle both real-time and large reprocessing workloads with one engine. It is simpler and increasingly the default for new systems, but it assumes your streaming engine and log retention can handle reprocessing the full history, which is not always true for enormous or long-lived datasets.
Core mental model
Kappa = one streaming path. To reprocess, replay the retained log through the same code. Batch is just streaming over history, so there is no second codebase.
Why it matters
Kappa is the modern, simpler default and the direction the industry has moved. Understanding it, and its assumptions about replay and retention, lets you choose the simpler architecture confidently when it fits.
streaming-only
A single streaming pipeline with no separate batch layer.
replay
Rewinding the log and re-running the streaming code over historical events to reprocess.
cutover
Switching consumers to the reprocessed output once a replay completes.
retention requirement
The need to keep enough log history to replay, a key Kappa assumption.
Kappa · “we just replay the log”That is a claim with a number behind it. Three dials decide whether the number is affordable.16.8 h to replay
Log retention
Events a day
Replay speed vs live
what
value
events in the retained log
2,800,000,000
log storage held
0.7 TB
full replay takes
16.8 h
covers the 18 months finance asks about?
no — only 7 days
The log cannot rebuild the history anybody asks aboutThis is where the Kappa promise usually breaks. Seven days of retention means a logic change can only be applied to the last week — everything older keeps whatever the old code produced, for ever, unless there is a batch path to rebuild it from. Which is Lambda, arriving by the back door.
Common mistake
Choosing Kappa without enough log retention to replay history. You cannot reprocess what the log no longer holds, undermining the whole approach.
Better habit
Use replay-based reprocessing instead of a separate batch layer.
Ensure log retention (or archival) covers the history you must replay.
Prefer Kappa when one engine can serve both real-time and reprocessing.
Interview note
Explaining Kappa as "reprocessing by replaying the log through the same streaming code, so there is only one codebase" is the crisp answer that shows you understand why it superseded Lambda for many teams.
Remember this
Kappa keeps a single streaming path and reprocesses by replaying the retained log through the same code, eliminating Lambda’s two-codebase problem, provided retention supports the replay.
Practice2 prompts
Explain how Kappa reprocesses history without a batch layer.
State the key assumption Kappa makes about the log.
04 · Applied method
Choosing an Architecture
Default batch; for real-time prefer Kappa (one path); use Lambda only when a constraint truly forces separate batch and speed layers. Simplest viable wins.
⏱ 6 min · Topic 4 of 7
As with batch versus streaming, the senior move is to resist the most impressive option and choose the simplest one that meets the requirement. Most workloads do not need real-time at all and should be plain batch (Chapters 2–12). Among those that do, Kappa’s single path is usually preferable to Lambda’s duplicated one, unless a specific constraint forces the split.
When might Lambda still make sense? When the batch and speed layers genuinely need different engines, for example, a heavy historical recomputation that is impractical to run as a replay, alongside a lightweight real-time approximation. And many real systems are neither pure Lambda nor pure Kappa: they are mostly batch with a few streaming paths, chosen per use case, which is the pragmatic reality the comparison below captures.
The unifying principle of this whole course applies one last time at the architecture level: complexity is a cost you pay forever. Two pipelines, two codebases, and a merge layer are justified only by a requirement that one path cannot meet. Start from the requirement, prefer one path, and add the second only when forced.
Core mental model
Default batch; for real-time prefer Kappa (one path); use Lambda only when a constraint truly forces separate batch and speed layers. Simplest viable wins.
Why it matters
Architecture choices are expensive and long-lived. Defaulting to the simplest viable design, batch where possible, single-path streaming where real-time is needed, avoids years of maintaining machinery you did not need.
streaming-first
Defaulting to a single streaming path (Kappa-style) for real-time needs.
hybrid platform
A mostly-batch platform with selected streaming pipelines per use case.
requirement-driven design
Choosing architecture from the freshness/accuracy requirement, not from fashion.
cost of complexity
The permanent maintenance burden each extra pipeline or codebase adds.
Three questions that come before either nameHow often does the logic change, what does a replay cost, and how fresh does it have to be?Kappa
Logic changes
A full replay
Freshness required
KappaLogic that changes often is exactly the case where maintaining two implementations hurts most, and a cheap replay is what makes one implementation sufficient. This is the configuration Kappa was designed for.
what it costs: Log retention long enough to cover the history people ask about — which is a storage bill, and the one people forget to include.
Notice what is not askedNot how much data there is, not which cloud, not which engine. Volume decides the size of the machines and changes none of the three answers above. An architecture question answered with a tool name has skipped the part that was being marked.
Lambda vs Kappa vs plain batch
Architecture
Codebases
Best when
Plain batch
One (batch)
No real-time requirement, most workloads
Kappa (streaming-first)
One (stream)
Real-time needed; one engine can also reprocess
Lambda
Two (batch + stream)
Batch and speed genuinely need different engines
Hybrid (per use case)
Mixed
Mostly batch with a few targeted streaming paths
Common mistake
Defaulting to Lambda because it sounds comprehensive. You inherit two-codebase maintenance forever for a need a single path would have met.
Better habit
Start from the freshness/accuracy requirement, not the architecture name.
Prefer one path; add a second only when a constraint forces it.
Accept that most platforms are mostly batch with selective streaming.
Simplest viable architecture
Lambda, Kappa, batch, the right choice is the least complex one that meets the requirement. Architecture is not where you show off capability; it is where you minimise lifelong cost.
Interview note
"Default to batch; for real-time I prefer a streaming-first (Kappa) single path; Lambda only if batch and speed truly need different engines." That progression is a principal-level architecture answer.
Remember this
Choose the simplest viable architecture: plain batch for most work, Kappa’s single path for real-time, and Lambda only when a constraint genuinely forces two layers.
Practice2 prompts
Recommend an architecture for a mostly-historical analytics workload with one live dashboard.
Give a concrete constraint that would justify Lambda over Kappa.
05 · Made real
The Three Architectures People Actually Run
The question is not batch or streaming — it is how many places the business logic is written, and whether history can be rebuilt by the same code that handles today.
⏱ 6 min · Topic 5 of 7
Lambda and Kappa are the two names in the literature. The thing most companies actually run is a third shape that neither paper describes — streaming into a lakehouse table that batch also reads.
Below: all three drawn with real components, the reprocessing story for each, and the code that makes the third one work.
Core mental model
The question is not batch or streaming — it is how many places the business logic is written, and whether history can be rebuilt by the same code that handles today.
Why it matters
Choosing between these decides how many codebases compute your revenue number. Two implementations of one definition will disagree eventually, and reconciling them is somebody’s permanent job.
speed layer
The streaming half of a Lambda architecture — fast, approximate, and overwritten later by the batch result.
log replay
Rebuilding a result by reading a topic from the beginning. It only works while the log still retains that history.
streaming lakehouse
A continuously written table format that batch and interactive queries also read, so one table is both the stream’s output and the warehouse’s input.
reconciliation query
The scheduled comparison proving two layers still agree. Lambda needs one; the other two shapes do not.
Kappa: reprocessing history by replaying the logworked example
The move that makes Kappa possible. Start a second job from offset zero writing to a new table, let it catch up, then swap the consumers — no batch layer, and the same code produced both.
The shape most teams actually run: streaming into a lakehouse tableworked example
SQL
#thestreamwritesintoatableformat,notabespokeservingstore(orders_stream.writeStream.format("delta")#oriceberg.outputMode("append").option("checkpointLocation","s3://ckpt/orders/").option("mergeSchema","true").trigger(processingTime="1minute").toTable("silver.orders"))-- and every consumer just reads a table, whenever it likesSELECTregion,SUM(total_gbp)FROMsilver.ordersWHEREdt=CURRENT_DATE()GROUPBYregion;-- a batch backfill writes to the SAME table, with the same logic,-- because the table is the interface rather than the pipeline.
One table, written continuously and read by everything. Batch jobs, ad-hoc SQL and dashboards all read the same rows, so there is no speed layer to reconcile and no second implementation of the metric.
Lambda, and the reconciliation nobody budgets forworked example
SQL
-- the serving view: speed layer for today, batch for everything settledCREATEVIEWrevenueASSELECTorder_date,region,revenue_gbp,'batch'ASsourceFROMgold.revenue_batchWHEREorder_date<CURRENT_DATE()UNIONALLSELECTorder_date,region,revenue_gbp,'speed'ASsourceFROMgold.revenue_realtimeWHEREorder_date=CURRENT_DATE();-- batch has not settled this yet-- the reconciliation nobody plans for, and everybody eventually writes:SELECTb.order_date,b.region,b.revenue_gbpASbatch,s.revenue_gbpASspeed,ABS(b.revenue_gbp-s.revenue_gbp)ASdriftFROMgold.revenue_batchbJOINgold.revenue_realtimesUSING(order_date,region)WHEREABS(b.revenue_gbp-s.revenue_gbp)>0.01;-- alert on this
If you do run two layers, the serving layer has to combine them — and someone must own the query that proves they agree. That query is the real cost of Lambda.
The three shapes, with real components
Lambda
Kappa
Streaming lakehouse
Ingest
Kafka + a nightly extract
Kafka only
Kafka only
Compute
Spark batch AND Flink streaming
Flink or Spark streaming only
Spark or Flink streaming, plus batch on the same table
Storage
A batch table and a speed store
A serving store rebuilt by replay
One Delta or Iceberg table
Codebases for one metric
Two
One
One
Reprocessing history
Re-run the batch layer
Replay the log into a new table
Batch-rewrite the partitions
Bounded by
Reconciliation effort
Log retention
Table format maintenance
Which shape fits
Situation
Shape
Why
Mostly historical analytics, one live dashboard
Streaming lakehouse
One table serves both; no second implementation
Sub-second decisions — fraud, pricing, matching
Kappa, with a serving store
The dashboard is not the consumer; a system is
A batch estate that cannot be rewritten
Lambda, deliberately
The speed layer is an addition, not a migration
History older than any sane log retention
Lambda or lakehouse
Kappa’s replay assumption does not hold
One team, modest volume
Streaming lakehouse
Fewest moving parts that still gives freshness
What each shape costs to run
Shape
Always-on compute
Storage
The hidden cost
Lambda
A streaming cluster, plus batch bursts
Two copies of the results
Reconciliation, and two implementations drifting apart
Kappa
A streaming cluster, sized for replay too
Long log retention
A replay must run at many times real-time speed to catch up
Streaming lakehouse
A streaming writer, usually small
One table, plus its old file versions
Compaction and vacuum — see Chapter 20
Common mistake
Choosing Kappa without checking log retention. The replay that justified the architecture can only reach back seven days, so history cannot actually be rebuilt.
Running Lambda without a reconciliation alert. The two layers drift, both look plausible, and the disagreement is discovered in a meeting rather than by a check.
Writing a stream into a lakehouse table and never compacting. A file per minute becomes half a million small files, and every reader slows down until someone runs maintenance.
Building a speed layer for a dashboard nobody watches overnight. You pay always-on compute for freshness no decision consumes.
Better habit
Count the implementations of your most important metric. More than one is the actual problem.
Check log retention against the history you claim to be able to replay.
Prefer one table read by everyone over two stores that must be kept in agreement.
If you run two layers, schedule the reconciliation before the second layer ships.
The architecture most people run has no famous name
Streaming into Delta or Iceberg, read by batch and BI, is the common shape today and it is neither Lambda nor Kappa. It gets Kappa’s single codebase without Kappa’s dependence on infinite log retention, at the price of table maintenance.
The follow-up you will actually get
"Lambda or Kappa?" is the question; "how many places is this metric implemented, and can history be rebuilt by the same code?" is the answer. Then name the constraint that decides it — log retention, or an existing batch estate.
Remember this
Pick the architecture that leaves one implementation of each metric; Lambda buys compatibility at the cost of reconciliation, Kappa buys simplicity at the cost of retention, and a streaming lakehouse buys both at the cost of table maintenance.
Practice2 prompts
Name a metric in your company and count how many codebases compute it. If it is more than one, say what keeps them in agreement.
Check the retention on a topic you rely on, and say how far back a replay could actually rebuild.
06 · Practice
Practice Lab
Choose from how often the logic changes and what a replay costs. Both questions come before either architecture name.
⏱ 3 min · Topic 6 of 7
Five scenarios that between them produce all three architectures — including the hybrid nobody names, which is what most companies actually run.
Build them on the pipeline canvas with the chapter closed. Each is graded against the scenario’s own requirement rules rather than against a model answer, so there is more than one design that passes — and a design that does not pass is told exactly which requirement it missed.
Core mental model
Choose from how often the logic changes and what a replay costs. Both questions come before either architecture name.
Why it matters
Lambda and Kappa are named in every architecture question and understood in few answers. Building these makes the difference concrete: one bets you can maintain the same logic twice, the other bets replay is cheaper than that.
Common mistake
Recommending Kappa without checking the retention window a full replay would need. The review will find it, but only after you have submitted a design you believed in — which is the point. That is the memory that survives interview pressure.
Revealing the reference design before your own review comes back. You see what correct looks like without finding out what your version got wrong, and your version is the one you will draw again under pressure.
Better habit
Before naming an architecture, say how often this logic will change. That answer decides more than the diagram does.
Run the review, fix what it finds, and run it again. The second score is the one that means something.
Narrate the finished design out loud in ninety seconds. If you cannot, the design has a hole you have not found yet.
Two of the scenarios below resolve to neither Lambda nor Kappa. That third shape is the one most teams run and the one candidates rarely name.
These are the round, not a warm-up
Five graded design scenarios, each with staged requirement checks and interview probes of its own. Working them out loud, against a clock, is the closest rehearsal to the real thing this module offers.
Remember this
A chapter read is a chapter you can recognise; a scenario built and reviewed is one you can use. Close this and go build.
Practice2 prompts
Before opening any scenario, write down the freshness requirement and who consumes the output.
After each review, write one sentence naming the requirement you missed and why you missed it.
07 · Next Chapter
Next Chapter
You have completed the streaming arc: architecture, processing, guarantees, and the Lambda/Kappa debate. The course now turns to the Production, Quality & Advanced level, beginning with the trust that makes any pipeline worth running.
⏱ 3 min · Topic 7 of 7
Next chapter
Data Quality & Validation
You have completed the streaming arc: architecture, processing, guarantees, and the Lambda/Kappa debate. The course now turns to the Production, Quality & Advanced level, beginning with the trust that makes any pipeline worth running.
Chapter 17 covers data quality and validation: the dimensions of quality, schema and value checks, testing with tools like Great Expectations and dbt, and quarantining bad data instead of dropping it.