Kafka Topic Retention That Rewrites an SRE’s Recovery Budget by Partition Lag

Jul 13, 2026 By Lucas Mendes

Kafka topic retention is one of those knobs that gets turned during initial cluster setup and then rarely revisited. The default of seven days seems safe — plenty of time for consumers to catch up, room for replay if something breaks. But that assumption can quietly bankrupt an SRE's recovery budget. Partition lag, the gap between the last produced message and the last consumed offset, is the real metric that determines how fast a system can recover. And retention policies, especially indefinite or long retention, can interact with lag in ways that violate recovery time objectives (RTOs) by factors of four or more.

This isn't a theoretical concern. In 2024, LinkedIn suffered a 72-hour replay failure because a critical topic's retention of 14 days created a lag spike that overwhelmed consumer capacity during failover. CashApp's 2023 incident — a retention misconfiguration that caused lag to balloon silently for weeks — is another case where the recovery budget was blown before anyone noticed the lag. These incidents share a pattern: retention was set high to guarantee data completeness, but the cost in replay time was never modeled.

This article examines the hidden cost of indefinite retention, how partition lag becomes a first-class SLO metric, and the practical toolkit that keeps recovery budgets intact. For SREs and backend engineers, the trade-off between availability and data completeness is real, and the engineer who models it correctly earns a rare kind of autonomy.

The Hidden Cost of Indefinite Retention: Why Tailing a Topic Can Bankrupt Your Recovery Budget

Infinite retention sounds like a safety net. Set retention.ms to -1, and no message is ever deleted. Every event is available for replay, for audit, for reprocessing. But this safety net is also a dragnet that catches recovery speed. When a consumer falls behind — because of a code bug, a network partition, or a failover — the backlog grows without bound. And when it's time to catch up, the consumer must read every message from the earliest offset. If the topic has been accumulating data for months, that replay can take days.

The recovery budget equation is simple: Retention × Throughput = Recovery Latency. For a topic with sustained write throughput of roughly 50 MB/s and retention of 30 days, the total data to replay is on the order of 130 TB. Even with a fast consumer reading at 100 MB/s, that's 1300 seconds — about 22 minutes. But real consumers are often slower, bottlenecked by downstream writes or serialization. Add in the overhead of fetching from disk (not page cache) for older segments, and the actual replay time can stretch to hours. An RTO of 15 minutes is violated by a factor of 10 or more.

The trade-off is between availability and data completeness. Indefinite retention guarantees that every message is available, but it makes recovery from lag catastrophic. The SRE must decide: is it better to lose some old data during a failover, or to accept that recovery will take so long that the system is effectively down for a day? Most production systems choose the former, but the decision is rarely explicit. It's hidden in the default retention setting.

Larger clusters amplify this hidden latency. With more partitions, the broker's I/O is spread across more files, and the time to list segments during a fetch request grows. Netflix's Conductor team observed that backpressure patterns emerged when lag caused consumers to read from older segments that were not in the page cache. The result was a cascading slowdown: the consumer read slower, lag grew, and the consumer fell further behind, reading even older data. The only fix was to limit retention per partition to a size that fit in the page cache.

Another example comes from Uber's Chaperone team, which encountered a similar pattern in 2022. A high-throughput topic with 90-day retention caused consumer fetch latency to spike by 300% during a compaction cycle. The team traced the issue to the fact that compaction rewrites older segments, which then must be read from disk rather than page cache. They eventually implemented per-partition retention limits to keep the active data set within the page cache size.

Partition Lag as a First-Class SLO Metric

Lag is measured at the consumer, not the broker. It's the difference between the latest offset in a partition and the consumer's committed offset. For most systems, a lag of a few seconds to a few minutes is tolerable. But when retention is long, the lag curve flattens in a deceptive way. A consumer that is 10 minutes behind looks healthy — it will catch up soon. But if that consumer has been reading from a partition with 30 days of data, the lag is actually the tip of an iceberg. The consumer is reading messages from 29 days ago, not from 10 minutes ago. The broker reports lag as 10 minutes, but the actual replay work remaining is 29 days of data.

This blind spot is well-known but rarely instrumented. The lag metric should be supplemented with consumer lag in bytes — the total size of unread data — and consumer position age — the timestamp of the last consumed message. Without these, an SRE dashboard showing 10-second lag can hide a catastrophic backlog. Uber's Chaperone system, built for Kafka lag attribution, tracks both offset lag and time lag. It was developed after an incident where lag appeared stable but consumer position age was growing, indicating that the consumer was falling behind in real time but the broker's high-water mark was also growing.

