PostgreSQL "the database system is starting up" — Should I Wait or Intervene?
Diagnosing 57P03: separating routine startup from looping crash recovery, decoding pg_isready exit codes (0, 1, 2), inspecting pg_controldata, and archive command stalls.
Operational Verification & Reliability Metadata
The error string is a symptom, not the root cause. Do not restart the server blindly. Run the diagnostic queries below to pinpoint the actual failure mode.
▸Symptom
FATAL: the database system is starting up
FATAL: the database system is in recovery mode
FATAL: the database system is shutting down
FATAL: the database system is not yet accepting connections
FATAL: the database system is in an inconsistent stateAll coalesce under PostgreSQL SQLSTATE code `57P03` (cannot_connect_now).
This error confronts database reliability engineers with an urgent decision: "Should I wait, or should I intervene immediately?"
The purpose of this guide is to resolve that decision using empirical telemetry rather than panic.
▸Three Core Scenarios
- 1Routine Boot Initialization: The daemon just started; shared memory is initializing, and preloaded extensions are binding. Connections will be accepted within seconds. Do not intervene; wait.
- 2Crash Recovery (WAL Redo): The server halted uncleanly (power failure, kernel OOM kill, power loss). PostgreSQL is replaying Write-Ahead Logs (
REDO) from the last checkpoint to guarantee ACID consistency. Depending on dirty buffer volumes before the crash, this may take between 30 seconds and 20 minutes. - 3Stuck / Looping Recovery: Recovery is stalled in a crash-loop or hanging indefinitely waiting for a missing archive segment. Immediate intervention is required.
▸Triage via `pg_isready` Exit Codes
PostgreSQL provides `pg_isready` specifically to evaluate server readiness:
pg_isready -h localhost -p 5432 -d app
echo $?Exit code semantics:
- •0: Cluster ready; accepting client connections.
- •1: Cluster running, but rejecting client connections (starting up or running redo recovery) → Scope of this guide (
57P03). - •2: No response (daemon is down or port is blocked) → Scope of guide H-07.
- •3: Invalid invocation arguments.
An exit code of 1 proves PostgreSQL is active and repairing itself; killing the process here is catastrophic.
▸Is Recovery Progressing or Deadlocked?
Inspect the server logs for redo checkpoints:
LOG: database system was not properly shut down; automatic recovery in progress
LOG: redo starts at 0/1A2B3C48
LOG: redo done at 0/2F9D11A0
LOG: database system is ready to accept connections- •Progressing: LSN numbers advance sequentially between
redo starts atandredo done at. Active disk I/O confirms healthy recovery. - •Crash Loop: The exact same
redo starts atline logs repeatedly every few minutes. The postmaster completes redo and segfaults before opening connections (usually disk exhaustion or corrupt WAL headers). - •Archive Stall: The
restore_commandrepeatedly fails to fetch a required segment.
Querying Cluster State via pg_controldata
When psql is locked out, read the on-disk control block directly:
pg_controldata "$PGDATA" | grep -E 'cluster state|Latest checkpoint|REDO'▸Emergency Intervention Best Practices
Throttling Reconnection Surges
When PostgreSQL finally emits database system is ready to accept connections, hundreds of queued client connection pools will simultaneously flood port 5432. Throttle traffic at the PgBouncer pooler tier to allow shared buffers to warm up gracefully.
▸Related Error Guides & Hub Links
- •PostgreSQL Connection Refused (H-07) — Unreachable ports and daemon down
- •PostgreSQL Conflict with Recovery (H-11) — Standby replication query cancellation
- •PostgreSQL Terminating Connection (H-31) — Connection severance during shutdown
- •PostgreSQL Hub — Cluster initialization and disaster recovery
Other Database Error Triage Playbooks
Other battle-tested diagnostic guides for high-severity database errors.
PostgreSQL Connection Exhaustion & too many clients Triage
Root causes of FATAL: sorry, too many clients already and remaining connection slots errors, read-only pg_stat_activity diagnosis with privilege boundaries, and two-tier pooling mitigation.
PostgreSQL password authentication failed: Root Cause and Fix
Four root causes of psql password authentication failed: incorrect password, md5/SCRAM mismatch, pg_hba.conf rule ordering, and port/cluster confusion. Step-by-step triage.
PostgreSQL connection refused: 8-Step Definitive Triage
Difference between connection refused, timeout, and no pg_hba entry; triage for listen_addresses, port conflicts, firewalls, and Docker container mappings.