<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Pulsar Operations Guides on Netdata</title><link>https://www.netdata.cloud/guides/apache-pulsar/</link><description>Recent content in Apache Pulsar Operations Guides on Netdata</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://www.netdata.cloud/guides/apache-pulsar/index.xml" rel="self" type="application/rss+xml"/><item><title>Apache Pulsar abandoned subscriptions: cursor leaks that pin storage forever</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-subscription-cursor-leak/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-subscription-cursor-leak/</guid><description>&lt;p>Bookie disk usage climbs steadily across the cluster, but publish rates are flat and there is no traffic spike. Per-subscription backlogs look fine for the subscriptions you know about. When you try to delete an old topic to reclaim space, the operation fails with a message about active subscriptions. The topic has not had a consumer in weeks.&lt;/p>
&lt;p>This is the signature of a silent subscription cursor leak. Applications create dynamically-named durable subscriptions and then disconnect without unsubscribing. Each abandoned subscription leaves behind a cursor pinned at its last acknowledged position. Pulsar cannot delete any message after that cursor&amp;rsquo;s position until the subscription acknowledges past it, which never happens because no consumer is connected. Storage grows monotonically, and the growth is invisible in per-subscription backlog dashboards because those dashboards only track subscriptions the team knows about.&lt;/p></description></item><item><title>Apache Pulsar active connections climbing: connection leaks and file descriptor exhaustion</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-active-connections-climbing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-active-connections-climbing/</guid><description>&lt;p>&lt;code>pulsar_active_connections&lt;/code> has been drifting upward for weeks. Not spiking, not crashing, just rising a few connections a day. Then one morning new producers start failing to connect, or the broker dies with &lt;code>OutOfDirectMemoryError&lt;/code>, and the postmortem shows the leak was visible the whole time.&lt;/p>
&lt;p>Every TCP connection costs the broker one file descriptor and a slice of Netty direct memory. Connections that are established but never closed accumulate silently until one of those two resources hits its ceiling, at which point the failure is abrupt: refused connections or a crash, with no graceful degradation in between.&lt;/p></description></item><item><title>Apache Pulsar authentication failures: expired tokens, wrong credentials, and brute force</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-authentication-failures/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-authentication-failures/</guid><description>&lt;p>Authentication failures in Apache Pulsar surface through &lt;code>pulsar_authentication_failures_total&lt;/code> and &lt;code>AuthenticationException&lt;/code> entries in broker logs. In a stable environment, this counter sits near zero. When it spikes, the temporal pattern matters more than the absolute volume: a single burst from a known client after a credential rotation is normal; sporadic low-rate failures from production IPs point to misconfiguration; a sustained flood from unknown sources signals brute force or credential compromise.&lt;/p>
&lt;p>Each failure closes the TCP connection. The client reconnects, authenticates again, and either succeeds or fails. This loop consumes file descriptors, Netty direct memory buffers, and CPU on both sides. Brokers check auth data expiry every &lt;code>authenticationRefreshCheckSeconds&lt;/code> (default 60 seconds). If the client supports auth refreshing, the broker sends a &lt;code>CommandAuthChallenge&lt;/code>. If not, and the credential is expired, the broker disconnects. An expired token does not cause a single failure; it causes a continuous reconnect storm until the credential is refreshed.&lt;/p></description></item><item><title>Apache Pulsar authorization failures: the AuthorizationException only the logs will show</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-authorization-failures/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-authorization-failures/</guid><description>&lt;p>A producer or consumer authenticates successfully but cannot produce, consume, or manage a topic. The client receives an &lt;code>AuthorizationException&lt;/code> or a generic permission error. Your dashboard shows nothing unusual because Pulsar exposes no authorization failure counter in its Prometheus metrics. The only evidence is in broker logs.&lt;/p>
&lt;p>This is a common blind spot. Authentication failures have a dedicated metric (&lt;code>pulsar_authentication_failures_total&lt;/code>), but authorization failures do not. A client with valid credentials but missing role permissions fails silently from a metrics perspective. You find out when an application team reports errors or when someone greps the broker log.&lt;/p></description></item><item><title>Apache Pulsar AutoRecovery stalled: under-replicated ledgers that never heal</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-autorecovery-stalled/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-autorecovery-stalled/</guid><description>&lt;p>Under-replicated ledgers are the durability canary for your Pulsar cluster. When a bookie fails, ledger fragments on it lose redundancy and the under-replicated count spikes. AutoRecovery is supposed to drive that count back to zero. When the count stays flat or grows instead of trending down, recovery has stalled.&lt;/p>
&lt;p>A stall is not slow recovery. Slow recovery means the count is decreasing, just not fast enough. A stall means it is frozen or climbing. The diagnostic paths and fixes are completely different.&lt;/p></description></item><item><title>Apache Pulsar backlog age vs size: the latency depth alone cannot show</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-backlog-age-vs-size/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-backlog-age-vs-size/</guid><description>&lt;p>Backlog size tells you how much data is waiting. Backlog age tells you how long it has been waiting. Monitoring only one leaves you blind to entire classes of consumer health failures.&lt;/p>
&lt;p>A stable backlog of 1,000 entries is unremarkable if those entries are 5 seconds old. The same 1,000 entries from 5 hours ago means a cursor is stuck, a consumer is down, or an application has silently stopped acknowledging. Size alone cannot distinguish these scenarios. Age can.&lt;/p></description></item><item><title>Apache Pulsar backlog quota exceeded: producers held or rejected when consumers stall</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-backlog-quota-exceeded/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-backlog-quota-exceeded/</guid><description>&lt;p>Producers are timing out or receiving errors, but the root cause is not on the producer side. A subscription backlog has crossed a configured quota, and the backlog policy has kicked in. Depending on the policy, producers are now blocked, rejected, or the oldest messages are being silently deleted. The symptom is a producer outage or data loss, but the root cause is a consumer that stopped keeping up.&lt;/p>
&lt;p>The blast radius depends entirely on a namespace-level policy that many teams set once and forget. The same growing backlog can produce three different outcomes: producer timeouts, producer exceptions, or silent message eviction. Knowing which policy is active on the affected namespace is the first thing you need before touching anything.&lt;/p></description></item><item><title>Apache Pulsar bookie add-entry queue not draining: writes arriving faster than the disk can commit</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-add-entry-in-progress-growing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-add-entry-in-progress-growing/</guid><description>&lt;p>When &lt;code>bookkeeper_server_ADD_ENTRY_IN_PROGRESS&lt;/code> grows and does not drain to near-zero within seconds of a traffic burst, the bookie write path is saturated. Writes are arriving faster than the journal disk can fsync them, or the write thread is blocked by GC. Left unaddressed, this causes broker-side timeouts, producer failures, and throughput collapse.&lt;/p>
&lt;p>This metric is a gauge, not a counter. Absolute value matters less than trend. Spikes during traffic bursts are normal; sustained positive growth is not. The queue fills and stays filled because the bookie cannot commit entries as fast as they arrive. By the time broker publish latency spikes, the bookie has already been saturated for seconds or minutes.&lt;/p></description></item><item><title>Apache Pulsar bookie disk filling: runway to read-only and how to reclaim space</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-disk-filling/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-disk-filling/</guid><description>&lt;p>Bookie disk usage decides whether your cluster can accept writes. When a bookie&amp;rsquo;s ledger directories fill past the configured threshold (default 95%), the bookie transitions to read-only mode and stops accepting new entries. If enough bookies go read-only, the write quorum for affected ledgers cannot be satisfied, and producers start seeing errors.&lt;/p>
&lt;p>BookKeeper needs disk headroom to compact entry logs and reclaim space from deleted ledgers. &lt;!-- TODO: verify whether major compaction is actually suspended at diskUsageWarnThreshold (default 0.90) by default, or whether suspension only occurs at diskUsageThreshold (default 0.95) when isForceGCAllowWhenNoSpace=false --> At 95% (&lt;code>diskUsageThreshold&lt;/code>), the bookie goes read-only and suspends GC entirely. At that point, shortening retention or deleting topics will not reclaim space because the compaction that rewrites entry logs is itself suspended.&lt;/p></description></item><item><title>Apache Pulsar bookie failure cascade: recovery I/O that topples surviving bookies</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-failure-cascade/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-failure-cascade/</guid><description>&lt;p>Bookies are failing one at a time. Each time one drops, AutoRecovery starts replicating its ledgers to the survivors. The recovery reads and writes add I/O load to bookies already handling foreground traffic. Journal sync latency climbs, publish latency follows, then the next bookie starts timing out. It fails, and the cycle accelerates.&lt;/p>
&lt;p>This is the bookie failure cascade. The root cause is not the initial bookie failure; it is the recovery mechanism competing with production traffic on bookies near their I/O ceiling. With default settings, AutoRecovery triggers immediately (&lt;code>lostBookieRecoveryDelay=0&lt;/code>) and reads entries in batches of 100 (&lt;code>rereplicationEntryBatchSize=100&lt;/code>) from surviving bookies, then writes them locally.&lt;/p></description></item><item><title>Apache Pulsar bookie journal and ledger storage on one disk: the #1 architecture mistake</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-journal-storage-shared-disk/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-journal-storage-shared-disk/</guid><description>&lt;p>Every BookKeeper bookie has two storage responsibilities with fundamentally different I/O profiles. The journal is a write-ahead log: sequential writes, fsync&amp;rsquo;d per entry or batch, on the critical path of every producer acknowledgment. Entry logs and ledger indexes (managed by DbLedgerStorage, the default storage backend) store message payloads and serve random reads whenever consumers catch up on historical data.&lt;/p>
&lt;p>These workloads are incompatible on a single physical disk. When they share a device, consumer catch-up reads and BookKeeper garbage collection interrupt the journal&amp;rsquo;s sequential write pattern. Fsync latency spikes. Every producer writing through that bookie stalls. Because Pulsar&amp;rsquo;s write quorum requires acknowledgments from multiple bookies, one saturated bookie can bottleneck the entire topic.&lt;/p></description></item><item><title>Apache Pulsar bookie read latency high: catch-up reads competing with the write path</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-read-latency-high/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-read-latency-high/</guid><description>&lt;p>When &lt;code>bookkeeper_server_READ_ENTRY_REQUEST&lt;/code> or &lt;code>bookie_BOOKIE_READ_ENTRY&lt;/code> P99 latency rises well above baseline, the cause is usually not an isolated disk problem. It is consumers draining backlog (catch-up reads) generating a high volume of cold reads that bypass both the broker&amp;rsquo;s managed ledger cache and the bookie&amp;rsquo;s read cache, hitting ledger storage disks directly. If journal and ledger directories share a physical device, those read I/O operations compete with journal fsyncs and the write path degrades too.&lt;/p></description></item><item><title>Apache Pulsar bookie read-only: disk full and bookie_SERVER_STATUS at zero</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-read-only/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bookie-read-only/</guid><description>&lt;p>&lt;code>bookie_SERVER_STATUS == 0&lt;/code> means the bookie has transitioned to read-only mode and is no longer accepting writes. In most cases this is a self-protective response to ledger disk usage crossing &lt;code>diskUsageThreshold&lt;/code> (default 0.95). The bookie keeps serving reads, but any topic whose ensemble includes this bookie may fail to meet its write quorum, causing broker-side write errors and producer timeouts.&lt;/p>
&lt;p>The real danger is the cascade. If enough bookies in the ensemble go read-only simultaneously, the write quorum (Qa) cannot be satisfied for new ledger creation, and all writes to affected topics fail. This can look like a cluster-wide outage even though the root cause is disk exhaustion on a few nodes.&lt;/p></description></item><item><title>Apache Pulsar broker down: telling a dead broker from a fenced one</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-down/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-down/</guid><description>&lt;p>Your alerting fired: the broker&amp;rsquo;s HTTP admin endpoint on :8080 has been unreachable for more than two minutes, and the broker was previously running, so this is not a fresh deploy or a rolling restart. Pager says &amp;ldquo;broker down.&amp;rdquo; That phrase hides two very different incidents.&lt;/p>
&lt;p>The first is a hard death: the JVM crashed, got OOM-killed, or the host failed. The process is gone and the OS will tell you so in seconds. The second is a fenced broker: the process is alive, maybe even accepting TCP connections, but it has lost its ZooKeeper session and with it ownership of every namespace bundle it served. From the client&amp;rsquo;s perspective the broker is down. From the process table&amp;rsquo;s perspective it is fine. The fix, the blast radius, and the forensics are completely different for each.&lt;/p></description></item><item><title>Apache Pulsar broker GC death spiral: heap pressure, stop-the-world pauses, and lost topic ownership</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-gc-death-spiral/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-gc-death-spiral/</guid><description>&lt;p>A broker is losing topic ownership, recovering, and losing it again. Clients reconnect in bursts. Lookup failures climb. Publish latency is erratic even though traffic is flat and CPU looks busy for no obvious reason. The broker process never actually dies, which is why restarts and instance health checks keep &amp;ldquo;fixing&amp;rdquo; it for ten minutes at a time.&lt;/p>
&lt;p>This is the GC death spiral: the broker JVM is under memory pressure, full GC pauses stop the world long enough to miss ZooKeeper heartbeats, the session expires, the broker is fenced and loses its bundles, and the resulting client reconnect and metadata churn allocates even more memory, which triggers more GC. The loop feeds itself. The signature is oscillation, not a clean failure.&lt;/p></description></item><item><title>Apache Pulsar broker hotspot: one broker owning far more topics than the rest</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-hotspot-topic-count/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-hotspot-topic-count/</guid><description>&lt;p>You have a multi-broker Pulsar cluster where one broker carries a disproportionate share of topic ownership. Cluster-wide averages look acceptable, but that single broker shows elevated GC pressure, higher publish latency, more active connections, or a larger heap footprint than its peers. The imbalance may have built for hours or days without triggering an alert because aggregate metrics hid it.&lt;/p>
&lt;p>In Pulsar, topics are not assigned to brokers individually. They are assigned at the namespace bundle level. Each namespace is sharded into bundles (hash-range slices of the topic namespace), and each bundle is owned by exactly one broker at a time. A topic lands in a bundle by hashing its name. When a bundle accumulates too many topics, too much throughput, or too many sessions, the load balancer should split it and redistribute ownership. When this does not happen, one broker ends up owning a hot bundle and becomes a bottleneck.&lt;/p></description></item><item><title>Apache Pulsar broker lookup failures: new clients cannot find their topic</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-lookup-failures/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-broker-lookup-failures/</guid><description>&lt;p>Your dashboards look fine. Messages are flowing, publish latency is normal, consumers are draining backlog. But the new service you just deployed cannot start: its producer hangs or fails trying to connect to its topic. Restarting it does not help. Existing clients are unaffected.&lt;/p>
&lt;p>This is the classic Pulsar grey failure. Topic lookup is how every producer and consumer discovers which broker owns its topic. Existing connections keep working because they already resolved ownership. New traffic fails when lookups cannot resolve. Process health checks, message rates, and bookie metrics can all look healthy until a deploy, restart, scale event, or broker bounce forces mass re-lookup.&lt;/p></description></item><item><title>Apache Pulsar bundle unload thrashing: the load balancer that never converges</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bundle-unload-thrashing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-bundle-unload-thrashing/</guid><description>&lt;p>The primary signal is &lt;code>pulsar_lb_unload_bundle_total&lt;/code>, a counter exposed on the broker Prometheus metrics endpoint. In steady state it barely moves: bundle ownership changes are rare, ideally less than once per hour. When this counter climbs past one unload per minute and there is no rolling upgrade, no broker restart, and no planned maintenance, the load balancer is thrashing.&lt;/p>
&lt;p>Each unload transfers a namespace bundle (a hash-range slice of topics) from one broker to another. Each transfer drops the TCP connections for every producer and consumer on those topics. Clients reconnect automatically, but reconnection generates metadata operations against ZooKeeper, new ledger creation in BookKeeper, and a latency blip measured in tens of milliseconds per affected topic. When unloads happen every few seconds, those blips stack into sustained degradation: elevated publish latency, client reconnection storms, and metadata store pressure that feeds back into more instability.&lt;/p></description></item><item><title>Apache Pulsar consumers connected but not acknowledging: the silent consumer stall</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-consumer-stalled-no-acks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-consumer-stalled-no-acks/</guid><description>&lt;p>Your Pulsar cluster looks healthy. Brokers are up, bookies are writable, producers are publishing at normal rates. But for one topic or subscription, &lt;code>pulsar_rate_out&lt;/code> has gone flat. Messages are flowing in but nothing is coming out. The backlog is climbing. Consumers show as connected, but the acknowledgment rate is zero.&lt;/p>
&lt;p>No error surfaces in broker logs. The broker serves connections and bookie writes are fast. The problem lives in the consumer application or in the interaction between consumer configuration and broker dispatch policy.&lt;/p></description></item><item><title>Apache Pulsar dead letter queue filling: maxRedeliveryCount and the DLQ topic</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-dead-letter-queue-growing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-dead-letter-queue-growing/</guid><description>&lt;p>The dead letter topic is where Pulsar parks messages that exhausted their retry budget. When you set &lt;code>DeadLetterPolicy.builder().maxRedeliverCount(N).build()&lt;/code> on a Shared or Key_Shared subscription, the broker stops redelivering a message after N failed attempts, routes it to &lt;code>{topic}-{subscription}-DLQ&lt;/code>, and auto-acks it in the origin subscription so backlog clears.&lt;/p>
&lt;p>A growing DLQ arrival rate is a ledger of application processing failures. A few poison messages parked for inspection is the DLQ working as designed. A steady stream of thousands of messages per second is a systemic failure. Unmonitored, the DLQ topic itself becomes the incident: messages accumulate, storage grows, and nobody notices until disk fills or a downstream team asks why their data is missing.&lt;/p></description></item><item><title>Apache Pulsar ensemble, write quorum, and ack quorum: what E, Qw, and Qa actually guarantee</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-write-ack-quorum-explained/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-write-ack-quorum-explained/</guid><description>&lt;p>Every persistent message in Apache Pulsar passes through BookKeeper&amp;rsquo;s quorum system, governed by three parameters: ensemble size (E), write quorum (Qw), and ack quorum (Qa). Configured per namespace and inherited by topics, they determine how many bookies receive each entry, how many must confirm a durable write before the producer is acknowledged, and how the cluster behaves when bookies fail, slow down, or are taken offline.&lt;/p>
&lt;p>The nuance is in what each parameter does not guarantee. Write quorum is not a durability floor for acknowledged entries. Ack quorum is not the number of copies that will exist after the write completes. Ensemble size constrains ledger creation in ways that surprise teams during maintenance windows: you can have plenty of bookies but still be unable to create new ledgers.&lt;/p></description></item><item><title>Apache Pulsar entry log GC falling behind: reclaimed space that never comes back</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-entry-log-gc-lagging/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-entry-log-gc-lagging/</guid><description>&lt;p>A bookie&amp;rsquo;s ledger disk is filling. Retention policies have deleted ledgers, TTL has expired messages, and cursors have advanced past the data. By every logical measure, the space should be free. But disk usage keeps climbing, and the bookie is heading toward read-only.&lt;/p>
&lt;p>BookKeeper does not store each ledger in a separate file. Entry logs are large append-only files that interleave entries from many ledgers, written sequentially as they arrive. When a ledger is deleted, its entries remain physically embedded in the entry log alongside data from other ledgers that are still active. The only way to reclaim that space is compaction: the garbage collector reads the live entries from an old entry log, writes them into a new file, then deletes the old one. If compaction stalls, throttles to a crawl, or never triggers, dead data accumulates indefinitely.&lt;/p></description></item><item><title>Apache Pulsar geo-replication backlog: replication lag and your real RPO window</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-geo-replication-backlog/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-geo-replication-backlog/</guid><description>&lt;p>Geo-replication in Pulsar is asynchronous by design. Messages are persisted locally and acknowledged to producers before they reach the remote cluster. Every message sitting in the replication backlog is a message that would be lost if you failed over right now. The replication backlog is your recovery point objective (RPO) window, measured in real time.&lt;/p>
&lt;p>The common operational mistake is checking whether replication is &amp;ldquo;working&amp;rdquo; (connected, producing to the remote cluster) without checking how far behind it is. A replicator can be fully connected and actively shipping messages while being hours behind. The dashboard shows green. The failover plan assumes near-zero data loss. The reality is data loss measured in hours.&lt;/p></description></item><item><title>Apache Pulsar geo-replication disconnected: a remote cluster that stopped receiving</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-geo-replication-disconnected/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-geo-replication-disconnected/</guid><description>&lt;p>The symptom is unmistakable: &lt;code>pulsar_replication_disconnected_count&lt;/code> is non-zero for all replicators to a specific remote cluster, &lt;code>pulsar_replication_connected_count&lt;/code> has dropped to zero, and &lt;code>pulsar_replication_backlog&lt;/code> is growing at the rate of local publish throughput. The remote cluster has stopped receiving messages. Local producers and consumers continue working normally because Pulsar geo-replication is asynchronous. Messages persist locally first, then replicate. The damage is silent and cumulative.&lt;/p>
&lt;p>Every unreplicated message widens the recovery point objective (RPO) gap. If you fail over to the remote cluster right now, those messages are gone. The backlog is your exposure, measured in entries and in seconds via &lt;code>pulsar_replication_delay_in_seconds&lt;/code>.&lt;/p></description></item><item><title>Apache Pulsar journal force write queue growing: the earliest write-saturation signal</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-journal-force-write-queue-growing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-journal-force-write-queue-growing/</guid><description>&lt;p>&lt;code>bookie_journal_JOURNAL_FORCE_WRITE_QUEUE_SIZE&lt;/code> measures the depth of pending fsync batches inside a BookKeeper bookie&amp;rsquo;s journal write path. In a healthy system this gauge sits at or near zero, draining between write groups. When it sustains a non-zero depth, the journal disk cannot commit writes durably fast enough to keep up with incoming traffic.&lt;/p>
&lt;p>This signal rises before &lt;code>bookie_journal_JOURNAL_SYNC&lt;/code> latency spikes and before &lt;code>bookkeeper_server_ADD_ENTRY_IN_PROGRESS&lt;/code> grows. If you are not watching the force write queue, your first indication of write-path saturation will be broker publish latency degradation or producer timeouts, which means you are already two or three steps into the cascade.&lt;/p></description></item><item><title>Apache Pulsar ledger rollover latency spikes: the periodic blip that is usually normal</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-ledger-rollover-latency/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-ledger-rollover-latency/</guid><description>&lt;p>You see a periodic sub-second spike in publish latency on your Pulsar brokers. It happens at regular intervals, lasts a fraction of a second, and then latency returns to baseline. No errors, no bookie failures, no GC pauses. The spike is visible in P99 publish latency but barely touches P50. It correlates across topics on the same broker but not across the entire cluster.&lt;/p>
&lt;p>This is almost certainly a ledger rollover. When a managed ledger fills its current BookKeeper ledger (by entry count, size, or time), the broker seals that ledger and creates a new one. The creation step involves metadata store writes (ZooKeeper in most Pulsar 3.x deployments, Oxia in newer ones), which add latency to the write path for the duration of the operation. The result is a brief publish latency blip, typically under 100ms, that repeats at intervals determined by your managed ledger configuration.&lt;/p></description></item><item><title>Apache Pulsar LedgerFencedException: split ownership and fencing loops</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-ledger-fenced-exception/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-ledger-fenced-exception/</guid><description>&lt;p>LedgerFencedException appears when a broker tries to write to a BookKeeper ledger that another broker has already fenced. The error string is explicit: &amp;ldquo;Ledger has been fenced off. Some other client must have opened it to read.&amp;rdquo;&lt;/p>
&lt;p>In most production environments, this is expected noise during planned failover. It becomes a problem when fencing occurs without a corresponding bundle transfer, or when two brokers fence each other&amp;rsquo;s ledgers in a loop.&lt;/p></description></item><item><title>Apache Pulsar managed ledger cache miss rate high: consumer reads falling through to bookies</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-managed-ledger-cache-misses/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-managed-ledger-cache-misses/</guid><description>&lt;p>The managed ledger cache is the broker&amp;rsquo;s off-heap buffer of recently written entries. Connected consumers read from it at sub-millisecond latency. On a cache miss, the broker issues a read to the BookKeeper bookie ensemble holding that ledger segment, which adds disk I/O, network bandwidth consumption between broker and bookie, and consumer read latency.&lt;/p>
&lt;p>A sustained cache miss rate above 20% after warmup means the broker is serving a meaningful fraction of consumer reads from storage instead of memory. The extra bookie read traffic loads storage disks that also serve journal writes. If bookie read latency rises enough, publish latency follows. This is the leading edge of the Backlog Cascade: consumer reads and producer writes converging on the same physical disks.&lt;/p></description></item><item><title>Apache Pulsar message redelivery storm: poison messages and consumers making no progress</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-redelivery-storm/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-redelivery-storm/</guid><description>&lt;p>Subscription redelivery rate is climbing. Consumers are connected, the dispatch rate (&lt;code>pulsar_rate_out&lt;/code>) looks healthy, but messages keep cycling back without being acknowledged. The backlog may even appear stable or zero, because &lt;code>pulsar_subscription_back_log&lt;/code> measures messages not yet dispatched, not messages dispatched but unacked. The definitive signal is &lt;code>pulsar_subscription_msg_rate_redeliver&lt;/code> trending upward relative to dispatch. When redelivery exceeds 10% of your dispatch rate, something is wrong. When it approaches 100%, you have zero forward progress: the broker burns memory and network re-sending messages that will never succeed.&lt;/p></description></item><item><title>Apache Pulsar messages expiring before consumers read them: TTL and silent loss</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-message-ttl-expiry/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-message-ttl-expiry/</guid><description>&lt;p>When &lt;code>pulsar_subscription_msg_rate_expired&lt;/code> is non-zero on a topic where every message matters, messages are being silently deleted before consumers can read them. No errors appear in consumer logs. No producer failures occur. The broker&amp;rsquo;s TTL mechanism acknowledges messages on behalf of the subscription without ever delivering them to the consumer application.&lt;/p>
&lt;p>The backlog can hide the problem. TTL expiry trims unacked messages from subscription cursors, so backlog can appear stable or declining while real consumer lag grows underneath. Operators monitoring backlog size alone see a healthy-looking number. The data loss is invisible unless you specifically monitor the expiry rate.&lt;/p></description></item><item><title>Apache Pulsar metadata store latency: the leading indicator before every cluster-wide failure</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-metadata-store-latency-high/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-metadata-store-latency-high/</guid><description>&lt;p>Metadata store latency is the earliest signal that a Pulsar cluster is heading toward a widespread outage. In most 3.x deployments the metadata store is ZooKeeper. &lt;!-- TODO: verify Oxia introduction version --> Pulsar 3.3.0 introduced experimental Oxia support as an eventual replacement. Every broker, bookie, and load balancer operation that touches cluster topology, bundle ownership, schema lookups, ledger metadata, or cursor persistence routes through this store. When round-trip latency for those operations rises, the symptoms appear downstream in brokers and bookies, but the root cause is upstream.&lt;/p></description></item><item><title>Apache Pulsar monitoring checklist: the signals every production cluster needs</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-monitoring-checklist/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-monitoring-checklist/</guid><description>&lt;p>Pulsar fails differently from most systems you operate. A cluster can report every process &amp;ldquo;up&amp;rdquo; while the write path stalls on a bookie journal disk, while a broker GC-pauses its ZooKeeper session away, or while a subscription silently freezes because its unacked message count hit a limit. Monitoring that only checks &amp;ldquo;is the broker running&amp;rdquo; misses almost every real Pulsar incident.&lt;/p>
&lt;p>This checklist organizes the signals that matter into four maturity levels: survival, operational, mature, and expert. Each level builds on the previous one. If you are standing up monitoring for a new cluster, start at Level 1 and work down. If you are auditing an existing deployment, jump to the level you think you are at and check for gaps.&lt;/p></description></item><item><title>Apache Pulsar monitoring maturity model: from survival to expert</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-monitoring-maturity-model/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-monitoring-maturity-model/</guid><description>&lt;p>Most Pulsar outages do not arrive without warning. The journal force write queue grows before publish latency spikes. ZooKeeper latency drifts upward for days before brokers lose session ownership. Direct memory climbs for weeks before the broker dies with an OutOfDirectMemoryError while heap dashboards look fine. The signals were there. The team just was not collecting them yet.&lt;/p>
&lt;p>This is a four-level maturity model for Pulsar monitoring, from the bare minimum that tells you the cluster is alive to the deep signals operators add after their second or third incident. Use it to audit your current coverage and decide what to instrument next. The levels are cumulative: each one assumes everything below it is already in place.&lt;/p></description></item><item><title>Apache Pulsar NotEnoughBookiesException: new ledgers cannot be created and writes fail</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-notenoughbookies-exception/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-notenoughbookies-exception/</guid><description>&lt;p>&lt;code>NotEnoughBookiesException&lt;/code> (BookKeeper error code -6, surfaced as &lt;code>BKNotEnoughBookiesException&lt;/code>) fires when the ensemble placement policy cannot satisfy the ensemble size (E) and write quorum (Qw) requirements for a new ledger. The broker requests a new ledger on size or time rollover, during topic recovery, and during compaction. If the policy cannot form a valid ensemble, ledger creation fails, the managed ledger has nowhere to write, and messages cannot be persisted durably.&lt;/p></description></item><item><title>Apache Pulsar OutOfDirectMemoryError: the off-heap crash JVM heap dashboards never show</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-outofdirectmemory-error/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-outofdirectmemory-error/</guid><description>&lt;p>The broker is down. Your JVM dashboard shows heap at 55%, GC pauses normal, no heap OOM anywhere. Then someone opens the broker log and finds the real cause:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-text" data-lang="text">&lt;span style="display:flex;">&lt;span>io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 16777216 byte(s) of direct memory (used: ..., max: ...)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>or the plainer JDK variant, &lt;code>java.lang.OutOfMemoryError: Direct buffer memory&lt;/code>. In recent Pulsar versions the process may have exited deliberately: PulsarByteBufAllocator catches the allocation failure and, with the default &lt;code>-Dpulsar.allocator.exit_on_oom=true&lt;/code>, kills the JVM rather than limp along half-broken. Either way, the broker is dead in the part your heap monitoring was not watching.&lt;/p></description></item><item><title>Apache Pulsar publish latency high: reading pulsar_broker_publish_latency P99</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-publish-latency-high/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-publish-latency-high/</guid><description>&lt;p>Your alert fired on sustained P99 elevation of &lt;code>pulsar_broker_publish_latency&lt;/code> above 2x the rolling baseline. Producers are seeing slow acknowledgements.&lt;/p>
&lt;p>The metric &lt;code>pulsar_broker_publish_latency&lt;/code> is a Summary metric exposed on the broker Prometheus endpoint. It measures the time from when the broker receives a message from a producer through the BookKeeper write path (write quorum Qw, ack quorum Qa) and back to the client callback. It is broker-side only: it excludes client-to-broker network time and producer-side batching delay. The Summary type provides quantiles at 0.5, 0.95, 0.99, 0.999, 0.9999, and 1.0. Alert on P99. P50 can look healthy while P99 is spiking, and it is the tail that triggers producer timeouts.&lt;/p></description></item><item><title>Apache Pulsar subscription backlog growing: consumers falling behind producers</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-subscription-backlog-growing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-subscription-backlog-growing/</guid><description>&lt;p>A growing subscription backlog means producers are publishing faster than consumers can acknowledge. The absolute backlog size matters less than its trajectory. A high but stable backlog is normal for lagged or replay consumers. A monotonically increasing backlog is a problem regardless of size: it consumes bookie disk until the bookie goes read-only, the backlog quota trips and throttles producers, or retention and TTL silently delete messages the consumer never saw.&lt;/p></description></item><item><title>Apache Pulsar throttled connections: the broker shedding load under pressure</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-throttled-connections/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-throttled-connections/</guid><description>&lt;p>Your dashboard shows &lt;code>pulsar_broker_throttled_connections&lt;/code> climbing from zero, producers are complaining about elevated send latency, and some clients are timing out on new operations. The broker process is up, the health endpoint returns 200, and heap looks fine. The broker is not broken. It is defending itself.&lt;/p>
&lt;p>Connection throttling is a protective mechanism. When the broker&amp;rsquo;s internal send queues on a connection back up beyond a configured ceiling, it stops reading new requests from that TCP connection (it disables auto-read on the Netty channel) until the backlog drains. The throttled connection count tells you how many connections are currently in that state. In a healthy cluster this gauge is zero. Any sustained non-zero value means the broker is at or near its capacity for the work being pushed through it.&lt;/p></description></item><item><title>Apache Pulsar TLS certificate expiry: the silent, total outage no metric warns you about</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-tls-certificate-expiry/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-tls-certificate-expiry/</guid><description>&lt;p>When every component in a Pulsar cluster uses TLS (brokers, bookies, ZooKeeper, proxies, clients), a single expired certificate causes immediate handshake failures. Existing connections may persist briefly, but every new connection attempt fails the TLS handshake. Producers cannot publish. Consumers cannot subscribe. Brokers cannot reach bookies. Brokers cannot reach ZooKeeper.&lt;/p>
&lt;p>Pulsar does not expose a metric for certificate expiry. There is no &lt;code>pulsar_cert_days_until_expiry&lt;/code> gauge. The first signals you see are indirect: authentication failures spike, connections drop, and SSL handshake exceptions fill the logs. By that point, the outage is already happening. The only reliable defense is external certificate expiry monitoring that alerts you days or weeks before the cert becomes invalid.&lt;/p></description></item><item><title>Apache Pulsar topic ownership oscillation: brokers fighting over the same bundle</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-topic-ownership-oscillation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-topic-ownership-oscillation/</guid><description>&lt;p>Broker A takes ownership of a namespace bundle, opens managed ledgers, and begins serving clients. The load balancer sees A as overloaded and unloads the bundle. Broker B picks it up, fences the ledgers, creates new ones, and starts serving. The balancer now sees B as overloaded and moves it back. The cycle repeats indefinitely.&lt;/p>
&lt;p>Each iteration forces ledger fencing, new ledger creation, ZK metadata writes, and client disconnection and reconnection storms. Producers see intermittent publish latency spikes. New clients fail lookups during the brief ownership gap between fencing and re-acquisition. The cluster looks healthy in aggregate because no single broker is down, but the affected topics are in a constant state of transition.&lt;/p></description></item><item><title>Apache Pulsar unacked messages at the limit: the silent dispatch freeze</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-unacked-messages-dispatch-freeze/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-unacked-messages-dispatch-freeze/</guid><description>&lt;p>Consumers are connected. Producers are publishing. Backlog looks flat or zero. But no messages are being processed.&lt;/p>
&lt;p>Pulsar brokers enforce a per-subscription limit on unacknowledged messages (&lt;code>maxUnackedMessagesPerSubscription&lt;/code>, default 200,000) and a per-consumer limit (&lt;code>maxUnackedMessagesPerConsumer&lt;/code>, default 50,000). When unacked messages hit either ceiling, the broker stops dispatching new messages to that subscription or consumer. No error is returned to the client. No exception is thrown. Dispatch pauses silently.&lt;/p>
&lt;p>Most monitoring focuses on backlog and connection count. Both can look healthy during a freeze. Messages were already dispatched to consumers, so backlog may read zero. Consumers remain connected at the TCP level. The definitive indicators are the unacked message count itself and the &lt;code>blockedSubscriptionOnUnackedMsgs&lt;/code> flag in topic stats.&lt;/p></description></item><item><title>Apache Pulsar under-replicated ledgers: data at risk after a bookie failure</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-under-replicated-ledgers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-under-replicated-ledgers/</guid><description>&lt;p>You lost a bookie. The broker layer kept serving traffic because your write quorum absorbed the failure. But now &lt;code>auditor_NUM_UNDER_REPLICATED_LEDGERS&lt;/code> is climbing, and it is not coming back down. Every minute it stays elevated is a minute your data exists on fewer copies than your replication factor demands. If another bookie fails before AutoRecovery finishes rereplicating, those ledgers are gone permanently.&lt;/p>
&lt;p>This metric is exposed only on the elected auditor node, not on every bookie. If you are scraping bookie metrics and do not see it, you are either scraping the wrong host or AutoRecovery is not running. In steady state, the count is zero. After a bookie restart or failure, a temporary spike is expected and should trend back to zero within minutes to hours depending on data volume. A count that grows across audit intervals means recovery is failing, or bookies are dying faster than recovery can complete.&lt;/p></description></item><item><title>Apache Pulsar write stall: bookie journal fsync latency and the blocked write path</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-journal-write-stall/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-journal-write-stall/</guid><description>&lt;p>The write stall is the most common performance failure in Pulsar. It starts at the bookie journal disk and cascades upward through the write path until producers are blocked or timing out.&lt;/p>
&lt;p>Every persistent message write in Pulsar must survive a journal fsync before the bookie acknowledges it. The broker waits for ack quorum (Qa) acknowledgments before acknowledging the producer. When the journal disk cannot sync fast enough, pending fsync operations accumulate, add-entry operations queue up, brokers hold connections open waiting for acks, client buffers fill, and throughput collapses.&lt;/p></description></item><item><title>Apache Pulsar ZooKeeper session cascade: reconnect storms and the thundering herd</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-zookeeper-session-cascade/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-zookeeper-session-cascade/</guid><description>&lt;p>Multiple brokers lose their ZooKeeper sessions within seconds of each other. Bundle ownership churns across the cluster as surviving brokers acquire orphaned bundles. Every connected producer and consumer simultaneously discovers its topic has moved or its connection has dropped, triggering a mass reconnection event. Each reconnection generates topic lookups, ephemeral node registrations, and watch re-establishments that hit the already overloaded ZK ensemble. Latency rises further, more sessions expire, and the cascade tightens.&lt;/p></description></item><item><title>Apache Pulsar ZooKeeper session expired: brokers fenced and topics reassigned</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-zookeeper-session-expired/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-zookeeper-session-expired/</guid><description>&lt;p>A broker&amp;rsquo;s ZooKeeper session expires when it fails to send heartbeats within the session timeout window. The expiry triggers immediate fencing of the broker, loss of all namespace bundle ownership, and reassignment of those bundles to surviving brokers. Clients connected to the fenced broker see errors like &amp;ldquo;Topic is temporarily unavailable&amp;rdquo; or &amp;ldquo;Attempting to add producer to a fenced topic&amp;rdquo; until the topics are picked up elsewhere.&lt;/p>
&lt;p>The most common root cause is a long JVM garbage collection pause on the broker that prevents ZK heartbeats from being sent in time. The second most common is elevated ZK server latency, where heartbeats are sent but not processed before the timeout. Both paths converge on the same outcome: the broker&amp;rsquo;s ephemeral znodes are deleted, ownership transfers, and the cluster enters a state of high metadata churn.&lt;/p></description></item><item><title>Apache Pulsar ZooKeeper watch explosion: thousands of watches killing metadata latency</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-zookeeper-watch-explosion/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-zookeeper-watch-explosion/</guid><description>&lt;p>Topic lookups slow down. Bundle ownership transfers stall. Broker sessions flicker between connected and disconnected. ZooKeeper reports thousands, sometimes tens of thousands, of registered watches. This is a watch explosion, and the root cause is rarely in ZooKeeper itself. It is in client connection churn.&lt;/p>
&lt;p>Watches accumulate when consumers disconnect and reconnect in waves. Each reconnection registers metadata watches for topic ownership, subscription state, and policy changes. During a mass reconnection event (broker restart, network blip, load balancer cycle), thousands of ephemeral znodes are created and deleted in rapid succession. Each creation and deletion triggers watch registration and notification. ZK processes requests sequentially, so as notification load grows, request latency climbs. Once latency exceeds session timeout, brokers lose sessions, triggering bundle unloads and another round of client reconnections. The feedback loop tightens until the cluster thrashes.&lt;/p></description></item><item><title>How Apache Pulsar actually works in production: a mental model for operators</title><link>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-how-it-works-in-production/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.netdata.cloud/guides/apache-pulsar/apache-pulsar-how-it-works-in-production/</guid><description>&lt;p>Most Pulsar incidents are misdiagnosed in the first thirty minutes because the operator is looking at the wrong layer. A publish latency spike gets chased on the broker when the real bottleneck is a bookie journal disk. A &amp;ldquo;consumer problem&amp;rdquo; turns out to be a cursor that stopped advancing. A broker that looks healthy on its HTTP endpoint is fenced off from ZooKeeper and losing topic ownership in a loop.&lt;/p></description></item></channel></rss>