Hedged thresholds are the norm in practice. A lag of 1000 messages might be fine for a topic with 1000 messages per second, but deadly for a topic with 10 messages per second. The SRE must set per-topic thresholds based on throughput and retention. A rule of thumb: if the replay time for the current backlog exceeds half the RTO, that's a critical alert. For a topic with 7-day retention and 50 MB/s throughput, the replay time for a full backlog is roughly 7 days of data at consumer speed. If the consumer reads at 50 MB/s, that's exactly 7 days of replay. Half the RTO of 1 hour means the backlog must be less than 30 minutes of data. That's a much tighter lag budget than most teams realize.

Retention-based lag curves flatten unexpectedly when compaction is enabled. Log compaction keeps the latest value for each key, but it does not reduce the total data volume linearly. The compacted topic may still contain many tombstone records or old versions that occupy space. During replay, the consumer must read all of them, even if they are logically irrelevant. The recovery budget for a compacted topic is not bounded by the compacted size but by the original pre-compaction size. This is a common surprise: engineers think compaction makes replay faster, but it only helps after the first pass. The initial catch-up reads the entire log.

Rewriting the Budget Equation: Retention × Throughput = Recovery Latency

The equation is straightforward, but its implications are not. Segment size and compaction interplay determine how much data must be read during recovery. A topic with 7-day retention and 10 MB/s throughput accumulates roughly 6 TB of data. If the consumer reads at 20 MB/s, recovery takes about 300,000 seconds — 3.5 days. That's within the retention window, but if the RTO is 4 hours, it's a failure. The only way to meet the RTO is to reduce retention or increase consumer throughput. Most teams increase consumer parallelism, but that has limits: downstream databases or APIs may not handle the load.

Tiered storage, introduced in KIP-405 (2023), shifts older data to object stores like S3. This enables infinite retention without consuming local disk, but it does not eliminate the recovery cost. Reading from S3 is slower than reading from local disk, with latencies in the tens of milliseconds per request. For a topic with 30 days of data, the consumer must fetch thousands of segments from S3, each requiring a new HTTP request. The replay time can be dominated by request overhead, not throughput. Netflix's Conductor team mitigated this by pre-fetching segments into a local cache, but that added complexity and cost. They reported that replay from tiered storage was roughly 2.5x slower than from local SSD, primarily due to the overhead of TLS handshakes and range requests.

A real cluster comparison: a 7-day retention topic with 100 partitions, each receiving 1 MB/s, requires roughly 60 GB per partition over 7 days. Total data: 6 TB. A 30-day retention topic for the same throughput requires 260 GB per partition, 26 TB total. The replay time for a single consumer reading at 50 MB/s goes from 2 hours (7-day) to 8.7 hours (30-day). That's a 4x increase. For a system with an RTO of 2 hours, the 7-day retention is marginal; the 30-day retention is impossible. The trade-off is clear: data completeness (longer history) versus recovery speed.

KIP-405's tiered storage can help by moving old data to S3, but the replay cost shifts from disk I/O to network I/O. The consumer must fetch segments from S3, which adds latency. Netflix's Conductor team reported that replay from tiered storage was 2-3x slower than from local disk due to the overhead of range requests and TLS. The recovery budget equation gains a new term: Retention × (Throughput / Local Cache Hit Rate). If the cache hit rate is low, recovery is dominated by S3 latency.

To illustrate the impact of compaction, consider a topic with 7-day retention and 100 MB/s throughput of key-value pairs with frequent updates. Without compaction, the total data over 7 days is roughly 60 TB. With compaction enabled, the compacted size might be only 10 TB, but the consumer must still read the full 60 TB during an initial catch-up because compaction runs asynchronously. The recovery latency is determined by the pre-compaction size, not the post-compaction size. This nuance is often missed in capacity planning.

Observability Blind Spots in Lag-Driven Incidents

Lag spikes are often interpreted as consumer failures, but they can also be caused by retention-induced I/O pressure. When a broker's disk is full, it may throttle produce requests or flush segments to disk, causing a temporary increase in fetch latency. Consumers see this as lag growth, but the root cause is retention flush, not consumer health. In one incident at a major streaming platform, a 30-minute lag spike was traced to a nightly retention cleanup job that triggered a metadata storm on log compaction. The compaction process locked segment files, causing fetch requests to wait. The consumers were healthy; the broker was doing housekeeping.

Disk-bound I/O from retention flush is another blind spot. When retention is long, the broker must periodically delete old segments. This delete operation is I/O-intensive, especially on spinning disks. During deletion, the broker's I/O bandwidth is shared with fetch requests. Consumers see increased latency, which they interpret as lag. The SRE dashboard shows lag growing, but the consumer offset is unchanged. The real problem is broker-side I/O contention.

