Data Pipeline Monitoring and Observability Questions
Observing pipeline health: freshness, volume, schema, and distribution monitoring; lineage; alerting; and data-downtime detection. Covers instrumenting pipelines, defining SLAs/SLOs for data, and observability tooling. The operational-visibility discipline for data platforms.
Define data lineage and describe three concrete operational uses of lineage metadata specifically for pipeline monitoring and incident response, for example impact analysis, replay and backfill, or SLA enforcement. For one of those uses, state the minimum lineage information required and how it would actually be queried during a live incident.
Sample Answer
Direct answer
Data lineage is the recorded chain of transformations and dependencies a piece of data passes through, from its original source to every table, report, or model that consumes it. For pipeline monitoring and incident response it matters because it turns "something downstream is wrong" into "here is the exact upstream cause and the exact list of things affected," which no amount of per-stage monitoring alone can tell you.
Structured elaboration
Three concrete operational uses:
- Impact analysis: given a corrupted or delayed upstream table, lineage answers "which downstream tables, dashboards, and models are affected" so you can notify the right people and suppress the right alerts without guessing or manually tracing SQL.
- Replay and backfill targeting: when you fix an upstream bug, lineage tells you exactly which downstream artifacts need to be recomputed, rather than either replaying everything (wasteful) or guessing a subset (risks leaving stale, wrong data in some untouched table).
- SLA enforcement and root-cause attribution: if a downstream SLA breach occurs, lineage lets you attribute the delay to the specific upstream job or partition that was late, instead of investigating the whole pipeline graph by hand.
Worked example
Take impact analysis specifically. The minimum lineage information required is a directed edge list: for each table or dataset, which upstream tables and which job run produced it, ideally down to the partition or run-id granularity (not just "table A depends on table B" but "partition 2026-07-22 of table A was produced by run 4471, which read partition 2026-07-22 of table B"). During a live incident, "upstream table B's partition for today is corrupted," you would query the lineage graph starting at that node and traverse forward (downstream) to enumerate every table, and by extension every dashboard or model, that consumed that specific partition. A well-indexed lineage store answers that query in under a second even across a graph with millions of edges; without it, you'd be grepping SQL definitions or asking team leads by Slack message, which takes hours during exactly the window when speed matters most.
Trade-offs and pitfalls
The main pitfall is capturing lineage at too coarse a granularity, table-level only, which tells you table A depends on table B in general but not whether TODAY's corrupted partition of B actually fed the specific downstream partition you're worried about, forcing you to over-notify (flagging consumers who were never actually affected by this run) or under-notify (missing a partition-level dependency a table-level view hides). The other common failure is letting lineage capture go stale: if it's captured by manual annotation rather than automatically extracted from job runs or query parsing, it drifts from reality exactly as pipelines evolve, and a lineage graph you can't trust during an incident is worse than no lineage graph, because it gives false confidence.
You are given a time series of daily row counts per partition. Design an approach to detect a SLOW-DRIP silent failure, one where counts decay gradually over weeks rather than dropping suddenly, and distinguish that from legitimate seasonal decline. How would you tune sensitivity, and what would you check first (producer, broker, or consumer/ETL layer) once the decay is confirmed real?
Sample Answer
Direct answer
A slow-drip silent failure, where row counts decay gradually over weeks rather than dropping suddenly, needs a detector tuned for TREND, not point-in-time deviation: comparing a smoothed recent trend against a smoothed historical trend, rather than comparing today's raw count to yesterday's or to a single historical baseline, since a gradual decline can hide inside normal day-to-day noise for a long time before any single day looks obviously wrong.
Structured elaboration
- Why point-in-time checks miss this: a simple "today vs. yesterday" or "today vs. trailing median" check tolerates small day-to-day swings by design, and a slow decay (losing 1-2% per week) stays within that normal-variance tolerance band for a long time, each individual day looks fine relative to its immediate neighbors even as the underlying trend is clearly downward over a longer window.
- Detector design: compute a smoothed trend line (a moving average over, say, 14 days) and compare its SLOPE over the trailing 4-8 weeks against a near-zero or seasonally-adjusted expected slope; a sustained negative slope over multiple weeks, even a small one, is the signal, not any single day's absolute value.
- Distinguishing decay from legitimate seasonal decline: overlay the same weekday comparison across YEARS, not just weeks, if this pattern recurs at the same calendar period every year (a known seasonal dip), it's legitimate; if the decline is unprecedented relative to the same period in prior years, it's more likely a real failure.
- Sensitivity tuning: set the slope-detection threshold based on the smallest decay rate you actually care about catching before it becomes a real problem (for example, a cumulative 10% loss over 8 weeks), rather than trying to catch every tiny fluctuation, which would be too noisy to be actionable.
Worked example
Concretely: a table's daily row count has a typical range of 95,000-105,000 with no obvious pattern day to day, so no point-in-time alert ever fires. Plotted as a 14-day moving average over 8 weeks, though, the trend line drops from about 102,000 to about 89,000, a roughly 13% decline with a clearly negative slope. The seasonal check confirms this same 8-week period last year showed a flat trend, ruling out a recurring seasonal explanation. Tracing which layer is responsible: producer logs, still emitting at a normal rate; Kafka retention/offsets, no gaps; consumer/ETL (extract, transform, load) layer, this is where the investigation lands, checking recent deploys to the consumer finds a filter condition added five weeks ago that was slightly too aggressive, silently excluding a small but growing subset of legitimate records as an edge case in the filter logic gradually widened its unintended impact.
Trade-offs and pitfalls
A slope-based trend detector inherently has a longer detection lag than a point-in-time anomaly detector, by design, since it needs several weeks of data to distinguish a real trend from noise, which is the trade-off you accept for catching a class of failure that point-in-time checks structurally cannot see. The pitfall is setting the trend window too short, a 5-day moving average is still noisy enough to false-positive on ordinary week-to-week variance, while a window long enough to be stable (14+ days) means a slow-drip failure that started only 10 days ago won't show a clear trend yet, so this detector complements rather than replaces point-in-time checks, it doesn't substitute for them.
A critical revenue dashboard shows a large, unexpected drop compared to the same period last week. Outline a prioritized investigation using observability data: which metrics, logs, traces, and lineage queries you would run first, how you would determine whether the cause is instrumentation, pipeline data loss, a transformation bug, or downstream logic, and what mitigation you would apply while still investigating.
Sample Answer
Direct answer
Investigating a large, unexpected revenue-dashboard drop against the same period last week means working through observability signals in a specific order: metrics first to bound WHEN and by HOW MUCH, traces or lineage next to localize WHERE in the pipeline, then logs to find WHY, while applying mitigation as soon as you're confident enough, not only after the full root cause is known.
Structured elaboration
- Metrics first: check the revenue metric's time series at finer granularity than the daily aggregate (hourly, if available) to see whether the drop is a sudden step-change at one point in time (suggesting a pipeline event) or a gradual decline (suggesting a genuine trend). Also check adjacent metrics, order count and average order value separately, since revenue is a product of both, and a drop in one but not the other narrows the search space immediately.
- Lineage next: once you know roughly WHEN the drop started, use lineage to identify which upstream jobs and tables feed the revenue metric, and check whether any of them had an unusual run (failed, partial, or unusually fast/slow) around that time.
- Logs and traces: for the specific job/run lineage flagged as suspect, pull its logs for errors or warnings, and check traces for that run's per-stage timing to see if one stage behaved abnormally.
- Determine the cause category: instrumentation (an event-tracking bug undercounting orders at the source), pipeline data loss (a job failed partway and didn't reprocess), a transformation bug (a recent code change to the revenue calculation), or downstream logic (the dashboard query itself changed). Each points to a different owning team and a different fix.
- Mitigate while investigating: if you can confirm the underlying data is fine and only the DASHBOARD's calculation or presentation is wrong, you can often revert a recent dashboard-layer change immediately as a stopgap while the deeper investigation continues, rather than waiting for full root cause before doing anything.
Worked example
Concretely: the daily aggregate shows revenue down 18% versus last week. Hourly breakdown shows the drop is concentrated entirely in a 3-hour window overnight, not spread evenly across the day, ruling out "the whole day was just slow" and pointing toward a specific event. Order count for that window is also down proportionally, while average order value is flat, which rules out a pricing/discount bug (that would show flat order count with lower average value) and points toward missing orders. Lineage shows the orders_raw table's ingestion job for that window completed in 4 minutes instead of its usual 25, a strong signal of a partial or truncated run. The job's logs confirm: a Kafka consumer restarted mid-run and resumed from a committed offset that skipped roughly 3 hours of unconsumed messages due to a retention/offset misconfiguration during the restart. Mitigation: replay the skipped offset range from Kafka's retained log (still within retention window) to backfill the missing orders, while a longer-term fix addresses the offset-handling bug in the consumer restart logic.
Trade-offs and pitfalls
Checking metrics at finer granularity (hourly, not just the daily aggregate) before diving into logs is what actually narrows the search space efficiently; starting immediately with logs across an entire day's worth of job runs, without first bounding the time window, wastes significant investigation time. The pitfall to avoid is declaring the investigation complete once you've found A plausible explanation without confirming the magnitude actually accounts for the full observed drop, if the Kafka gap only explains half the missing revenue, there is a second contributing cause still undiscovered, and stopping early risks shipping an incomplete fix.
A dashboard shows stale results, last refreshed several hours ago, even though the nightly ETL job did not report any errors. Walk through a step-by-step triage plan across the ingestion, transformation, storage, and serving layers to find the root cause, including the first two or three quick checks you would run.
Sample Answer
Direct answer
A dashboard showing stale results despite the nightly ETL (extract, transform, load) job reporting no errors is a classic silent-failure pattern: the job's SUCCESS signal only tells you the process exited cleanly, not that fresh data actually reached the dashboard. The triage plan works backward through the serving, storage, transformation, and ingestion layers, checking each layer's freshness independently rather than assuming the problem is wherever you'd guess first.
Structured elaboration
- Serving layer first (cheapest to check): is the dashboard tool itself caching a stale query result? Check the dashboard's own cache/refresh timestamp before assuming the underlying data is stale, a BI tool with an aggressive cache TTL (time-to-live) can show old numbers even when the warehouse table underneath is perfectly fresh.
- Storage layer: query the underlying table directly, bypassing the dashboard, and check its actual last-updated timestamp or max partition date. If the table itself is fresh but the dashboard isn't, the problem is entirely in the serving/caching layer, not the pipeline.
- Transformation layer: if the table is stale, check whether the transformation job that populates it actually ran and wrote data for the expected window, a job can "succeed" while writing to the WRONG partition (an off-by-one date bug) or writing zero new rows into an already-existing partition.
- Ingestion layer: if the transformation job legitimately had no new data to process, check whether the upstream source actually delivered anything, an upstream extraction job might have silently produced an empty extract that fed cleanly, with zero errors, into a transform that correctly processed zero rows.
Worked example
Concretely: first two or three checks. Check 1, query the dashboard's underlying table directly: SELECT MAX(partition_date) FROM fact_orders returns yesterday's date, one day stale, confirming the problem isn't dashboard caching. Check 2, check the transform job's run log for last night: it shows SUCCESS, completed in normal time, but a closer look at row counts shows it wrote 0 rows to today's partition. Check 3, check the ingestion layer's extract for today: the extract job also shows SUCCESS but its output file is 0 bytes, tracing back to an upstream source system that had a maintenance window overnight and produced no export, which its own monitoring didn't catch because it also only checked "did the export process run," not "did it produce a non-trivial file."
Trade-offs and pitfalls
The efficient order is cheapest-to-check-first (serving layer cache, a quick lookup) before more expensive investigation (tracing through transformation and ingestion logs), since a meaningful fraction of "stale dashboard" complaints turn out to be pure caching issues with perfectly fresh underlying data. The pitfall is skipping straight to "the pipeline must be broken" and starting a deep pipeline investigation before ruling out the cheap, common cause first, which wastes time on days when the real answer was a five-second cache check. Once you do trace into the pipeline, checking "did it run" without ALSO checking "did it produce a nontrivial row count" is precisely the gap that let this incident go undetected for two layers running before anyone noticed.
Walk through the three pillars of observability, logs, metrics, and traces, in the specific context of a data pipeline. For each pillar, give one concrete example (a metric name, a representative log line, or a trace span) and explain when an on-call engineer investigating a late-arriving record would reach for that signal first.
Sample Answer
Direct answer
Logs, metrics, and traces are the three pillars of observability. Logs are discrete, timestamped events carrying rich context (an error message, a row count, a stack trace). Metrics are numeric time series, cheap to store and query, good for trends and alerting. Traces (or in a batch pipeline, lineage-annotated run metadata) capture the causal path a piece of work took across stages, which is what lets you go from "stage 3 is slow" to "specifically this partition, fed by this upstream job, is the bottleneck."
Structured elaboration
For a data pipeline, a concrete example of each:
- Metric:
pipeline_stage_duration_seconds{pipeline="orders_etl", stage="transform"}, a histogram you'd chart to see the transform stage creeping from 4 minutes to 40 minutes over a week. - Log: a structured line like
{"level":"error","stage":"validate","partition":"2026-07-22","message":"schema mismatch: expected DECIMAL got STRING","field":"amount"}, which tells you exactly which field and partition failed, something a metric alone cannot say. - Trace/lineage span: a span or lineage record showing
ingest(kafka:orders) -> transform(spark:orders_etl) -> load(warehouse:fact_orders), with a duration and a partition id attached to each hop, which is what lets you localize a slowdown to one specific hop instead of the whole pipeline.
Worked example
An on-call engineer gets paged because the "orders" pipeline's end-to-end latency crossed an SLO threshold (the metric fired the alert). The METRIC tells them latency is up, but not why. They pull up the trace for a recent run and see the transform stage's span duration jumped from 4 minutes to 38 minutes while ingest and load stages are unchanged, so they know the problem is localized to the transform stage. They then pull the LOGS for that stage's most recent run and find repeated warnings about a join key with unexpectedly high cardinality (a partner table's key distribution changed upstream, causing a skewed shuffle). The trace told them WHERE, the log told them WHY. This progression, metric to trace to log, is the standard on-call investigative workflow: metrics catch it, traces localize it, logs explain it.
Trade-offs and pitfalls
Relying on only one pillar is the common failure: a team that only has metrics can tell something is wrong but not localize or explain it; a team that only has verbose logs without structured, queryable fields drowns in text they cannot correlate at scale. The pitfall on the trace/lineage side specifically is treating it as free: capturing a span or lineage record for every row is prohibitively expensive at high throughput, so most pipelines sample traces (for example, always trace failures, plus a small percentage of successful runs) while keeping metrics at full fidelity, since metrics are cheap to aggregate but traces are not.
Unlock Full Question Bank
Get access to all 19 Data Pipeline Monitoring and Observability interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.