Architecture
Server shutdown modes
PostgreSQL has three controlled shutdown modes. Smart waits for sessions, fast terminates sessions and rolls back their active transactions, and immediate aborts server processes without normal shutdown processing, requiring crash recovery on the next startup.
In plain words
pg_ctl stop offers three modes, and they are intentionally very different. Fast is the pg_ctl default.
| Mode | Signal to postmaster | Client sessions | Normal shutdown checkpoint? | Next start |
|---|---|---|---|---|
| smart | SIGTERM | New connections are refused; existing sessions are allowed to finish normally. | Yes, after sessions drain. | Clean start. |
| fast | SIGINT | Existing server processes are told to exit; active transactions are aborted and clients disconnect promptly. | Yes, after backends stop. | Clean start. |
| immediate | SIGQUIT | Children are aborted immediately; stragglers can be SIGKILLed after 5 seconds. | No. | Crash recovery required. |
Smart and fast are both clean database shutdowns; their difference is how they handle connected sessions before the clean shutdown sequence begins. Immediate is an emergency stop: it deliberately skips normal database shutdown processing so PostgreSQL must replay WAL next time.
Do not use SIGKILL on the main postgres/postmaster as your normal stop method. It prevents PostgreSQL from coordinating its children and cleaning up normally.
For DBAs and operators
Smart — wait for the users
pg_ctl stop -m smart sends SIGTERM to the postmaster. PostgreSQL stops accepting ordinary new connections but remains in its running/hot-standby state while existing client sessions finish. Only after the regular sessions have gone does the postmaster advance into the shutdown states.
Fast — stop sessions, then shut down cleanly
pg_ctl stop -m fast sends SIGINT. This is the default pg_ctl stop mode. PostgreSQL refuses new sessions and tells existing server processes to terminate; client backends abort active transactions and exit promptly. The postmaster waits for the relevant children before moving on to the clean database-shutdown phase.
The clean-shutdown tail
For both smart and fast shutdown, once backends are out of the way the postmaster reaches PM_WAIT_XLOG_SHUTDOWN and asks the checkpointer to perform the shutdown-WAL work. In checkpointer.c, SIGINT sets ShutdownXLOGPending, then ShutdownXLOG() performs the shutdown checkpoint/restartpoint work and notifies the postmaster with PMSIGNAL_XLOG_IS_SHUTDOWN. The state machine then waits for remaining WAL archival/sender work, I/O workers and the checkpointer before the postmaster exits.
Immediate — deliberately unclean
pg_ctl stop -m immediate sends SIGQUIT. The postmaster relays an immediate-abort signal to its children and does not run normal database shutdown processing. PostgreSQL waits for the children to terminate; a child still alive after 5 seconds can receive SIGKILL. The next start therefore follows the crash-recovery path and replays WAL.
Durability versus consistency
Immediate shutdown is designed to recover to a consistent database state through WAL redo; it is not a normal way to "corrupt" a healthy PostgreSQL cluster. However, durability still follows each transaction's configured commit guarantees. With the usual synchronous_commit = on, a commit is acknowledged only after the required local WAL flush. Modes that intentionally acknowledge before durable flush can lose a small window of recently acknowledged work after a crash/immediate stop.
Operational commands
pg_ctl stop -D "$PGDATA" -m smart
pg_ctl stop -D "$PGDATA" -m fast # pg_ctl default
pg_ctl stop -D "$PGDATA" -m immediate # emergencies
# -w (the default for stop) waits until postmaster.pid disappears
pg_ctl stop -D "$PGDATA" -m fast -wPostgreSQL 18 source trail: postmaster.c defines SmartShutdown, FastShutdown, ImmediateShutdown and the shutdown state machine. checkpointer.c documents the normal shutdown checkpoint path. See also PostgreSQL 18: Shutting Down the Server and pg_ctl.
For developers: inside the source
Signal to state machine
The postmaster's handler handle_pm_shutdown_request_signal() only sets a pending flag; the work happens in process_pm_shutdown_request() from the main loop, which picks SmartShutdown, FastShutdown or ImmediateShutdown, writes stopping into postmaster.pid and calls PostmasterStateMachine(). The states, in order:
PM_RUN (smart: connsAllowed = false until no B_BACKEND left)
PM_STOP_BACKENDS SignalChildren(SIGTERM, …)
PM_WAIT_BACKENDS backends, autovacuum, bgworkers, walwriter, bgwriter …
PM_WAIT_XLOG_SHUTDOWN checkpointer got SIGINT
PM_WAIT_XLOG_ARCHIVAL archiver and walsenders got SIGUSR2
PM_WAIT_IO_WORKERS io workers got SIGUSR2
PM_WAIT_CHECKPOINTER checkpointer got SIGUSR2
PM_WAIT_DEAD_END → PM_NO_CHILDREN → exitThe checkpointer, archiver, WAL senders and I/O workers are deliberately left running in PM_WAIT_BACKENDS: the shutdown checkpoint still needs them, and WAL senders must ship it to standbys.
What each child does
- Backends get
SIGTERM:die()inpostgres.csetsProcDiePending; at the nextCHECK_FOR_INTERRUPTS(),ProcessInterrupts()raises FATAL "terminating connection due to administrator command" and the transaction aborts during exit. - Checkpointer:
SIGINTsetsShutdownXLOGPending(ReqShutdownXLOG()); it then callsShutdownXLOG(), which runsCreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE)(orCreateRestartPoint()on a standby), setsDB_SHUTDOWNED(orDB_SHUTDOWNED_IN_RECOVERY) in pg_control and sendsPMSIGNAL_XLOG_IS_SHUTDOWN. It ignoresSIGTERMand exits only onSIGUSR2. - Immediate:
TerminateChildren(SIGQUIT); backends runquickdie()("terminating connection due to immediate shutdown command"). AfterSIGKILL_CHILDREN_AFTER_SECS(5)ServerLoop()logs "issuing SIGKILL to recalcitrant children". No checkpoint, so pg_control still saysDB_IN_PRODUCTION(orDB_IN_ARCHIVE_RECOVERY) and the next start replays WAL.
pg_ctl side
do_stop() reads the PID from postmaster.pid, sends the signal with kill() and, with -w, wait_for_postmaster_stop() polls until the file is gone (--timeout, default 60 s).
Experiment and extend
src/test/postmaster/t/003_start_stop.plandsrc/test/recovery/t/013_crash_restart.pl;pg_controldatashows "Database cluster state" after each mode.- Extensions clean up with
before_shmem_exit(),on_shmem_exit()oron_proc_exit()callbacks (ipc.c); background workers getSIGTERMinPM_STOP_BACKENDS(default handlerbgworker_die()inbgworker.c).
Parameters that shape this
Related topics
Server startup sequence Postmaster Checkpointer Startup process Crash recovery Write-ahead log (WAL) Process model