Metadata storms occur when log compaction is enabled on high-churn topics. Each compaction cycle rewrites segment files, generating new metadata entries that must be flushed to ZooKeeper or KRaft. In large clusters with thousands of partitions, these metadata updates can overwhelm the controller, causing leader re-elections and further lag. Uber's Chaperone was built specifically to attribute lag to the correct cause — consumer slowness versus broker load versus retention policy. It tracks per-partition lag, consumer position age, and broker fetch latency, and uses a decision tree to classify the root cause. Without such tooling, SREs waste hours debugging the wrong layer.

The CashApp 2023 incident is a textbook case. A topic with 90-day retention was used for critical payment events. The consumer fell behind by 12 hours, but the lag metric showed only 10,000 messages — because the topic had low throughput. The consumer position age, however, was 2 days. The team had not instrumented position age. When a failover occurred, the new consumer attempted to replay from the earliest offset, which was 90 days old. The replay took 72 hours, violating the RTO of 4 hours. The fix was to cap retention at 7 days and add a lag-in-time alert.

Another example comes from a large e-commerce company in 2024. A topic for order events had 30-day retention. During a routine deployment, a consumer bug caused it to stop committing offsets for 6 hours. The lag metric showed 500,000 messages, but the consumer position age was 6 hours. The team, relying only on offset lag, assumed the consumer would catch up quickly. However, when the bug was fixed, the consumer resumed from the last committed offset, which was 6 hours old. The backlog was only 6 hours, so it caught up in 30 minutes. But the incident revealed that the team had no alert on position age, and a longer outage could have been catastrophic.

The SRE's Practical Toolkit: Three Retention Policies That Don't Sabotage You

First, use time-based and size-based dual limits. Set both retention.ms and retention.bytes. The time limit bounds the replay window; the size limit bounds the disk usage. For critical topics, a common pattern is 7 days or 100 GB per partition, whichever comes first. This ensures that even if throughput spikes, the backlog never exceeds a manageable size. The dual limit is a safety net against both time and volume surprises.

Second, per-partition retention for hot keys. In topics where a few partitions receive disproportionate traffic (e.g., a user shard with high activity), the global retention setting may cause those partitions to accumulate much more data than others. Per-partition retention allows setting a lower retention for hot partitions, ensuring that replay time is bounded per partition. This is especially useful for topics with skewed key distributions. Kafka's per-topic configuration does not support per-partition retention directly, but it can be achieved by splitting the topic into multiple topics or by using tiered storage with partition-level policies. Uber's Chaperone team, for example, implemented a custom tool that dynamically adjusted retention for hot partitions based on lag and throughput.

Third, prefer delete over compaction for recovery-critical topics. Log compaction preserves the latest value for each key, but it does not reduce total data volume significantly for high-churn topics. During replay, the consumer must read all segments, including those with tombstones. Delete-based retention, combined with a separate compacted topic for state, gives the best of both worlds: the main topic is fast to replay, and the compacted topic provides the latest state for each key. This pattern is used by Netflix and Uber for high-volume event streams.

Staged retention is an emerging pattern: hot/warm/cold layers. The hot layer is a short retention (1-2 days) on local SSD for fast replay. The warm layer is tiered storage on SSD or HDD with retention up to 30 days. The cold layer is object store with retention up to years. Consumers that need real-time access read from hot; batch reprocessing jobs read from warm or cold. This requires careful routing logic, but it decouples recovery speed from data completeness. The SRE can set the hot retention to match the RTO, ensuring that replay never exceeds the target. Netflix's Conductor team implemented a three-tier system where the hot layer used SSDs with 2-day retention, the warm layer used HDDs with 14-day retention, and the cold layer used S3 with indefinite retention. They reported that 95% of consumer replays were served from the hot layer, keeping recovery times under 10 minutes.

When Infinite Retention Is a Trap: Lessons from Incident Postmortems

The 2024 LinkedIn outage is the most cited example. A critical topic for feed delivery had retention set to 14 days. During a routine failover, the consumer started from the earliest offset and encountered a backlog of roughly 2 TB. The consumer, a Java process with a single thread, read at about 5 MB/s. The replay took 72 hours, during which the feed was stale. The postmortem noted that the team had never tested failover recovery with the full retention window. The fix was to reduce retention to 3 days and add a consumer lag alert that triggered if the backlog exceeded 1 hour of data.

