How to fix Recovery is in progress in PostgreSQL

PostgreSQLINTERMEDIATEMEDIUMUpdated Dec 28, 2025ยท 323 views

This error occurs when PostgreSQL is performing recovery after an improper shutdown or when WAL control functions are executed on a standby/replica server. Most cases resolve automatically once recovery completes.

Quick fix

Fixes Recovery is in progress

psql -U postgres -d postgres -c "SELECT pg_is_in_recovery()"
  1. Check if recovery is automatic startup recovery
  2. Monitor recovery progress during startup
  3. Wait for recovery to complete
  4. For standby servers: use correct functions
postgresql โ€” error
psql -U postgres -d postgres -c "SELECT pg_is_in_recovery()"
Recovery is in progress

What this error means

PostgreSQL enters recovery mode in two main scenarios. First, when the database is started after an unclean shutdown (crash, power loss, or forced termination), PostgreSQL must replay Write-Ahead Log (WAL) records from the last checkpoint to restore consistency. Second, standby/replica servers are perpetually in recovery mode while replicating from a primary server. During recovery, certain WAL control functions (like pg_current_wal_lsn(), pg_start_backup(), and pg_replication_slots queries) are restricted because they can only run on the primary server.

Typical symptoms

  • PostgreSQL startup is slow or appears frozen
  • Database reports "ERROR: recovery is in progress" when running WAL functions
  • Monitoring tools fail with "HINT: WAL control functions cannot be executed during recovery"
  • Cannot connect to database with "FATAL: the database system is in recovery mode"
  • Replication-related queries fail on standby nodes

Common causes

  1. Database was not shut down cleanly (power loss, kill -9, crash)
  2. PostgreSQL process was forcibly terminated while running
  3. Attempting WAL control functions on a standby/replica server
  4. Monitoring tools or scripts querying replication functions on non-primary servers
  5. Incomplete or interrupted recovery process from a previous crash

How to fix "Recovery is in progress"

1Check if recovery is automatic startup recovery

If PostgreSQL just started, allow the automatic recovery process to complete. Watch the logs:

bash
psql -U postgres -d postgres -c "SELECT pg_is_in_recovery()"

Returns t (true) if in recovery, f (false) if fully started. The recovery process typically completes within minutes unless the WAL is very large.

2Monitor recovery progress during startup

While PostgreSQL is recovering, you can monitor progress:

bash
# Check if recovery is still running
ps aux | grep "startup recovering"

# Use pg_controldata to see recovery state (if available)
pg_controldata -D $PGDATA

Look for incrementing WAL positions to confirm recovery is progressing.

3Wait for recovery to complete

Do not restart PostgreSQL or interrupt the process. Let it complete fully. For very large databases with extensive WAL files, recovery can take hours. Check logs for:

bash
LOG: database system was interrupted; last known up at 2024-12-28 10:15:23
LOG: database system was not properly shut down; automatic recovery in progress
LOG: redo starts at 0/...
LOG: redo done at 0/...
LOG: database system is ready to accept connections
4For standby servers: use correct functions

If the error occurs on a standby server, use functions designed for standby nodes:

sql
-- Instead of:
SELECT pg_current_wal_lsn(); -- ERROR on standby

-- Use on standby:
SELECT pg_last_wal_receive_lsn(); -- Safe on standby
SELECT pg_last_wal_replay_lsn();  -- Safe on standby
SELECT pg_is_in_recovery();       -- Safe on standby
5Fix monitoring tools to check recovery state

Update monitoring scripts to check recovery mode before running restricted functions:

sql
-- Safe way to check replication slots on any server:
IF NOT pg_is_in_recovery() THEN
  SELECT slot_name, database FROM pg_replication_slots;
END IF;

-- Or use the appropriate standby functions:
SELECT slot_name, database, active FROM pg_replication_slots
WHERE NOT pg_is_in_recovery() OR function_name != 'pg_wal_lsn_diff';

Advanced notes

For PostgreSQL 15+, use the log_startup_progress_interval parameter to get periodic progress updates during recovery: ALTER SYSTEM SET log_startup_progress_interval = '10s'; SELECT pg_ctl_restart();. Recovery time depends on WAL volume and I/O performance; on systems with many transactions, recovery can legitimately take hours. If recovery appears stuck (no progress for extended time), check for disk I/O bottlenecks, corrupted WAL files, or hardware failures. Use pg_wal_replay_pause() on primary (not standby) to temporarily pause WAL replay during streaming replication if needed.

Frequently asked questions

What does "Recovery is in progress" mean?
PostgreSQL enters recovery mode in two main scenarios. First, when the database is started after an unclean shutdown (crash, power loss, or forced termination), PostgreSQL must replay Write-Ahead Log (WAL) records from the last checkpoint to restore consistency. Second, standby/replica servers are perpetually in recovery mode while replicating from a primary server.
How do I fix "Recovery is in progress"?
This error occurs when PostgreSQL is performing recovery after an improper shutdown or when WAL control functions are executed on a standby/replica server. Most cases resolve automatically once recovery completes.
What causes "Recovery is in progress"?
Database was not shut down cleanly (power loss, kill -9, crash) PostgreSQL process was forcibly terminated while running Attempting WAL control functions on a standby/replica server
Is the "Recovery is in progress" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading