Lambda and Kappa architectures explained

During a big sale, the CEO wants live numbers; the next morning, finance wants exact ones. The Lambda architecture runs a fast stream path and an accurate batch path and merges them. The Kappa architecture keeps only the stream and fixes history by replaying the event log. This lesson builds both in Python, shows them working on sale night, and teaches you how architects choose.

Module 4 · The Ecosystem⏱ 28 minBeginner → AdvancedRuns in your browser (Python)3 real-time scenariosLog replay on your PC9 practice problems
1 The story

Two numbers for the same sale

TiffinGo runs its biggest-ever Diwali dinner sale. The CEO wants a live revenue counter on the office TV all evening. Kabir builds it on the streaming path, and at midnight it proudly shows ₹2.31 crore. Next morning, the finance team's batch report says ₹2.24 crore. The CEO asks one question: “Which number is true?”

Order events sales, refunds Kafka log append-only Speed layer (stream) seconds old · approximate ₹2.31 cr at midnight Batch layer (recompute) hours old · accurate ₹2.24 cr next morning Serving layer batch view + speed view Lambda: run both paths and merge. Kappa: keep only the stream, and replay the log to fix anything.
Kabir

Sir, my live counter didn't subtract refunds properly, and some orders came twice when phones retried. But it was live! Finance took six hours.

Arjun Sir

Both numbers are useful, Kabir. The live one answers “how is the sale going right now?” The batch one answers “what exactly did we earn?” In 2011, an engineer called Nathan Marz proposed running both paths together and merging them. He called it the Lambda architecture.

Riya

Then everyone is happy. What's the catch?

Arjun Sir

You now maintain the same business logic twice: once in the stream code, once in the batch code. Fix the refund rule in one and forget the other, and the numbers disagree forever.

Kabir

Can't we just have one path?

Arjun Sir

That's the Kappa architecture, proposed in 2014 by Jay Kreps, one of Kafka's creators: only the streaming path, and when the logic changes, replay the saved event log through the new code. Today you'll build both in Python and decide which one TiffinGo should use.

2 Definition

What are the Lambda and Kappa architectures?

Formal definition (write this in exams)

The Lambda architecture processes data through two parallel paths: a batch layer that stores the complete, immutable master dataset and periodically recomputes accurate batch views, and a speed layer that processes only recent data in real time to produce low-latency real-time views. A serving layer answers queries by merging both views. The Kappa architecture removes the batch layer: all data is treated as a stream stored in a replayable, append-only log, a single stream-processing code path produces the views, and reprocessing is done by replaying the log through a new version of the job.

In simple words

Lambda: a fast, rough answer from the stream, plus a slow, exact answer from batch; show both combined. Kappa: one stream-only path; if you need to fix or recompute something, rewind the saved event log and run it again.

Words you'll meet in this lesson

Master datasetThe complete, raw, never-edited record of all events, usually in the lake.
Batch viewA result precomputed from all data up to the last batch run: accurate but hours old.
Real-time viewA result computed by the speed layer from events since the last batch run.
Serving layerThe store that answers queries by combining batch and real-time views.
ImmutableNever changed after being written: you append corrections, you don't overwrite.
OffsetAn event's position number in a Kafka partition. Consumers can start reading from any offset.
RetentionHow long the log keeps events: hours, days, or forever with tiered storage.
Replay / reprocessRead old events again from an earlier offset, usually with fixed or new logic.

The two architectures at a glance

LambdaBatch layer (Spark/Hadoop on the lake) + speed layer (Flink/Spark Streaming) + serving layer · accurate and fresh · two codebases
KappaKafka log (long retention) + one stream processor + serving store · one codebase · reprocess by replaying the log

Lambda and Kappa at three levels

Pick your level. New to this? Start at Beginner and climb.

Beginner Two cooks, or one cook with a recipe book

  • Lambda is a kitchen with two cooks. The fast cook sends a quick tasting plate the moment an order arrives. The head chef cooks the full, perfect meal more slowly. The waiter serves the perfect meal when it's ready and the tasting plate until then.
  • Kappa is one very good cook who keeps every ingredient delivery and every recipe. If a recipe was wrong, the cook simply re-cooks from the saved ingredients with the corrected recipe.
  • Lambda gives you two opinions to reconcile. Kappa gives you one opinion that can be redone.