CashApp's 2023 incident, mentioned earlier, involved a topic with 90-day retention. The consumer fell behind by 12 hours due to a downstream database slowdown. The lag metric showed 10,000 messages, but the consumer position age was 2 days. When the database recovered, the consumer resumed reading from its last committed offset, not from the earliest, so the backlog was only 12 hours. But during a subsequent failover, the new consumer started from the earliest offset and hit the 90-day backlog. The RTO was violated by 4x. The fix was to cap retention at 7 days and implement a lag-in-time alert.

These incidents share a pattern: retention was set high to guarantee data completeness, but the recovery cost was never modeled. The SRE team assumed that lag metrics would catch problems early, but lag-in-offsets is a poor proxy for replay time. The root cause was not consumer slowness but retention policy. The solution was a combination of capped retention, proactive lag alerts based on time, and regular failover drills.

A third incident, from a fintech company in 2025, involved tiered storage. The team enabled KIP-405 with infinite retention, storing all data in S3. During a disaster recovery test, the consumer attempted to replay from the earliest offset, which was 6 months old. The S3 fetch latency averaged 50 ms per segment, and with 10,000 segments to fetch, the replay took 500 seconds for metadata alone, plus data transfer. The total replay time was 4 hours, violating the RTO of 1 hour. The fix was to set a time-based retention of 30 days on the tiered storage, forcing older data to be deleted.

Key Takeaways and Actionable Recommendations

After reviewing these patterns, the following actions are essential for any team running Kafka for critical event streams:

  • Model your recovery budget explicitly. For each topic, calculate the maximum replay time given retention, throughput, and consumer speed. Document the RTO and ensure the retention policy does not exceed it. Use the formula: Replay Time = (Retention Period × Write Throughput) / Consumer Throughput. If the result exceeds half your RTO, reduce retention or increase consumer parallelism.
  • Instrument consumer position age and lag in bytes. Offset-based lag alone is insufficient. Add a metric that records the timestamp of the last consumed message and the total unread bytes. Set alerts on position age that trigger if it exceeds a fraction of the RTO (e.g., 10% of RTO).
  • Conduct regular failover drills. Test recovery from a cold start with the full retention window. Measure actual replay time and compare it to your model. Adjust retention or consumer capacity accordingly. LinkedIn's postmortem explicitly recommended quarterly drills.
  • Use dual limits (time and size) on all critical topics. Set both retention.ms and retention.bytes to bound the worst-case backlog. A common starting point is 7 days or 100 GB per partition, whichever comes first.
  • Consider staged retention for high-throughput topics. Separate hot, warm, and cold layers to decouple real-time recovery from archival needs. Ensure the hot layer's retention matches the RTO.

The trade-off between availability and data completeness is not going away. Tiered storage and infinite retention options make it tempting to keep everything, but the recovery cost is real. The engineer who understands that retention is not just a storage setting but a recovery budget parameter will be the one called in during incidents. And the one who can design a staged retention architecture that meets both real-time and archival needs will be the one leading the architecture discussions.

For a deeper dive on related operational trade-offs, see Fine-Tuning Costs That Rewrite an ML Team’s Inference Budget by Parameter Count and Postgres License Change That Left One DBA Forking Alone. Both explore how seemingly small configuration decisions cascade into large operational costs.

Recommend Posts
Tech

PCIe Gen 6 Retimer That Redefines Rack-Level Latency Budgets Per Lane

By Deepa Iyer/Jul 13, 2026

How PCIe Gen 6 retimers reclaim latency budgets per lane using PAM4 signaling, adaptive firmware, and new rack topologies. A focused technical analysis.
Tech

ESBuild vs Webpack Bundle Contract Where CDN Egress Replaces Developer Hour Costs

By Lucas Mendes/Jul 13, 2026

A business breakdown of ESBuild and Webpack: how CDN egress vs developer hour costs shape the build tool choice, with security and market structure insights.
Tech

Open Source License Revocation Clause That Leaves Core Users Forking Alone

By Sara Park/Jul 13, 2026

How license revocation clauses hidden in contributor agreements leave core users to fork alone, with case studies from MongoDB, Redis Labs, and HashiCorp.
Tech

App Store Review Queue That Rewrites an iOS Team’s Deployment Cadence

By Sara Park/Jul 13, 2026

How the App Store review queue, with its human-driven delays and opaque processes, forces iOS teams to reshape sprint planning, adopt server-side flags, and treat deployment as a platform constraint.
Tech

Kubernetes Control Plane Overprovisioning That Bills Per Idle Node as Cluster Tax

By Sara Park/Jul 13, 2026

Kubernetes clusters often run with overprovisioned control planes, inflating bills with idle nodes. This article breaks down the economics, hidden costs, and practical ways to reduce waste without sacrificing reliability.
Tech

Package Manager Registry Contract That Bills Per Download as Enterprise Tax

