Unexpected storage growth in PostgreSQL does not always mean the database itself is growing. Write-Ahead Log (WAL) retained by replication slots can consume significant storage when replicas or subscribers stop consuming WAL. This article explores common scenarios that cause unexpected storage growth in Azure Database for PostgreSQL Flexible Server, how to identify WAL retention as the cause, and best practices to monitor and prevent it. Replication slots are essential for reliable replication, but when a slot stops advancing, WAL can accumulate and gradually consume available storage.
Table of Contents
Understanding WAL in PostgreSQL
PostgreSQL uses Write-Ahead Logging (WAL) to guarantee durability and consistency. Every change made to the database is first recorded in WAL before being written to data files.
The following activities generate WAL:
- INSERT operations
- UPDATE operations
- DELETE operations
- VACUUM operations
- CREATE INDEX
- ALTER TABLE
- Bulk data loads
- Maintenance operations
A common misconception is that WAL generation is only significant for large transactions. Database workloads with frequent data modifications continuously generate WAL throughout the day.
WAL is critical for both crash recovery and replication.Why Replication Slots Exist
Imagine a primary server generating WAL files while a replica becomes temporarily unavailable.
Without replication slots, PostgreSQL would eventually remove older WAL files to reclaim storage space.
In this scenario, the replica would require rebuilding.To prevent this, PostgreSQL uses replication slots.
A replication slot tracks the WAL position required by a specific replica and prevents PostgreSQL from deleting WAL files that have not yet been consumed.
This mechanism significantly improves replication reliability.
The Hidden Side Effect
Replication slots solve one problem but introduce another.
When a replica stops consuming WAL, PostgreSQL continues retaining WAL files because the replication slot indicates they are still required.
The database may function normally. Applications may run without issues. Database size may remain unchanged.
Yet storage usage continues increasing.
This often times comes as a surprise, because the growth isn't coming from tables or indexes.
It comes from retained transaction logs.
Microsoft documentation specifically notes that replication slots automatically retain WAL required by replicas and warns that inactive replication slots can cause significant storage growth on the primary server.
Let’s explore some common scenarios that can lead to unexpected storage growth due to WAL retention
Scenario 1: Replica Lag
Replica lag is perhaps the most common cause of WAL accumulation.
Consider a workload generating:
- 50 GB WAL per day
If the replica falls behind and remains several days behind the primary:
The primary cannot remove WAL because the replica still requires it.
Even though replication is technically working, retained WAL continues to grow.
Common causes include:
- Network latency
- High write workloads
- Long-running transactions
- Resource bottlenecks on replicas
What to do
- Monitor replication lag and primary storage using Azure Monitor metrics.
- Investigate sustained or increasing replication lag and address the underlying cause.
- Continue monitoring storage while the replica catches up, as accumulated WAL may remain until it is no longer required.
See the “How to investigate” section below for steps to monitor replication lag, check replication slots, and correlate WAL retention with storage growth.
Scenario 2: Broken Replica
When a replica becomes unavailable due to infrastructure, maintenance, or recovery issues, WAL required by the replica can accumulate on the primary and contribute to storage growth.
When the replica is unavailable:
What to do
- Restore the replica if it is still required.
- Monitor replication lag and primary storage using Azure Monitor metrics while the replica is unavailable.
- If the replica has been permanently removed, verify that its associated replication slot is no longer required before removing the slot.
- Do not remove a replication slot simply because it is inactive. Confirm that no replica or other replication consumer still depends on it.
See the “How to investigate” section below for steps to identify inactive replication slots and measure retained WAL.
Scenario 3: Deleted Logical Replication Subscriber
If a logical replication subscriber is removed but its replication slot remains on the publisher, the slot can continue retaining WAL even though the subscriber is no longer consuming it.
What to do
Confirm whether the subscriber has been permanently removed. If the associated replication slot is no longer required, it can be removed after verifying that no replication consumer depends on it.
See the “How to investigate” section below for steps to identify inactive logical replication slots and measure retained WAL.
Scenario 4: WAL Retention Becomes the Largest Storage Consumer
One of the most interesting escalation cases occurs when WAL occupies more storage than business data.
For example:
|
Component |
Size |
|
Database Data |
500 GB |
|
Indexes |
120 GB |
|
WAL Retention |
1.8 TB |
At this point, the actual application data is no longer the primary storage consumer.
The retained WAL becomes the dominant storage workload.
You will commonly see symptoms like:
- Stable database size
- Continuously increasing storage utilization
- Unexpected storage alerts
- Auto-grow events
What to do
- Identify replication slots retaining significant WAL.
- Monitor Storage Used and Storage Percentage in Azure Monitor.
- Resolve the underlying replication issue rather than relying on additional storage alone.
See the “How to investigate” section below for steps to identify replication slots and measure retained WAL.
Scenario 5: Primary Server Enters Read-Only Mode
The most severe outcome is storage exhaustion.
According to Microsoft documentation, when retained WAL causes storage utilization to reach critical thresholds, Flexible Server can automatically switch to read-only mode to prevent disk-full scenarios.
The sequence typically looks like:
At this stage, the server prevents further modifications, which can result in application write failures and service impact. Microsoft also notes that disk-full conditions can affect operational activities such as backups and WAL archiving
This behavior has been observed in real-world storage exhaustion incidents where storage consumption reached critical levels and database write operations were affected.
What to do
- Monitor Storage Percentage and Storage Used in Azure Monitor.
- Check whether retained WAL is contributing to storage growth.
- Resolve the underlying replication or replication-slot issue where applicable.
- Configuring alerts on Storage Percentage for approaching disk-full conditions.
How to Investigate
- Review Azure Monitor Metrics and Configure Alerts
Monitor: Use Azure Monitor Metrics to track storage consumption and replication health over time.
In the Azure portal, open your Flexible Server and use Monitoring > Metrics (Metrics Explorer) to review the relevant storage and replication metrics. You can also select Dashboards with Grafana from the server menu to use the built-in Grafana monitoring experience.
-
- Transaction Log Storage Used (txlogs_storage_used) to track transaction log/WAL storage consumption.
- Storage Used Monitor the amount of storage currently consumed and look for sustained or unexpected growth.
- Storage Percentage: Monitor how much of the provisioned storage is being consumed and watch for a steady increase toward the available capacity.
- Read Replica Lag (physical_replication_delay_in_seconds): Shows replica lag in seconds on an individual read replica.
- Max Logical Replication Lag (logical_replication_delay_in_bytes): Shows the maximum WAL backlog retained for logical replication.
- Max Physical Replication Lag (physical_replication_delay_in_bytes): Shows the largest physical replication backlog on the primary server.
Learn more about Monitor here.
Learn more about Dashboards with Grafana here.
Alert: Use Azure Metric alerts for proactive monitoring and alerting.
Create metric alerts based on the backlog and storage limits that the workload can tolerate. Useful starting examples include:
-
- Alert when Max Logical Replication Lag exceeds the acceptable logical replication backlog.
- Alert when Read Replica Lag remains above 300 seconds.
- Alert when Storage Percentage exceeds 80%.
For configuration steps, see Configure metric alerts for Azure Database for PostgreSQL Flexible Server.
2. Check Replication Slots
For logical replication, first monitor Max Logical Replication Lag (logical_replication_delay_in_bytes) in Azure Monitor to identify whether the replication backlog is increasing.
If the metric shows a sustained or increasing backlog, check the replication slots to identify inactive consumers:
SELECT slot_name, slot_type, restart_lsn, inactive_since FROM pg_replication_slots WHERE active='f';
Note: " inactive_since" column only exists in PostgreSQL 17 and later.
This query identifies inactive replication slots. Investigate each inactive slot to determine whether its replication consumer is temporarily unavailable or whether the slot is no longer required.
3. Check Replica Status
For read replicas, start by monitoring replication lag in Azure Monitor. Use Read Replica Lag (physical_replication_delay_in_seconds) on each replica and Max Physical Replication Lag (physical_replication_delay_in_bytes) on the primary server to identify replicas that are falling behind.
If Azure Monitor indicates persistent or increasing replication lag, check the replication state from the primary:
SELECT usename, application_name, state, sync_state, replay_lag FROM pg_stat_replication;
Use the replication state and replay_lag to understand whether the replica is keeping up:
-
- state = streaming: WAL is actively being streamed to the replica.
- state = catchup: The replica is connected but is working through a WAL backlog.
- replay_lag: Helps identify delay in WAL replay on the replica.
4. Measure Retained WAL
Before measuring WAL retained by individual replication slots, review the following metrics in Azure Monitor:
-
- Transaction Log Storage Used (txlogs_storage_used): helps determine whether transaction/WAL log usage is increasing.
- Storage Percentage (storage_percent): shows overall storage utilization as a percentage.
- Storage Free (storage_free): shows the remaining available storage.
Reviewing these metrics together helps determine whether increasing transaction-log usage is contributing to overall storage pressure.
If transaction-log storage is increasing, use the following query to determine how much WAL is being retained by each replication slot:
SELECT slot_name, pg_size_pretty( pg_wal_lsn_diff(pg_current_wal_lsn(),restart_lsn)) AS retained_wal FROM pg_replication_slots;
-
- restart_lsn represents the earliest WAL position that may still be required by the replication slot.
- retained_wal estimates the amount of WAL between the slot’s restart_lsn and the current WAL position.
- A large or steadily increasing retained_wal can indicate that the slot is not advancing fast enough and WAL is accumulating.
- Compare retained_wal across slots to identify which slot is associated with the largest WAL retention.
Preventative Measures
✅ Monitor replication lag and overall storage utilization.
✅ Configure Azure Monitor alerts for replication lag and storage percentage.
✅ Regularly review replication slots
✅ Remove unused slots only after confirming that no replication consumer depends on them.
✅ Validate replica health after maintenance activities
✅ Include replication slot checks in operational runbooks
Conclusion
By proactively monitoring replication lag, replica health, replication slots, and storage metrics, administrators can identify issues like lagging replicas and inactive replication slots early, helping prevent unexpected storage growth caused by retained WAL.