Batch, Streaming, and Real-Time Serving Trade-offs Questions
Reasoning about when to use batch, micro-batch, or continuous streaming and how to serve low-latency analytics: latency, cost, complexity, and correctness trade-offs; lambda vs kappa architectures; and reprocessing semantics. Covers real-time aggregation, freshness vs consistency trade-offs, and reconciling streaming results with batch ground truth, including geospatial and high-throughput real-time workloads under eventual consistency. The data-systems judgment topic for choosing and reconciling batch versus real-time approaches, distinct from the hands-on streaming transport itself.
Compare the Lambda and Kappa architectures for combining batch and streaming processing: what components does each have, what operational complexity does maintaining two codepaths (Lambda) versus a single replayable streaming codepath (Kappa) actually cost you, and when would you choose one over the other?
Sample Answer
Direct answer
Lambda architecture runs two separate codepaths, a batch layer for accuracy and a speed layer for freshness, and merges their outputs at serving time. Kappa architecture collapses that into a single streaming codepath with full replay capability, using reprocessing instead of a second batch system to get accuracy. Lambda buys you a battle-tested batch layer as a correctness backstop at the cost of maintaining two implementations of your business logic; Kappa buys you one codebase at the cost of your streaming engine and storage having to support cheap, full-history replay.
Structured elaboration
Lambda's components: a batch layer (recomputes accurate views from the full historical log, usually on a schedule), a speed layer (a stream processor providing low-latency, possibly-approximate views of very recent data), and a serving layer that merges the two, typically overwriting the speed layer's view for a time window once the batch layer's more-accurate result for that window lands.
Kappa's components: a single durable, replayable event log (the source of truth) and one stream-processing codebase that both handles live traffic and, when you need to fix a bug or backfill, gets pointed at an earlier offset and replayed through the same code.
The real cost of Lambda is that your batch and speed layers are two independent implementations of the same business logic, in whatever language/framework each layer uses, and they can silently drift apart (a bug fixed in one and not the other, a metric defined slightly differently). That duplication is the actual argument against it, not raw complexity for its own sake.
The real cost of Kappa is that it pushes all correctness work onto the streaming engine: state management, exactly-once guarantees, and cheap full-history replay for potentially years of data, all inside one system, which is a harder engineering problem than "run a batch job over the same log."
Worked example
A team building fraud scoring that needs both a fast online signal and periodic full retraining on corrected historical labels is a natural Lambda fit: the speed layer scores in real time with best-effort features, the batch layer recomputes ground truth nightly once labels settle, and a small serving-layer reconciliation step swaps in the corrected value. A team building a single, well-defined metrics pipeline (say, per-minute active users) where the exact same logic should always apply, live or replayed, is a better Kappa fit: one Flink job computes it, and a bug fix just means replaying the log from the point of the bug, not fixing and re-deploying two systems.
Trade-offs and pitfalls
A common mistake is choosing Kappa because "one codebase" sounds obviously simpler, without checking whether the team's streaming engine and storage can actually afford cheap, full-history replay at their retention window and data volume; if replay is slow or expensive, Kappa quietly turns into "one codebase, but reprocessing takes three days," which defeats the purpose. The opposite mistake is defaulting to Lambda out of caution and then never actually keeping the two layers' logic in sync, which produces the exact dual-codepath drift Lambda is often criticized for.
Explain the real differences between batch processing and stream processing for a production data platform: latency, throughput, cost, operational complexity, and correctness. Give one concrete workload that clearly favors each approach, and describe a scenario where a hybrid of the two is the right call.
Sample Answer
Direct answer
Batch and streaming are two ways of answering the same question (what does the data say right now) at different points on the latency/cost/complexity curve. Batch reads a large accumulated chunk on a schedule; streaming processes each event as it arrives. Pick batch by default and reach for streaming only when a specific business decision genuinely needs data fresher than the next scheduled run can provide.
Structured elaboration
Latency. Batch is minutes to a day (whatever the schedule is); streaming is sub-second to a few seconds, bounded mainly by how long you wait for late data (the watermark).
Throughput. Batch amortizes overhead across a huge chunk, so it is usually the cheaper way to move the same total volume of data. Streaming pays a small per-event tax (serialization, network hops, state lookups) on every single record, so the same total throughput costs more compute.
Cost. A batch job runs, finishes, and releases its compute. A streaming job holds compute (and often memory-resident state) 24/7 whether or not there's a burst of traffic, so streaming infrastructure has a real always-on cost floor that batch does not.
Operational complexity. Batch failure recovery is simple: rerun the job. Streaming failure recovery has to reason about partial state, checkpoints, exactly-once vs at-least-once delivery, and consumer lag, which means more moving parts, more monitoring surface, and a team that has to understand event-time semantics, not just SQL.
Correctness. Batch naturally sees all the data for a period before computing anything, so late-arriving records are simply part of the input. Streaming has to make an explicit decision about how long to wait for late data (allowed lateness) before it emits a result, which means a streaming aggregate can legitimately differ from the eventual batch recompute of the same period.
| Axis | Batch | Streaming |
|---|---|---|
| Latency | minutes to a day | sub-second to seconds |
| Throughput cost per unit volume | lower (amortized) | higher (per-event overhead) |
| Infra cost floor | zero between runs | always-on |
| Ops complexity | low (rerun on failure) | higher (state, checkpoints, lag) |
| Correctness model | sees everything before computing | must decide how long to wait for late data |
Worked example
A nightly-refreshed revenue dashboard is a clean batch case: the business consumes it once a day, a few hours of latency is invisible to the user, and a failed run just reruns. A fraud-detection system that has to block a card swipe before it completes is a clean streaming case: by the time a batch job would even start, the transaction has already succeeded or failed. A hybrid shows up constantly in practice: a company might run streaming only for the handful of metrics that trigger pages or block a transaction, and leave everything else (the other 90% of reporting) on batch, because paying the always-on cost and operational overhead of streaming for a dashboard nobody checks more than once a day has no payoff.
Trade-offs and pitfalls
The most common mistake is treating this as a technology choice instead of a latency-requirement choice: teams reach for Kafka and Flink because streaming sounds more modern, then discover they've taken on 24/7 operational burden for data nobody looks at more than once a day. The second most common mistake is the opposite: assuming batch is always simpler, when a batch job that has grown large enough to blow its nightly window is itself an operational risk. The right first question is always "what decision does this data drive, and how fresh does it actually need to be to drive that decision correctly," not "which technology is state of the art."
A product team requests near-real-time personalization requiring sub-100ms reads and 1,000 writes/sec. Decide between a stateful streaming architecture and a micro-batch near-real-time approach: compare latency, cost, operational complexity, and developer velocity, and propose a recommended architecture with a migration plan from whatever exists today.
Sample Answer
Direct answer
At sub-100ms reads and 1,000 writes/sec for personalization, a micro-batch approach almost certainly cannot meet the latency bar (even a very tight micro-batch adds tens to hundreds of milliseconds of batching delay before a write is even visible), so this points toward a stateful streaming architecture, with the real design work being how to serve those sub-100ms reads cheaply, not whether streaming is required.
Structured elaboration
Why micro-batch struggles here: a micro-batch interval tight enough to keep end-to-end latency under 100ms (accounting for batch collection time plus processing time) starts to lose most of micro-batching's efficiency advantage, since you're now paying near-continuous compute anyway, without the operational simplicity batch normally offers. At that point you've built something that behaves like streaming but without streaming's tooling for state and exactly-once handling, which is often a worse trade than just using a real streaming engine.
Latency: streaming wins clearly; a stateful stream processor updating a low-latency key-value store as writes arrive can support sub-100ms reads if the read path is a simple point lookup, not a recomputation.
Cost: streaming's always-on compute and (likely) resident low-latency storage cost more than a batch approach would, but at only 1,000 writes/sec, this is a modest-scale system either way, so the absolute cost difference is unlikely to be the deciding factor here, the latency requirement is.
Operational complexity: real, and worth naming honestly: state management, checkpointing, and monitoring for a stream-processing system require different skills than a batch pipeline, and this is a genuine cost of the recommendation, not something to gloss over.
Developer velocity: initially slower to build (more moving parts to get right), but once the pattern is established, adding new personalization signals to an existing streaming pipeline is usually incremental, versus repeatedly re-tuning batch intervals as latency requirements tighten over time.
Worked example
Suppose the current system is a batch job that recomputes personalization signals hourly. The migration plan: (1) stand up a stream processor that consumes the same event source and computes the personalization state incrementally, writing to a low-latency store (Redis or DynamoDB-style key-value store) sized for the 1,000 writes/sec and sub-100ms read requirement; (2) run it in shadow, comparing its computed values against the batch job's hourly output for the same users, to validate correctness before it serves any real reads; (3) cut over reads to the new store behind a feature flag, monitoring read latency directly (not just throughput) to confirm the sub-100ms bar holds under real production load, not just in testing; (4) once validated, retire the hourly batch job, or repurpose it as a periodic correctness-reconciliation check rather than the primary compute path.
Trade-offs and pitfalls
The common mistake is trying to squeeze micro-batch tighter and tighter to chase a latency target it wasn't designed for, rather than recognizing the 100ms bar as a genuine architectural signal to move to streaming; there's a point (well before 100ms) where shrinking the batch interval stops buying meaningful latency improvement and just adds overhead. The other mistake is under-investing in the shadow-validation step in the migration plan, since a stateful streaming system that's subtly wrong (a race condition in how state updates, an edge case in cold-start behavior for a brand-new user with no prior state) is much harder to debug after it's serving live personalization decisions than to catch in a shadow comparison against the known-correct batch baseline.
A team needs both retrainable ML models (which want reproducible, accurate historical data) and low-latency online scoring. Which would you recommend, Lambda or Kappa, and why? Sketch how you would migrate from the other architecture with minimal risk, and describe how you'd keep the online features and the periodic batch snapshots used for training reconciled with each other.
Sample Answer
Direct answer
For a team that needs both retrainable models on reproducible historical data and low-latency online scoring, I'd lean toward a Kappa-style single streaming codebase with an explicit batch snapshot layer bolted on for training, rather than a full Lambda split, because the two consumers (the online scorer and the training pipeline) actually want the same underlying feature-computation logic, and duplicating that logic in a full Lambda setup is where ML teams most often introduce training-serving skew.
Structured elaboration
The key insight is that "low-latency scoring" and "reproducible training data" don't need two different processing engines, they need one feature-computation codebase and two different consumption patterns of its output: a live path for scoring, and periodic durable snapshots of the same computed features for training.
If choosing Kappa-leaning: run the feature computation as a single streaming job (Flink or Kafka Streams) that both serves online reads and periodically materializes a snapshot of feature values to durable storage (a feature store's offline layer or a warehouse table) at a fixed cadence. Training reads the snapshots; serving reads the live streaming state. Because both paths run the same code, a definition change (say, a new bucketing rule for a categorical feature) automatically applies to both, which is exactly the alignment you want.
Migration steps from a Lambda-style setup: (1) identify where the batch and speed layer logic has already diverged, and reconcile them into one shared definition first, before touching infrastructure; (2) stand up the streaming feature-computation job so it can both serve online reads and write periodic snapshots, running it in shadow (not yet serving) against production traffic; (3) validate that the streaming job's snapshots match the batch layer's historical output for a trailing window, within an agreed tolerance; (4) cut serving traffic over, keep the old batch layer running in parallel for a defined bake period as a fallback; (5) once validated, deprecate the separate batch feature pipeline.
Keeping online features and batch snapshots reconciled: version every feature definition (not just the values), so an offline snapshot can be tagged with exactly which code version produced it; run a scheduled comparison job that samples recent online feature values against what the batch snapshot computed for the same entities and time window, and alert if they diverge past a tolerance (some drift is expected from timing, not necessarily a bug, so the tolerance matters).
Worked example
A personalization model retrains nightly on nightly feature snapshots but scores online with sub-second freshness. Before migration, the team has two implementations of "user's 7-day click rate": a Spark job for training data and a Flink job for serving, and they've already seen the two disagree by a few percent because of a rounding difference in a time-window boundary. After migrating to the shared streaming codebase, the same Flink job computes the click rate for both serving and, once a day, snapshots it to the training table, so the discrepancy is structurally impossible rather than something the team has to keep re-verifying.
Trade-offs and pitfalls
The risk in this approach is treating the snapshot cadence as free: if training needs feature values reproducible for a specific historical instant (for point-in-time correctness, avoiding label leakage), the snapshot job has to be built with that discipline from day one, not bolted on later, since a naive "just query current state" snapshot will leak future information into training data. The other pitfall is skipping the shadow-validation step under time pressure; training-serving skew introduced silently during a rushed migration is far more expensive to debug after the fact than the extra week the validation step costs upfront.
You must recommend moving a high-throughput analytics pipeline from nightly batch to near-real-time streaming. Build a decision framework comparing latency, cost, operational complexity, data correctness, and business value, then outline a phased migration plan (parallel run, parity validation, cutover) and a rollback strategy.
Sample Answer
Direct answer
The decision framework has five parts (latency, cost, operational complexity, data correctness, and business value), and the answer to "should we migrate" only becomes yes once a genuine business need for latency below what batch can deliver is established; the migration itself should be executed as a parallel-run, not a cutover, so correctness is proven before the old system is retired.
Structured elaboration
Decision framework:
- Latency: quantify the gap between what batch currently delivers and what the business need actually requires; if the gap is small (batch already delivers close to what's needed), the case for migrating weakens regardless of the other axes.
- Cost: streaming's always-on compute and operational overhead versus batch's pay-per-run model; this is a real, ongoing cost increase that should be weighed against the latency gain, not treated as a rounding error.
- Operational complexity: honestly assess whether the team has (or can build) the skills to run a production streaming system: state management, monitoring, on-call for a system that, unlike batch, can't just be "rerun tomorrow" if it breaks.
- Data correctness: streaming introduces a genuinely different correctness model (event-time semantics, watermarks, late data) that batch never had to reason about; this isn't free even with a well-executed migration.
- Business value: translate the latency improvement into an actual business outcome (faster fraud detection catching more fraud, fresher dashboards changing a decision sooner), not just "more real-time is better."
Phased migration plan:
- Parallel run: stand up the streaming pipeline alongside the existing batch pipeline, both reading from the same source, without the streaming pipeline serving any production traffic yet.
- Parity validation: compare the streaming pipeline's output against the batch pipeline's output over a meaningful historical window (including known edge cases like month-end, late data, and any past incidents), at a fine enough granularity that compensating errors can't hide behind a matching aggregate total.
- Cutover: once parity holds for an agreed bake period, switch downstream consumers to the streaming pipeline's output, ideally behind a flag that can be reversed quickly.
- Deprecation: only after the cutover has run cleanly through a full business cycle (including whatever periodic events, like month-end close, are most likely to expose a gap) does the old batch pipeline get formally retired.
Rollback strategy: keep the batch pipeline's code and infrastructure intact (not deleted, just not the primary path) until deprecation, and make the cutover a config/flag change, not a one-way infrastructure migration, so reverting doesn't require rebuilding anything under incident pressure.
Worked example
A 200 TB/day pipeline is approaching its nightly batch window's limit (the job is starting to run past when downstream consumers need it ready). Rather than treating this purely as "the batch job needs to be faster," the team quantifies the actual business latency need (in this case, dashboards need to be ready by 7am, and the batch job is now finishing at 6:45am with shrinking margin) and concludes a streaming migration is justified not by a desire for lower latency in the abstract, but by a concrete, worsening operational risk in the current batch approach. The migration proceeds through the four phases above, with parity validated against three months of historical data including the last two month-end closes, which is where a subtle late-data handling bug in the new streaming pipeline is actually caught, before it ever touched production.
Trade-offs and pitfalls
The most common failure is skipping straight to "we need streaming" once a batch job is straining, without first asking whether the underlying problem (a batch job that's grown too large or inefficient) has a batch-side fix (better partitioning, incremental processing, a bigger cluster) that's cheaper and lower-risk than a full paradigm migration. The second failure is compressing or skipping the parallel-run/parity-validation phase under deadline pressure, which is exactly how subtle correctness bugs (event-time edge cases, a different late-data policy than the old system implicitly had) end up discovered in production instead of in validation.
Unlock Full Question Bank
Get access to all 9 Batch, Streaming, and Real-Time Serving Trade-offs interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.