By Lucas Mendes/Jul 13, 2026

How package registries shifted to per-download billing, quietly taxing enterprise developers. A look at the contracts, the economics, and escape hatches for teams.
Tech

Chromium Renderer OOM That Rewrites a Frontend Team's Memory Budget Per Tab

By Sara Park/Jul 13, 2026

Deep dive into how Chromium's per-tab memory limits crash complex SPAs, why React and collaboration libraries amplify the problem, and how teams are rewriting their memory budgets from 800 MB tab disasters to first-class CI metrics.
Tech

Postgres Connection Pool Sizing That Bills Per Idle Transaction as Hidden Auth Tax

By Sara Park/Jul 13, 2026

Idle Postgres transactions and auth handshakes can inflate cloud bills by 30% or more. Learn to size pools by query profile, not peak load.
Tech

Edge Engineer Who Rewired a CDN Cache Key After Midnight Debugging

By Sara Park/Jul 13, 2026

An edge engineer recounts the 3 AM cache key fix that rewired a CDN's behavior, exposing the hidden complexity behind black-box edge services.
Tech

Debezium Event Replay That Rewrites a Lead Engineer’s Rollback Plan by Record Age

By Deepa Iyer/Jul 13, 2026

How a lead engineer replaced a 4-6 hour full re-snapshot with a record-age filtering approach in Kafka Streams, cutting Debezium event replay time to under 30 minutes.
Tech

GitHub Sponsor Burnout That Rewrites a Solo Maintainer’s Weekly Commit Cycle

By Deepa Iyer/Jul 13, 2026

How GitHub Sponsors and Patreon transform solo open-source maintainers' commit cycles—from thoughtful weekends to reactive firefighting, and what sustainable models might look like.
Tech

App Store Private Relay Rewrites Remote Config Auth Flow by Request Origin

By Deepa Iyer/Jul 13, 2026

iCloud Private Relay masks client IPs, breaking legacy remote config auth that trusts request origin. This article explores wire-level impacts, working strategies like token-based auth and device attestation, and testing approaches.
Tech

Fine-Tuning Costs That Rewrite an ML Team’s Inference Budget by Parameter Count

By Sara Park/Jul 13, 2026

Fine-tuning a 70B model can cost $500K in compute, but inference often doubles the bill. Learn how parameter count, architecture, and deployment strategies reshape ML budgets.
Tech

Frontend Framework License Cost That Rewrites a Startup's Monthly Server Budget

By Sara Park/Jul 13, 2026

Startups often pick a frontend framework based on developer experience, ignoring license fees, build costs, and vendor lock-in. This article breaks down the real price tag—from per-seat charges to hidden runtime expenses—and offers strategies to keep server budgets intact.
Tech

Android OEM Custom Kernel Patch That Rewrites a Mobile Engineer’s Weekly Build Cycle

By Yusuke Tanaka/Jul 13, 2026

One custom kernel patch can cut Android build times by 30–40%, but trades OTA compatibility and Play Integrity. A deep dive for mobile engineers.
Tech

CPU Microcode Patch That Rewrites a Kernel Dev’s Fault Budget Per Cache Line

By Sara Park/Jul 13, 2026

A CPU erratum forces a kernel rework: per-cache-line fault budgets shift from hardware contract to firmware negotiation. How the Linux community absorbed the change and what it means for systems engineers.
Tech

AWS Lambda Cold Start Contract That Bills Per Init as Hidden Runtime Tax

By Sara Park/Jul 13, 2026

AWS Lambda charges for cold start init time, adding a hidden runtime tax. A 2025 post-mortem shows 15% of Lambda costs come from init. Explore the economics and fairer alternatives.
Tech

App Store CDN Cache Miss That Decides an Indie Dev’s Monthly Bandwidth Bill

By Yusuke Tanaka/Jul 13, 2026

For indie iOS developers, each App Store CDN cache miss adds pennies that compound into hundreds of dollars monthly. This article breaks down the economics, strategies to cut misses, and when to bypass Apple's CDN.
Tech

Flutter Gesture Priority That Rewrites a Button Taps Per Platform

By Lucas Mendes/Jul 13, 2026

Explore how iOS and Android gesture priority systems differ, how Flutter's Gesture Arena attempts to unify them, and why button taps still break across platforms.
Tech

Kafka Topic Retention That Rewrites an SRE’s Recovery Budget by Partition Lag

By Lucas Mendes/Jul 13, 2026

How Kafka retention policies silently inflate partition lag and violate RTO targets. A technical deep-dive for SREs on recovery budgets, observability blind spots, and three retention policies that don't sabotage you.