Intermediate Layers, merging and replay

  • Batch layer: appends every event to an immutable master dataset in the lake and recomputes views from scratch (for example nightly with Spark). Recomputing from raw data corrects any earlier mistakes.
  • Speed layer: processes only events that arrived after the last batch run, with a stream processor. Its results are temporary: they are discarded once the next batch view covers that period.
  • Serving layer: stores views (Cassandra, HBase, Druid, a warehouse) and answers query = batch view + real-time view.
  • Kappa: Kafka keeps events long enough to replay. To change logic, start job v2 from offset 0 writing to a new table, wait until it catches up with the live stream, switch readers to the new table, then stop v1.

Advanced Trade-offs in real systems

  • Lambda's cost is duplicated logic: two implementations of every metric, two test suites, and subtle drift between them. Its strength is that batch recomputation from the lake is simple, robust and can use any batch tool.
  • Kappa's cost is in the stream: long log retention (tiered storage helps), replays that may take hours for large state, careful exactly-once and idempotent sinks, and schema evolution across years of events.
  • Unified engines (Apache Flink, Spark Structured Streaming, Apache Beam) let one codebase run in batch and streaming modes, removing much of Lambda's duplication.
  • Lakehouse streaming tables (Delta, Iceberg, Hudi) can be both a streaming sink and a batch source, so many modern platforms use a pragmatic mix: a stream for live views plus scheduled recomputation from the same tables and the same code.
  • Choose by need: how often must you recompute history, how complex is the logic, how long can the log be kept, and how strong is the team in stream processing?

Exam tip: Draw Lambda with its three layers (batch, speed, serving) and arrows from one data source to both batch and speed. Draw Kappa as log → stream processor → serving, with a “replay” arrow. Then give two advantages and two disadvantages of each.

3 Types and ways to use it

Lambda vs Kappa side by side

LambdaKappa
Processing pathsTwo: batch + speedOne: stream only
Source of truthImmutable master dataset in the lakeReplayable event log (Kafka with long retention)
CodebasesTwo, must stay consistentOne
Fixing a bug / new metricChange both; the next batch run recomputes historyDeploy a new job version and replay the log
AccuracyBatch view is exact; speed view approximate until replacedExact if the stream job is exactly-once
ComplexityOperational: two systems to runTechnical: stateful streaming, replays, retention
Good fitHeavy historical recomputation, ML training, very complex batch logicEvent-driven businesses, logic expressible as stream jobs, frequent small changes

Typical tools in each layer

Batch layer

HDFS or S3 for the master dataset; Spark (earlier Hadoop MapReduce) to recompute views; Airflow to schedule.

Accurate

Speed layer

Kafka in front; Flink, Spark Structured Streaming or Kafka Streams (earlier Apache Storm) to keep real-time views.

Fresh

Serving layer

Cassandra, HBase, Apache Druid, Apache Pinot or a warehouse, holding views that dashboards and APIs query.

Answers

The “lambda” name comes from the shape of the diagram (data splitting into two branches), not from Python's lambda functions or AWS Lambda. Don't mix them up in interviews.

4 Step by step

A query during the sale, the Lambda way

  1. Every event is appended, twice over

    {"offset": 50213, "order": "O90017", "amount": 499, "type": "sale", "ts": "19:42:05"}
    The event goes into Kafka. From there, one consumer writes it to the master dataset in the lake (batch layer), and another feeds the speed layer.
  2. The batch view from last night

    batch_view = {"revenue_till_yesterday": 18_40_00_000}   # computed at 02:00 by Spark
    A nightly Spark job recomputed revenue from all raw events up to midnight: duplicates removed, refunds subtracted, late events included. Exact, but it knows nothing about today.
  3. The speed layer covers today

    speed_view = {"revenue_today": 0}
    for e in todays_events:                      # updated within seconds of each event
        speed_view["revenue_today"] += e["amount"] if e["type"] == "sale" else -e["amount"]
    The stream processor keeps a running total for events after midnight only. Quick, but approximate: a duplicate or a late refund may slip through until tomorrow's batch.
  4. The serving layer merges

    batch_view = 18_40_00_000
    speed_view = 2_31_00_000
    print("Revenue (this season):", batch_view + speed_view)
    Revenue (this season): 207100000
    The dashboard asks the serving layer; it adds the exact past to the fresh present. The CEO sees a number that is both complete and up to the minute.
  5. Next night, batch catches up

    At 02:00 the batch job recomputes everything including the sale day: ₹2.24 crore for the day, not ₹2.31 crore.

    The new batch view replaces the speed layer's estimate for that day, and the speed layer starts again from zero for the new day. Errors in the fast path never last longer than one batch cycle. That is Lambda's safety net.
