Not crashing. Not throwing errors. Just quietly serving you stale, skewed, or subtly wrong data while every health check stays green.
This is the failure mode nobody talks about enough. Engineers are trained to respond to alerts: CPU spikes, pod restarts, consumer group rebalances. Those are loud. You fix them and move on. The harder problem is when a pipeline appears healthy but the data coming out of it has drifted away from reality. Downstream teams notice first, usually by comparing numbers in a report. By then, the damage is already baked into dashboards, models, or decisions.
Here is what actually causes this, and what it takes to catch it before users do.
The Quiet Culprits
Most silent pipeline failures trace back to three things: hidden lag accumulation, slow or incomplete checkpoints, and partition-level IO errors that never surface cleanly.
Consumer lag is the classic one. You track total lag, it looks fine, but one partition is stuck. The average hides it. You need per-partition lag visibility, not aggregate.
Checkpoint latency is less obvious. In Flink, if your checkpoint interval is 30 seconds but checkpoints are taking 28 seconds to complete, you are not getting the durability or recovery guarantees you think you are. The job keeps running. Nothing alerts. But if it fails, your recovery point is much older than expected.
Partition IO errors are the sneakiest. Kafka brokers can return partial fetch responses or throttle specific partitions without the consumer throwing an exception that logs clearly. The consumer just slows down on that partition, or skips ahead depending on your error handling config. You lose records or process them out of order, and the job reports no errors.
Metrics Are Not Enough on Their Own
Most teams instrument Kafka and Flink at the surface level: consumer group lag, throughput, JVM heap. That is a start, but it is not observability.
Real observability means metrics, logs, and traces working together. Metrics tell you something changed. Logs tell you what was happening in context. Traces let you follow a specific record through the pipeline to understand exactly where it slowed down or disappeared.
For Flink specifically, the metrics you actually need go deeper than defaults:
# Flink metrics worth tracking explicitly
numberOfFailedCheckpoints
lastCheckpointDuration
lastCheckpointSize
currentInputWatermark
numRecordsInPerSecond (per operator, not just source)
numLateRecordsDropped
numLateRecordsDropped is one that teams frequently ignore until it causes a problem. If your watermark is too aggressive for real-world event time variance, you will silently drop late records. The job is "working." The aggregations are just wrong.
On the Kafka side, pay attention to records-lag-max per partition and per consumer instance, not just the group-level rollup. Also watch fetch-throttle-time-avg on producers and consumers. Throttling is a common cause of unexpected lag that does not show up as an obvious error.
Connecting Metrics to Meaning
Raw metrics are only useful if they are connected to outcomes. That means defining SLOs for your pipeline, not just for your API.
For a streaming pipeline, useful SLOs might look like:
- End-to-end latency from event time to processed output stays under 5 seconds for 99% of records
- Consumer lag across all partitions stays below 10,000 records
- Checkpoint completion rate stays above 99.5% over any 1-hour window
Without agreed-upon thresholds, every team has a different opinion about what "degraded" means. With them, you can build alerts that fire before users notice something is wrong, not after.
SLOs also change how you write runbooks. Instead of "alert fires, investigate," you get a structured escalation path: lag crosses threshold, check per-partition breakdown, check broker throttle metrics, check checkpoint latency, compare watermark advance rate against wall clock. You are not starting from scratch each time.
Closing the Loop with Reconciliation
Even with good instrumentation, you will occasionally miss something. That is fine as long as you have a reconciliation layer.
Reconciliation means periodically comparing what your pipeline processed against a source of truth. This could be comparing aggregated counts in your stream output against counts in the source system, or validating that event totals for a given time window are within an acceptable margin. It does not need to be continuous; even a daily batch reconciliation job catches drift that real-time monitoring misses.
The output of reconciliation feeds back into your alerting. If the pipeline metrics look healthy but reconciliation shows a 3% gap in event counts for the last hour, you have a real signal that something upstream went wrong, probably silently.
The Concrete Takeaway
Your pipeline is not observable just because Prometheus is scraping it. Observability means you can look at a time window and answer: did the right records arrive, were they processed correctly, and did the output reflect reality? If you cannot answer all three from your current tooling, you have gaps. Start with per-partition lag, checkpoint duration, and late record drop rates. Those three metrics alone will surface the majority of silent failures before they become data disagreements nobody can explain.
Top comments (0)