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.
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."
Compare batch processing and stream processing as general models, then bring Lambda and Kappa architecture into the comparison. For a concrete analytics workflow of your choosing, walk through why you would pick pure batch, pure streaming, Lambda, or Kappa.
Sample Answer
Direct answer
For any given analytics workflow, the choice isn't a single spectrum from batch to streaming; it's two separate decisions layered on top of each other: how fresh does this need to be (which points you toward batch or streaming), and, if you need streaming, do you also need a batch backstop for correctness (which is the Lambda-vs-Kappa question).
Structured elaboration
Start with the freshness requirement. If the consumer can tolerate minutes-to-a-day of latency, pure batch wins on cost and operational simplicity; there's nothing to gain from adding streaming machinery. If the consumer needs sub-second-to-seconds latency, you need some form of streaming, full stop, because no amount of clever batch scheduling gets you there.
Once you've established you need streaming, the second decision is whether a single streaming codepath (Kappa) is trustworthy enough on its own, or whether you want a separate, deterministic batch recomputation as a correctness backstop (Lambda). That decision usually turns on: how expensive is being wrong (financial reporting wants a backstop; a live view-count doesn't), and how cheap is full-history replay in your streaming stack (if replay is fast and reliable, Kappa's single codepath is enough; if it isn't, or if a regulator wants a simple, deterministic recompute story, add the Lambda-style batch layer).
Worked example
Take a concrete workflow: computing daily active users for a product dashboard, with a secondary need for a live "users online right now" counter.
- Pure batch fits the daily-active-users number: it's consumed once a day, needs to be exactly right, and a nightly job scanning the day's log is both cheap and simple.
- Pure streaming fits the live counter: it needs to update within seconds and an occasional off-by-a-few-users error during a brief network blip is not a business problem.
- Kappa would fit if this company later wants daily active users computed from the same streaming pipeline as the live counter, and their streaming engine can cheaply replay a day's worth of events to recompute that day's number deterministically, avoiding a second batch codebase.
- Lambda would fit if daily active users feeds into a revenue-attribution or billing calculation where the company genuinely wants a batch recompute as an audit trail, independent of whatever the streaming engine's live counter reported.
Trade-offs and pitfalls
The pitfall in this kind of question is answering "it depends" without giving the two-step decision structure that makes it not ambiguous: freshness requirement first, correctness-backstop need second. Answering with just "streaming is for real-time and batch is for reports" skips the actual judgment call, which is when a single streaming codebase is trustworthy enough to be the only source of truth, and when it isn't.
Your team processes 100M events/day through a batch pipeline and retrains models every few hours. Someone proposes adding real-time features for personalization. Before committing to that, how would you evaluate whether the need is real: what minimal experiment or prototype would you run, and what objective success and cost criteria would decide whether it's worth building?
Sample Answer
Direct answer
Before building anything, I'd run a cheap, time-boxed experiment (a data-only prototype, not a real streaming pipeline) that estimates the upper bound of value real-time features could add, using data the team already has, and only commit to the real build if that upper bound clears a cost threshold worth the engineering investment.
Structured elaboration
The minimal experiment: take a sample of historical events, and instead of building a live streaming pipeline, simulate what a real-time feature would have looked like by re-deriving it from the existing batch data at fine time granularity (for example, reconstructing "user's activity in the last 5 minutes" from timestamped logs offline). Feed that simulated feature into an offline evaluation of whatever downstream system would use it (a recommendation model, a personalization rule), and measure the lift over the current nightly-batch-derived feature. This gives a real signal about value without paying for any streaming infrastructure.
Why this bounds the value from above: a production real-time pipeline will always be somewhat noisier and lossier than a perfectly-reconstructed offline simulation (late data, partial state on cold start, occasional gaps), so if the simulated version doesn't show a meaningful lift, a real implementation won't either, and you've avoided the build entirely.
Objective success criteria: define the lift threshold before running the experiment, not after seeing the result, ideally in terms the business cares about (a lift in a downstream metric like conversion rate or session length, not just a proxy metric like feature correlation). Also define a cost threshold: estimate the ongoing infrastructure and operational cost of a real streaming build (compute, on-call burden, added system complexity), and require the measured lift to translate into more business value than that ongoing cost, not just be statistically distinguishable from zero.
Worked example
Suppose the offline simulation shows that using 5-minute-fresh features instead of the current several-hours-old batch features would lift a downstream conversion metric by an estimated 0.3 percentage points on a baseline of 4%, a real but modest improvement. If that lift, extrapolated across current volume, is worth less per month than the estimated cost of running the streaming infrastructure to get 5-minute freshness in production, that's a clear "not yet" answer, and the team should revisit only if volume grows enough to change that math, or if the freshness need becomes strategic rather than incremental.
Trade-offs and pitfalls
The main pitfall is running the offline simulation but skipping the cost side of the comparison, which tends to happen when the team is technically excited about streaming and only wants to prove the value case, not weigh it. The other pitfall is picking a lift threshold that's too easy to clear (any statistically significant lift, however tiny) rather than one tied to whether the lift is large enough to justify the ongoing operational cost; a real-time feature that's measurably better but not meaningfully better is a bad trade once you account for what running it in production actually costs.
Design an approach to compute per-city, per-minute aggregates (trip count, median fare, median ETA) updated every minute for dashboards. Would you use materialized views, streaming pre-aggregations, or periodic batch aggregation, and why? Justify the trade-offs in latency, cost, and accuracy, calling out anything (like a median) that doesn't aggregate as cleanly as a sum or count.
Sample Answer
Direct answer
For per-minute, per-city aggregates like trip count and median fare, I'd use streaming pre-aggregation for the additive metrics (trip count, sum of fares) and handle median separately, since a true median can't be incrementally updated the way a count or sum can; the practical approach is either a periodic recompute of the median from a bounded recent window, or an approximation (like a t-digest or histogram sketch) that can be updated incrementally.
Structured elaboration
Materialized views vs. streaming pre-aggregations vs. periodic batch aggregation, for this workload: on-demand compute (scanning raw trip events at query time) is a non-starter here, since doing that on every dashboard refresh, every minute, across every city, doesn't scale. That leaves three named options. A materialized view is a stored, incrementally-maintained result kept in sync as new data arrives, refreshed either continuously or on a trigger. Periodic batch aggregation is different in kind: a scheduled job that recomputes the aggregate from scratch over a raw window and replaces the prior value wholesale, cheap to reason about but only as fresh as its last run. Streaming pre-aggregation is a continuously-updating computation that emits an updated value on (or shortly after) every new event, the freshest of the three but the most operationally involved. The per-minute freshness bar effectively decides between the three: a tightly-scheduled periodic batch aggregation can hit a few-minutes latency cheaply and is the simplest to operate, but streaming pre-aggregation is what actually gets you a smooth, continuously-updating per-minute number without a visible "jump" every refresh cycle, and a materialized view refreshed on a normal warehouse trigger cadence usually lands somewhere in between the two on both freshness and cost, unless the warehouse specifically supports near-real-time incremental refresh.
Why median is the interesting part of this question: count and sum are associative and incrementally combinable (add the new trip's fare to a running sum, increment a counter), so a streaming aggregator can maintain them cheaply as new events arrive. Median is not: you cannot get the exact median of a growing set by combining a small update with the previous median, it requires access to the full sorted set (or an equivalent structure) for that window.
Two honest options for median: (a) maintain a bounded window of raw fares in state (feasible if the per-city, per-minute volume is small enough to hold in memory) and compute the true median from that window on each emit; (b) use an approximate percentile sketch (t-digest or a histogram-based approach) that supports incremental updates and gives a median within a known error bound, which scales to much higher volume at the cost of exactness.
Worked example
A mid-size city with roughly 200 trips/minute can comfortably hold that minute's fares in memory and compute an exact median from the sorted list, so option (a) is the right, simplest choice there. A high-volume city with 50,000 trips/minute holding a full minute of raw fares in state for an exact median starts to add real memory pressure across many cities simultaneously, so a t-digest sketch, updated incrementally per event, giving a median accurate to within a small, bounded error, is the more scalable choice, and the small accuracy trade-off is invisible to a dashboard consumer who's reading "$14.20" versus a true "$14.18".
Trade-offs and pitfalls
The pitfall in this kind of question is treating all three metrics (count, sum-derived-fare, median) the same way and reaching for one uniform technique; the right design explicitly separates the additive metrics (cheap to stream-aggregate exactly) from the median (which needs either bounded state or an approximation). The other pitfall is choosing periodic batch materialization for cost reasons and then being surprised the dashboard looks "jumpy", updating in visible steps rather than smoothly, which matters if the UX goal is a live-feeling dashboard rather than just an accurate one.
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.
Unlock Full Question Bank
Get access to all 7 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.