5 min read
A replication-slot status metric is not proof of replication health
A useful signal with a narrow job
A logical replication slot can be synchronized across a high-availability pair while the data pipeline that depends on it is still behind, stopped, or unable to recover. That is why I would treat Azure Database for PostgreSQL’s logical_replication_slot_sync_status as evidence about one part of the system—not as a green light for replication as a whole.
Azure’s PostgreSQL release notes list the metric, and Microsoft describes it as a binary signal for whether logical replication slots are synchronized between the HA primary and standby in its March 2026 Azure Database for PostgreSQL recap. That answers an important operational question: if the primary fails, is the slot state available on the standby for a failover scenario?
It does not answer whether a consumer is connected, whether it is applying changes, how far behind it is, or whether the whole path can resume after promotion. Those are different questions with different evidence. I would keep the new metric, but put it beside signals for slot health, consumer progress, data freshness, and recovery—not use it in place of them.
Separate slot state from data movement
A slot is a mechanism for retaining the WAL a logical consumer needs. Its state is not the same thing as the consumer’s progress. PostgreSQL exposes slot details such as whether a consumer is active and the slot’s WAL positions in pg_replication_slots. On the subscriber, pg_stat_subscription exposes information about subscription workers.
I would monitor both sides. On the publisher, this query makes it possible to see whether each logical slot has an active consumer and how much WAL lies between the current WAL position and the slot’s restart point:
SELECT
slot_name,
active,
restart_lsn,
confirmed_flush_lsn,
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS wal_bytes_from_restart
FROM pg_replication_slots
WHERE slot_type = 'logical';
The byte difference is a useful indication of WAL retained behind a slot, not a direct measurement of subscriber lag. A slot may be inactive because its consumer is disconnected; an active slot does not prove the consumer is applying changes at an acceptable rate. And a growing retained-WAL amount deserves attention even if the slot synchronization metric says the HA copies are in sync.
On the subscriber, I would look for a running worker and inspect its reported receive and apply-related positions and timestamps:
SELECT
s.subname,
st.pid,
st.received_lsn,
st.latest_end_lsn,
st.last_msg_receipt_time
FROM pg_stat_subscription AS st
JOIN pg_subscription AS s ON s.oid = st.subid;
These observations need interpretation over time and in the context of the workload. A single sample cannot tell me whether progress is advancing. Nor would I treat a worker row or a recent message receipt as proof that the subscriber’s application-visible data is fresh. PostgreSQL’s logical replication monitoring guidance describes the subscription statistics, but the operational question still belongs to the system I am building: are changes arriving and being applied quickly enough for the consumer’s purpose?
Measure the outcome the consumer needs
I want an end-to-end freshness signal as well as database internals. If a downstream system must reflect source changes within a defined window, then the useful measurement is the age of the newest change it has actually made available—not just the state of a slot or a replication worker.
One practical pattern is to include a small, identifiable heartbeat in the published data and check when it becomes visible downstream. The details depend on the publication and consumer, so I would not assume that a heartbeat table is automatically included or processed. The important design point is to test the path the real data takes: source commit, logical decoding, transport, consumer processing, and the read that users or dependent services rely on. If that check stops advancing, I know the outcome is unhealthy even if individual components report normal state.
I would also watch trends rather than only thresholds. Increasing WAL retained behind a slot, a consumer position that stops moving, or a growing age of downstream data each points to a different failure mode. The point is not to add every available number to one dashboard. It is to make each signal answer a distinct question, so an alert tells the on-call engineer what has stopped working and where to begin looking.
Make failover readiness an explicit test
Slot synchronization improves evidence about failover readiness, but readiness has more dependencies than slot state. After promotion, the consumer must connect to the right endpoint, find a usable slot, and resume from a position that preserves the required continuity. The system also needs enough retained WAL for its recovery path. I would not infer all of that from one status metric.
I would turn recovery into a runbook exercise: check the slot synchronization signal, verify that the expected slot exists and is usable after promotion, confirm that the consumer reconnects and advances, and validate that downstream data becomes fresh again. The exact steps depend on the managed service and the consumer, so I would follow the service’s documented failover behavior rather than assume that a synchronized slot guarantees a successful recovery.
The useful alert is therefore not simply “slot status is bad” or “slot status is good.” I would alert on slot synchronization because it tells me something important about the HA pair. Separately, I would alert when consumer progress stalls, retained WAL moves in the wrong direction, or end-to-end freshness exceeds the system’s requirement. A green slot-sync signal is reassuring evidence about one boundary. Replication health is the larger claim, and I would only make it when the data is moving and the recovery path has been shown to work.
Drafted with AI assistance, reviewed and edited by Ali.