Stream Processing and Event Streaming Questions
Building on event-streaming platforms: Kafka and message queues, event sourcing, partitioning, consumer groups, exactly-once vs at-least-once delivery, and windowing. Covers handling late and out-of-order events, watermarks, and stateful stream operators. The core skill for real-time data engineering.
For a real-time scoring use case, compare embedding a machine learning model's inference directly inside the stream-processing job versus calling out to a separate model-serving service. What drives the choice?
Sample Answer
Direct answer
Embedding a model's inference directly inside the stream job avoids network round-trip latency and an external dependency, favoring the lowest-latency path; calling out to a separate model-serving service centralizes model versioning, scaling, and monitoring for the model independent of the streaming job, favoring operational cleanliness at the cost of added latency and a new failure mode.
Structured elaboration
Embedding the model means the model's weights and inference code ship as part of the stream job's own deployment artifact, so scoring an event never leaves the process, the fastest possible path but meaning every model update requires redeploying the streaming job itself, and the job's own resource footprint (memory, potentially GPU) now includes the model's requirements too. A separate serving call decouples model lifecycle from the streaming job's lifecycle entirely (the model team can deploy a new model version independently, with its own canary and rollback process), and lets the model-serving layer scale and be monitored on its own, at the cost of a network call on the hot path (latency, and a new dependency that can fail or slow down independent of the streaming job's own health).
Worked example
A use case needing sub-millisecond scoring latency at extremely high event volume, where the model changes infrequently, favors embedding: no external call, and infrequent model updates mean the redeploy-to-update cost is acceptable. A use case where the model is updated frequently (multiple times a day, by a separate ML team iterating quickly) and can tolerate a few milliseconds of added latency favors a separate serving call, decoupling the model team's release cadence entirely from the streaming job's own deployment schedule.
Trade-offs and pitfalls
Embedding ties the streaming job's own release cycle to the model's release cycle, which can become a real organizational bottleneck if the model changes far more often than the streaming logic itself does. Calling out to a serving layer adds a genuine new failure mode (the serving layer being slow or down) that the streaming job needs an explicit fallback behavior for (skip scoring, use a cached prior score, or apply backpressure), not silently blocking indefinitely on a stalled call.
Compare Avro, Protocol Buffers, and JSON as serialization formats for streaming events. Discuss payload size, parsing speed, and how well each supports schema enforcement and evolution.
Sample Answer
Direct answer
Avro and Protocol Buffers are both compact, schema-driven binary formats well suited to high-throughput streaming, with Avro's schema-registry integration especially mature in the Kafka ecosystem, while JSON is human-readable and requires no schema-registry infrastructure at all, at the cost of much larger payloads, slower parsing, and no built-in schema enforcement.
Structured elaboration
Avro embeds enough information (via a schema known to both producer and consumer, resolved through a schema registry) to serialize very compactly with no field names repeated per record, and has first-class, mature tooling for schema evolution and compatibility checking in the streaming ecosystem specifically. Protocol Buffers achieve similarly compact payloads via field numbering rather than a full schema lookup, and are often preferred by teams already using them for gRPC service contracts, giving one shared schema definition style across both streaming and RPC. JSON needs no schema registry, no code generation, and is trivially human-readable for debugging, but every record repeats its field names as text, inflating payload size significantly, and has no built-in mechanism to detect a breaking schema change before it happens.
On parsing speed specifically: JSON parsing is the slowest of the three because a decoder has to tokenize raw text, infer types on the fly, and match string field names against the target structure for every single record. Avro and Protobuf are both binary formats and parse substantially faster since there's no text tokenization or type inference involved, but they aren't identical to each other either: Protobuf typically decodes a bit faster than Avro in practice because its generated (code-genned) bindings give direct, compiled field access by tag number, whereas Avro's decoding commonly goes through a schema-resolution step at read time (matching the writer's schema against the reader's), which is very fast but still an extra layer of indirection compared to Protobuf's generated getters.
Worked example
For a very high-throughput, cost-sensitive pipeline (billions of events per day where payload size and per-record decode cost directly affect network, storage, and CPU cost), Avro or Protobuf's compactness and faster parsing pay for themselves quickly; for a lower-volume internal debugging or prototyping topic where engineers frequently want to eyeball raw messages without a deserialization tool, JSON's readability is worth the size and parsing-speed cost. A team already using Protobuf for its gRPC services often standardizes on Protobuf for its Kafka topics too, avoiding the cost of maintaining two separate schema ecosystems, and getting Protobuf's typically faster decode path as a side benefit.
Trade-offs and pitfalls
JSON's lack of enforced schema is the most common source of "silent breaking change" incidents: a producer field rename or type change ships with no build-time or registry-level warning, and consumers discover the break only in production. Avro's registry-based approach requires the extra infrastructure and operational dependency of running (or using a managed) schema registry, which is a real cost some smaller teams underestimate before committing to it. On parsing speed, it's easy to overweight the Protobuf-versus-Avro difference: it's real but usually much smaller than either format's gap versus JSON, so choosing between Avro and Protobuf should still be driven mainly by ecosystem fit (schema registry maturity, existing gRPC usage) rather than a marginal decode-speed edge.
Design a streaming ingestion and processing architecture for a real-time feature store serving online ML models: partitioning strategy for low-latency per-key lookups, retention/compaction choices, and how you tolerate single-node failures without serving stale or missing features.
Sample Answer
Direct answer
A real-time feature store for online ML models needs a partitioning strategy that puts each entity's features on a predictable partition for fast, direct key lookups, retention and compaction tuned to keep only the latest feature values per entity (not full history), and a design that tolerates a single node's failure without ever silently serving stale or missing features to a live model.
Structured elaboration
Partitioning by the entity key (user ID, item ID) that models actually look up by ensures a serving request can go directly to the partition holding that entity's current features, without a broader scan; this is the same partitioning discipline as any low-latency keyed lookup. Compaction (keeping only the latest value per feature key, discarding intermediate history) is exactly the right retention policy here, since online serving only ever needs the current feature value, not its full history (which, if needed at all, belongs in an offline feature store instead). Fault tolerance against a single node's failure means the serving layer must have replicated, quickly-failover-capable storage for the hot feature data (not relying on a single node being the only place a feature value lives), and the serving API needs an explicit behavior for a genuinely unavailable feature (a documented default or a graceful degradation of the model's confidence) rather than silently substituting a stale value with no signal that it's stale.
Worked example
A feature store serving personalization features for 200,000 events per second at under 10 milliseconds of latency: features are partitioned by user ID (matching the natural lookup key), stored in a compacted topic or equivalent low-latency key-value store that keeps only the latest value per user, replicated across at least two nodes so a single node failure fails over transparently to a replica rather than serving errors, and the serving API returns an explicit "feature unavailable, using model default" signal rather than a silently stale value when a genuine gap occurs (say, a brief replication lag right after a node failure).
Trade-offs and pitfalls
Relying purely on compaction for freshness assumes producers are reliably emitting updated feature values often enough that a stale-but-present value is rare; if an upstream feature-computation job stalls, compaction alone won't tell you the value is now dangerously stale, since the last value is still technically present, just old, which is why a separate freshness metric (time since last update per feature) matters as its own monitored signal, distinct from whether a value exists at all.
Explain the difference between event time, processing time, and ingestion time in stream processing, and give a concrete example where using the wrong one produces an incorrect result.
Sample Answer
Direct answer
Event time is when something actually happened in the real world; processing time is when your system happens to handle it; using processing time when event time is what actually matters produces a result that reflects your pipeline's own timing quirks (delays, retries, backpressure) rather than the reality you're trying to measure.
Structured elaboration
The two only coincide when data arrives instantly and in order, which almost never holds in a real distributed system: network delays, retries, mobile devices batching and later flushing offline events, and backpressure all mean a batch of events can arrive minutes or hours after they actually occurred, and can arrive out of the order they happened in. Any metric computed by grouping on processing time ("count of events I happened to receive this hour") answers a different, less useful question than the one grouped by event time ("count of events that actually happened this hour"), and the two answers diverge exactly when your pipeline experiences any delay or reordering, which is precisely when correctness matters most.
Worked example
A mobile app logs a purchase event at 11:58 PM while the phone is offline; the event only reaches the server and gets processed at 12:15 AM the next calendar day, once connectivity returns. A metric grouped by processing time would count that purchase in the wrong day's revenue entirely, inflating the next day and understating the true day it happened on. Grouped by event time (the 11:58 PM timestamp recorded on the device), the purchase correctly lands in the original day's total, which is the number a finance team actually needs.
Trade-offs and pitfalls
Event time requires trusting the timestamp the event carries, which is only as reliable as its source (a device with a wrong clock, or a system that stamps arrival time rather than occurrence time, undermines the whole approach); processing time needs no such trust and is simpler to reason about, which is why it's still the right choice for genuinely processing-time-relevant metrics (like measuring your own pipeline's throughput or latency, where you actually do want to know when things were handled, not when they happened). The mistake is applying one uniformly everywhere rather than choosing per metric based on what question is actually being asked.
Tell me about a time you disagreed with other engineers about moving a workload into real-time streaming. What was the disagreement, and how was it resolved?
Sample Answer
Direct answer
When I disagreed with other engineers about moving a workload to real-time streaming, the strongest resolution came from grounding the disagreement in a specific, measurable requirement (an actual latency need) rather than a general preference for or against streaming architecture.
Structured elaboration
The disagreement centered on whether a nightly batch job computing a business metric should move to streaming; some engineers favored streaming because it felt more modern and would eventually be needed anyway, while I was skeptical the current requirement actually justified the added operational complexity (a new class of infrastructure, new failure modes, a team that hadn't yet operated a stateful streaming job). Rather than resolving this through opinion, we agreed to define the actual latency requirement explicitly: how fresh did the metric genuinely need to be for the business decision it supported, and did the current nightly batch actually cause any real, documented pain.
Worked example
Once we looked, the business decision the metric supported was made weekly, not daily, meaning the nightly batch's freshness was already far tighter than what was actually needed; we deferred the streaming migration, documenting the specific latency threshold that WOULD justify revisiting it later, rather than either side simply prevailing on preference. That threshold became the actual decision criterion for a future conversation, not something either of us had to re-argue from scratch.
Trade-offs and pitfalls
The lesson I took from this was that architecture disagreements resolve far better when both sides agree on what evidence would settle the question before gathering it, rather than each side arguing from its own instinct about what feels right; documenting the threshold that would trigger revisiting the decision also meant the debate didn't quietly resurface every few months without new information.
Unlock Full Question Bank
Get access to all 29 Stream Processing and Event Streaming interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.