5 See it happen

Sale night, the morning after, and the week Kabir switched to Kappa

Step through six frames. Left: what the CEO and finance see. Right: which layer is doing the work.

From Lambda to Kappa 6 steps
What you see DIWALI DINNER SALE · LIVE ₹018:00 · sale begins ₹1.12 cr20:30 · updated 2 seconds ago ₹20.71 crseason total = till yesterday + today18.40 cr (exact) + 2.31 cr (live) The office TV during the sale Finance report · morning after Live counter at midnight₹2.31 cr − duplicate orders (retries)₹0.04 cr − refunds processed late₹0.05 cr + orders that arrived late₹0.02 cr Exact sale revenue₹2.24 cr A week later: the numbers disagree again Finance changed the rule: “cancelled within 5 minutes is not a sale.” The batch code was updated. The stream code was not. Live and morning numbers now drift apart every day. After moving to Kappa ✓ one job computes both live and final numbers ✓ rule changes: deploy v2, replay 30 days of log ✓ live counter and finance agree ✗ needs long log retention and careful exactly-once processing myphatshala.in
Behind the screen Kafkaevents Speed layer Batch layer Servingbatch + speed today: ₹0master dataset in lakeview till yesterday: 18.40 cr Each event goes to BOTH paths. +499 +250 −120 …today: 1.12 cronly appending rawevents, no recompute yet The speed layer updates a running total per event. real-time view: 2.31 crbatch view: 18.40 cr Query = batch view + real-time view. 02:00 recompute ALL rawsale day exact: 2.24 crestimate for that daydiscarded, reset to 0 Batch replaces the speed layer's estimate. stream code: OLD rulev1 (Flink job)batch code: NEW rulev2 (Spark job) Same metric, two implementations, drifting apart. Kafka log · 30-day retention offset 0now job v1 (old rule)stopped after switch job v2 (new rule)replayed from offset 0 serving table v2live + historical Kappa: one code path; replay the log to recompute. myphatshala.in
6 Real-world use

Real-time scenarios with both architectures

Watch the live estimate and the batch correction on one chart, replay a Kafka log after a bug, and (advanced) walk the decision an architect makes when choosing.

Real-time scenario 1

Sale night on one chart: speed layer vs batch correction

Revenue per hour during the sale. The green line is what the speed layer showed live; the blue line is what the batch layer computed afterwards from complete data.

Live estimate, exact correction 5 steps
Animated example 18h19h20h21h22h23h ₹ lakh — speed layer (live)- - batch (corrected) 18:00–19:00 · speed layer updates every few seconds. 20:00–21:00 · peak dinner hour, still live and fresh. 23:00 · sale ends. Live total ₹2.31 crore. 02:00 · batch recomputes every hour from raw events.each hour slightly lower: duplicates and late refunds Gap ≈ 3%: small, but finance needs the exact linelive for decisions tonight, batch for the books tomorrow myphatshala.in
Real-time scenario 2

Kappa in action: replaying a month after a bug

TiffinGo moved to Kappa. On 19 October, a bug is found in how coupons were applied since 20 September. The log keeps 30 days. Watch the team fix a month of numbers without any batch system.

Replay, catch up, switch 5 steps
Animated example topic: orders (retention 30 days) 20 Sep (offset 0)now: 19 Oct job v1 job v2 job v2 job v2 v1 stopped 19 Oct · bug found: coupons applied twice since 20 Sepjob v1 keeps running live, so dashboards stay upbut a month of revenue numbers is wrong 11:00 · start job v2 (fixed code) from offset 0writing to a NEW table: revenue_v2replay runs much faster than real time 13:30 · halfway through the monthlag shrinking: v2 reads old events at 50× live speedtwo jobs running side by side for a while 16:10 · v2 caught up with the live streamcompare v1 and v2 outputs, then point dashboardsto revenue_v2 (blue-green switch) 16:20 · switched. v1 stopped, old table dropped laterone month corrected with one codebase, no batch systemonly possible because the log kept 30 days of events myphatshala.in
Real-time scenario 3 · Advanced

The architect's decision: Lambda, Kappa or a unified engine?

Three teams at TiffinGo ask for real-time plus historical data. Watch the architect walk each one through the same questions and reach different answers.

Choosing an architecture 5 steps
Animated example Q1 · Real-time answer needed? Q2 · All logic fits a stream job? Q3 · Log keeps enough history? Q4 · One engine for batch + stream? Payroll: NO → plain batch Monthly payroll doesn't need live numbers.Neither Lambda nor Kappa: a nightly batch job is enough. ML training: NO → Lambda Retraining the ETA model needs months of joinsand heavy batch work; live scoring uses a stream. Two paths. Order metrics: YES → Kappa Revenue and order counts are simple stream logic;Kafka with tiered storage keeps 90 days for replay. YES → unified With Flink, Spark Structured Streaming or Beam,one codebase runs live AND recomputes history. No single winner: match the architecture to the need.Most modern platforms mix: stream for live, scheduledrecompute from the same tables and the same code. myphatshala.in

Where these patterns appear

livebill

1. Online advertising: Lambda-style billing

Ad clicks are counted in real time to stop campaigns that hit their budget, while invoices are produced by batch jobs that remove fraudulent and duplicate clicks from the complete data.

Clicks→Speed: budget cap · Batch: invoices→Serving: ads dashboard

2. Banking ledgers: event logs as the source of truth

Many modern banking and wallet systems record every transaction as an immutable event and derive balances and statements from the log. Replaying events to rebuild state is close to the Kappa idea.

Transactions→Append-only log · replay to rebuild→Balances, statements

3. Machine learning features: batch + streaming

