DB Internals AtlasPostgreSQL 18.6 Home About

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.

ModeSignal to postmasterClient sessionsNormal shutdown checkpoint?Next start
smartSIGTERMNew connections are refused; existing sessions are allowed to finish normally.Yes, after sessions drain.Clean start.
fastSIGINTExisting server processes are told to exit; active transactions are aborted and clients disconnect promptly.Yes, after backends stop.Clean start.
immediateSIGQUITChildren 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 -w

PostgreSQL 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 → exit

The 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() in postgres.c sets ProcDiePending; at the next CHECK_FOR_INTERRUPTS(), ProcessInterrupts() raises FATAL "terminating connection due to administrator command" and the transaction aborts during exit.
  • Checkpointer: SIGINT sets ShutdownXLOGPending (ReqShutdownXLOG()); it then calls ShutdownXLOG(), which runs CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE) (or CreateRestartPoint() on a standby), sets DB_SHUTDOWNED (or DB_SHUTDOWNED_IN_RECOVERY) in pg_control and sends PMSIGNAL_XLOG_IS_SHUTDOWN. It ignores SIGTERM and exits only on SIGUSR2.
  • Immediate: TerminateChildren(SIGQUIT); backends run quickdie() ("terminating connection due to immediate shutdown command"). After SIGKILL_CHILDREN_AFTER_SECS (5) ServerLoop() logs "issuing SIGKILL to recalcitrant children". No checkpoint, so pg_control still says DB_IN_PRODUCTION (or DB_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.pl and src/test/recovery/t/013_crash_restart.pl; pg_controldata shows "Database cluster state" after each mode.
  • Extensions clean up with before_shmem_exit(), on_shmem_exit() or on_proc_exit() callbacks (ipc.c); background workers get SIGTERM in PM_STOP_BACKENDS (default handler bgworker_die() in bgworker.c).

Parameters that shape this

log_checkpoints checkpoint_flush_after

Related topics

Server startup sequence Postmaster Checkpointer Startup process Crash recovery Write-ahead log (WAL) Process model