Recommendation systems combine long-term features computed in batch (a user's favourite cuisine over months) with fresh streaming features (what they clicked a minute ago) when scoring.

History + live clicks→Batch features + stream features→Recommendations

4. Live dashboards with nightly correction

Sales, delivery and operations dashboards often show stream numbers during the day and switch to batch-verified numbers for previous days: a simple, practical Lambda.

Orders→Today: stream · past days: batch→One dashboard

5. IoT fleets: unified stream and batch

Vehicle and machine telemetry is processed live for alerts, and the same pipeline code is re-run over stored history to test new alert rules before switching them on.

Telemetry→One engine, live + historical runs→Alerts, rule testing

Simplified patterns; real systems often blend Lambda and Kappa ideas.

7 Run the code

Lambda in miniature: batch view + speed view

An append-only list of events plays the master dataset. Last night's batch job computed an exact view up to a cut-off; the speed layer keeps a running total for everything after it. The query adds the two. Then, in the challenges, replay the log Kappa-style, watch two codebases drift, and size a log for replay.

# The master dataset: every event ever, append-only (sale = +, refund = -)
master = [("O1", 120, "sale"), ("O2", 250, "sale"), ("O3", 90, "sale"),
          ("O2", 250, "refund"), ("O4", 300, "sale"),          # up to last night
          ("O5", 140, "sale"), ("O6", 60, "sale")]             # arrived today

def revenue(events):
    total = 0
    for order, amount, kind in events:
        total += -amount if kind == "refund" else amount
    return total

CUTOFF = 5                                 # last night's batch job processed events 0-4

batch_view = revenue(master[:CUTOFF])      # BATCH LAYER: exact, recomputed nightly
speed_view = revenue(master[CUTOFF:])      # SPEED LAYER: only events since the batch run

print("Batch view (till last night):", batch_view)
print("Speed view (today, live)    :", speed_view)
print("Query answer = batch + speed:", batch_view + speed_view)

# A new event arrives: only the speed view changes, instantly
master.append(("O4", 300, "refund"))
speed_view = revenue(master[CUTOFF:])
print("After a refund arrives      :", batch_view + speed_view)
Batch view (till last night): 510 Speed view (today, live) : 200 Query answer = batch + speed: 710 After a refund arrives : 410
  • master = [...]The master dataset is only ever appended to. Corrections (like a refund) are new events, not edits.
  • batch_view = revenue(master[:CUTOFF])The batch layer recomputes from all raw events up to the cut-off. Accurate, but only as fresh as its last run.
  • speed_view = revenue(master[CUTOFF:])The speed layer handles only the recent tail, so it can update within seconds.
  • batch_view + speed_viewThe serving layer's job: merge the two views into one answer.

Run it on your PC: a real log file, replayed

This program writes an append-only log file (orders.log), one JSON event per line with an offset, just like a Kafka partition. It then shows Kappa (a buggy v1 job, then a fixed v2 replayed from offset 0) and Lambda (batch view up to offset 4 plus speed view after it). Save it as replay_log.py, run it, and open orders.log to see the events.

Kappa replay and Lambda merge on one log

import json, os

# ---------- An append-only event log, like a Kafka topic ----------
LOG = "orders.log"
raw = [("O1", 120, "sale"), ("O2", 250, "sale"), ("O3", 90, "sale"), ("O2", 250, "refund"),
       ("O4", 300, "sale"), ("O5", 140, "sale"), ("O6", 60, "sale"), ("O4", 300, "refund")]
with open(LOG, "w") as f:
    for offset, (oid, amount, kind) in enumerate(raw):
        f.write(json.dumps({"offset": offset, "order": oid, "amount": amount, "type": kind}) + "\n")
print(f"Log written: {len(raw)} events (offsets 0-{len(raw) - 1}), never edited afterwards\n")


def consume(logic, start=0, end=None):
    """Read the log from an offset, like a consumer reading a Kafka partition."""
    total = 0
    with open(LOG) as f:
        for line in f:
            e = json.loads(line)
            if e["offset"] < start or (end is not None and e["offset"] >= end):
                continue
            total = logic(total, e)
    return total


def v1(total, e):                      # BUG: treats refunds as sales
    return total + e["amount"]


def v2(total, e):                      # FIXED: refunds reduce revenue
    return total - e["amount"] if e["type"] == "refund" else total + e["amount"]


# ---------- KAPPA: one streaming code path; fix a bug by replaying the log ----------
print("KAPPA")
print(f"  {'v1 job (live since morning) says revenue':44}: Rs {consume(v1)}")
print("  bug found -> deploy v2, replay from offset 0")
print(f"  {'v2 job after replay says revenue':44}: Rs {consume(v2)}")

# ---------- LAMBDA: batch view (complete but late) + speed view (recent, fast) ----------
print("\nLAMBDA")
batch_upto = 5                         # last night's batch job processed offsets 0-4
batch_view = consume(v2, 0, batch_upto)
speed_view = consume(v2, batch_upto)   # events that arrived since the batch ran
print(f"  {'batch view (offsets 0-4, computed at 02:00)':44}: Rs {batch_view}")
print(f"  {'speed view (offsets 5-7, live since then)':44}: Rs {speed_view}")
print(f"  {'query answer = batch view + speed view':44}: Rs {batch_view + speed_view}")

# In a terminal:  python replay_log.py
Log written: 8 events (offsets 0-7), never edited afterwards KAPPA v1 job (live since morning) says revenue : Rs 1510 bug found -> deploy v2, replay from offset 0 v2 job after replay says revenue : Rs 410 LAMBDA batch view (offsets 0-4, computed at 02:00) : Rs 510 speed view (offsets 5-7, live since then) : Rs -100 query answer = batch view + speed view : Rs 410

Recorded from a real run; your output will be identical. Both architectures give the same correct answer (₹410) from the same log. The speed view is negative because a ₹300 refund arrived after the batch run, a reminder that real-time views hold whatever happened recently, including corrections.

8 Line by line

A serving-layer query, one line at a time

The batch view was computed overnight; the speed layer adds today's events one by one. Watch speed change with each event while batch stays fixed, and the query merge them at the end.

Worked examples: real problems, solved and traced in memory

Four problems on merging views, catching up, code drift and replay planning. Each runs live and is traced.

Example 1BeginnerDashboard · serving layer

Combine yesterday's exact total with today's live total

Problem statement

The batch view says the season's revenue till last night is ₹18.40 crore. The speed layer has today's events: ₹1.12 crore so far, then two more updates of ₹0.80 crore and ₹0.39 crore. Print the dashboard number after each update.

Input
batch 18.40 cr · today: 1.12, +0.80, +0.39 (cr)
Expected output
dashboard: 19.52 cr
dashboard: 20.32 cr
dashboard: 20.71 cr

Approach

  1. Keep the batch view fixed.
  2. Add each live update to the speed view.
  3. Print batch + speed after every update.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 2IntermediatePlatform · batch catch-up

Move events from the speed view to the batch view

Problem statement

Events have offsets 0–9. Last night's batch covered offsets 0–5. Tonight's batch covers 0–9. Show which offsets each layer is responsible for, before and after.

Input
offsets 0–9, cut-off 6 then 10
Expected output
cutoff 6 | batch: [0, 1, 2, 3, 4, 5] | speed: [6, 7, 8, 9]
cutoff 10 | batch: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | speed: []

Approach

  1. The batch layer owns offsets below the cut-off.
  2. The speed layer owns offsets from the cut-off onwards.
  3. Print both lists for each cut-off.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 3IntermediateLambda pitfall · consistency

Detect drift between batch and stream logic

Problem statement

The same day's events are processed by the batch code and by the stream code. Finance's rule says orders cancelled within 5 minutes are not sales. Find whether the two implementations disagree and by how much.

Input
events with minutes-until-cancel (None = not cancelled)
Expected output
batch: 510 | stream: 820 | drift: 310

Approach

  1. Implement both functions as they exist in production.
  2. Run both on the same events.
  3. Report the difference, which should be zero.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

Example 4AdvancedKappa · capacity planning

Can we replay 90 days before the morning meeting?

Problem statement

A rule change must be applied to 90 days of history. The log holds 3 million events per day. The replay job processes 80,000 events per second, and new events arrive at 40 per second. Will it catch up within 8 hours?

Input
3,000,000/day × 90 days · replay 80,000/s · live 40/s · budget 8 h
Expected output
Backlog: 270,000,000 events
Catch-up time: 0.94 hours
Fits in 8 hours? True

Approach

  1. Backlog = events per day × days.
  2. The replay closes the gap at (replay speed − live speed) per second.
  3. Compare the hours needed with the 8-hour budget.

Solution: run it live

What happens in memory, step by step

Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.

9 Quiz and revision

Check yourself

Quick revision

Lesson 4.4 in one screen

  • Lambda = batch layer (exact, hours old) + speed layer (fresh, approximate) + serving layer (merge).
  • Query = batch view + real-time view; real-time views are discarded once batch catches up.
  • Lambda drawback: two codebases for the same logic, which can drift apart.
  • Kappa = append-only log + one stream job + serving store; reprocess by replaying the log.
  • Kappa needs long retention, fast replay, exactly-once sinks; switch versions blue-green.
  • Lambda: Nathan Marz (2011). Kappa: Jay Kreps (2014).
  • Modern practice: unified engines and lakehouse tables blend both ideas. Choose per use case.

Interview and viva questions

Explain the Lambda architecture with a diagram.

Incoming data is sent to two paths. The batch layer appends it to an immutable master dataset and periodically recomputes batch views over all data (accurate but high-latency). The speed layer processes only recent data in real time to produce real-time views (low-latency, approximate). The serving layer stores both and answers queries by merging them. When the batch layer catches up, the corresponding real-time views are discarded.

What is the Kappa architecture and how is it different from Lambda?

Kappa uses a single stream-processing path over an append-only, replayable log (such as Kafka with long retention). There is no separate batch layer: to fix bugs or compute new metrics, a new version of the stream job replays the log from the beginning into a new output, and readers switch to it once it catches up. This avoids maintaining two codebases, at the cost of relying on long retention and robust streaming.

What are the advantages and disadvantages of Lambda?

Advantages: accurate results from full recomputation, low-latency views from the speed layer, and robustness, since batch recomputation corrects any errors. Disadvantages: duplicated logic in two systems, more operational complexity, and possible inconsistencies between batch and real-time results.

When would you choose Kappa over Lambda?

When the processing logic can be expressed as stream jobs, the event log can retain enough history to replay, logic changes are frequent, and the team wants one codebase. Lambda (or a batch component) remains useful when recomputation needs heavy historical joins, very long history, or complex batch-only tools such as large model training.

What is the role of the serving layer?

It stores precomputed batch views and real-time views in a database built for fast reads (for example Cassandra, HBase, Druid or a warehouse) and answers application and dashboard queries by combining them, so users get complete and up-to-date results with low latency.

Practice problems

Exercises on views, replays and planning, from easy to advanced, ending with two business decisions.

P1Easy

Merge two views

The batch view is 9,450 orders and the real-time view is 312 orders. Print the total the dashboard shows.

Input
9450 + 312
Expected output
Dashboard: 9762
Show solution and explanation
batch, speed = 9450, 312
print("Dashboard:", batch + speed)
Dashboard: 9762

How it works: The serving layer's core operation: batch view + real-time view.

P2Easy

Which layer answers?

For each requirement, print which Lambda layer provides it.

Input
“seconds-old count”, “exact last month”, “combined answer”
Expected output
seconds-old count  -> speed layer
exact last month   -> batch layer
combined answer    -> serving layer
Show solution and explanation
needs = {"seconds-old count": "speed layer", "exact last month": "batch layer",
         "combined answer": "serving layer"}
for need, layer in needs.items():
    print(f"{need:18} -> {layer}")
seconds-old count -> speed layer exact last month -> batch layer combined answer -> serving layer

How it works: Fresh = speed, exact = batch, merged = serving.

P3Easy

Log storage for retention

An app produces 5 lakh events a day of 500 bytes each. How many GB does a 30-day log need (one copy)?

Input
500000 × 500 B × 30
Expected output
6.98 GB
Show solution and explanation
print(round(500_000 * 500 * 30 / 1024**3, 2), "GB")
6.98 GB

How it works: Retention size = events per day × size × days. Multiply by the replication factor for real storage.

P4Medium

Speed view after the cut-off

Event times are given in hours. The batch ran at hour 24. Sum only the amounts the speed layer handles (time ≥ 24).

Input
(20,100), (23,50), (24,70), (26,30)
Expected output
Speed view: 100
Show solution and explanation
events = [(20, 100), (23, 50), (24, 70), (26, 30)]
cutoff = 24
print("Speed view:", sum(a for t, a in events if t >= cutoff))
Speed view: 100

How it works: Everything before the cut-off belongs to the batch view; counting it twice would be a bug.

P5Medium

How wrong was the live number?

The live counter showed ₹2.31 crore; the batch result is ₹2.24 crore. Print the difference as a percentage of the batch result.

Input
2.31 vs 2.24
Expected output
3.1 % higher than exact
Show solution and explanation
live, exact = 2.31, 2.24
print(round((live - exact) / exact * 100, 1), "% higher than exact")
3.1 % higher than exact

How it works: Speed-layer results are useful for decisions but are not the final, audited number.

P6Advanced

Replay with corrected logic

Replay the log with the corrected rule (refunds subtract) and compare with the buggy total (refunds add).

Input
sale 500, refund 200, sale 300, refund 100
Expected output
Buggy: 1100 | Fixed after replay: 500
Show solution and explanation
log = [(500, "sale"), (200, "refund"), (300, "sale"), (100, "refund")]
buggy = sum(a for a, k in log)
fixed = sum(-a if k == "refund" else a for a, k in log)
print("Buggy:", buggy, "| Fixed after replay:", fixed)
Buggy: 1100 | Fixed after replay: 500

How it works: Because the log keeps every event, the corrected logic can recompute history exactly.

P7Advanced

When can we switch?

Job v2 starts 2 crore events behind live. It processes 40,000 events/s while new events arrive at 500/s. Print the minutes until it catches up.

Input
backlog 20,000,000; 40,000/s vs 500/s
Expected output
8.4 minutes until v2 catches up
Show solution and explanation
backlog = 20_000_000
minutes = backlog / (40_000 - 500) / 60
print(round(minutes, 1), "minutes until v2 catches up")
8.4 minutes until v2 catches up

How it works: Only when the new version has caught up do you switch readers to its output (blue-green).

P8Business problem

The cost of two codebases

Each new metric takes 3 days to build in batch and 4 days in streaming. A unified engine needs 5 days once. For 12 metrics a year, print the engineer-days for Lambda and for unified.

Input
12 metrics
Expected output
Lambda (two codebases): 84 days
Unified engine        : 60 days
Show solution and explanation
metrics = 12
print("Lambda (two codebases):", metrics * (3 + 4), "days")
print("Unified engine        :", metrics * 5, "days")
Lambda (two codebases): 84 days Unified engine : 60 days

How it works: Duplicate implementation is Lambda's hidden running cost (numbers illustrative).

P9Business problem

Does the replay fit the window?

A full replay takes 6.5 hours and must finish between 22:00 and 06:00. Print whether it fits and how much buffer remains.

Input
6.5 h vs 8 h window
Expected output
Fits: True | buffer: 1.5 hours
Show solution and explanation
replay_h, window_h = 6.5, 8
print("Fits:", replay_h <= window_h, "| buffer:", window_h - replay_h, "hours")
Fits: True | buffer: 1.5 hours

How it works: Replay time is a real constraint in Kappa designs; plan capacity so replays finish in time.

Real-world scenario questions (asked in company interviews)

Architecture questions asked in data engineering interviews. Decide your answer first, then open the model answer.

E-commerce · dashboardsFresher

“Why do the live and final numbers differ?”

The business head sees ₹2.31 crore on the live sale dashboard and ₹2.24 crore in the next day's report and thinks the system is broken.

The interviewer is checking: can you explain speed vs batch results to a non-technical person?

Show a strong answer

The live number comes from the speed layer: it is computed within seconds, so it can't yet account for late refunds, duplicate events from retries, or orders that arrive late. The next-day number comes from the batch layer, which recomputes from all raw events once everything has arrived. Live is for decisions during the sale; batch is the audited figure.

  • Label the live figure as “provisional” on the dashboard.
  • Show yesterday's and older figures from the batch view only.

Avoid: saying one of them is “wrong”. Each answers a different question.

Ad-tech · architecture choice1–3 years

Real-time budget cap and monthly invoices

An ad platform must stop a campaign within seconds of hitting its daily budget, and send advertisers an exact monthly invoice after removing fraudulent clicks. Propose an architecture.

The interviewer is checking: can you map requirements to speed and batch paths?

Show a strong answer
  • Speed path: clicks → Kafka → stream job keeping per-campaign spend for today → stops campaigns at the cap.
  • Batch path: all clicks stored in the lake → nightly Spark job applies fraud filtering and de-duplication → exact spend per campaign → invoices.
  • Serving: advertiser dashboard shows exact spend for past days and provisional spend for today.
  • Keep the spend logic in one shared library, or use a unified engine, to limit drift.

Avoid: invoicing from the real-time counters.

Fintech · reprocessing1–3 years

A bug corrupted three weeks of metrics

A Kappa-style platform's stream job had a currency-conversion bug for three weeks. Kafka retention is 14 days. How do you fix the history?

The interviewer is checking: do you understand Kappa's dependence on retention, and the backups?

Show a strong answer
  1. Fix the job and start v2 from the earliest offset still in Kafka (14 days) into a new table.
  2. For the 7 days no longer in Kafka, reprocess from the copy of raw events archived in the lake (most teams keep one), using the same v2 code in batch mode if the engine allows.
  3. Validate v2 against known totals, then switch readers (blue-green) and stop v1.
  4. Afterwards: increase retention or enable tiered storage, and keep raw events in the lake as a safety net.

Avoid: patching old results by hand with an estimated correction factor.

Platform · strategy3+ years

“Should we migrate our Lambda platform to Kappa?”

A company runs Lambda: Spark nightly jobs and Flink streaming jobs with duplicated logic. Numbers drift every month. Leadership asks whether to move to Kappa.

The interviewer is checking: balanced reasoning about trade-offs, not a slogan.

Show a strong answer
  • Classify metrics: simple aggregations (counts, revenue) are good Kappa candidates; heavy historical analytics and ML training may stay batch.
  • Check prerequisites: log retention and cost, replay speed, exactly-once sinks, team streaming skills, schema evolution over long histories.
  • Middle path: move duplicated logic into a unified engine (Flink or Spark Structured Streaming) so the same code runs live and over historical tables in the lakehouse.
  • Migrate metric by metric, running old and new in parallel and comparing outputs before switching.

Avoid: a big-bang rewrite, or claiming Kappa is always better.