PostgreSQL Error Guide: 'terminating connection due to administrator command' — Fix
Fix 'terminating connection due to administrator command' in Postgres: identify pg_terminate_backend calls, restarts, failovers, and idle-session reapers killing your session, with real diagnostics.
- #postgres
- #database
- #troubleshooting
- #errors
Stuck on this Postgres error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
PostgreSQL sends this to a client whose backend was deliberately terminated by an administrator action — someone (or something) called pg_terminate_backend(), or the server is shutting down:
FATAL: terminating connection due to administrator command
Unlike a network drop, this is intentional: the server chose to end the session. The diagnostic task is to find who or what issued the termination, because the culprit ranges from a human DBA to an automated idle-session reaper to a restart or failover.
Symptoms
- A long-running query or transaction is abruptly killed mid-execution.
- Application logs show connections dropping with this exact
FATALmessage, often in bursts. - Sessions that sit idle get terminated after a fixed interval.
- Connections all drop together during a maintenance window, restart, or failover.
- A connection pool shows recurring “connection terminated” errors and reconnects.
Common Root Causes
- A DBA or script called
pg_terminate_backend(pid)to clear a stuck or blocking session. idle_session_timeout(Postgres 14+) is set and reaped an idle connection.idle_in_transaction_session_timeoutkilled a session left idle inside an open transaction (this produces a related message about idle-in-transaction, but administrator-command terminations often accompany cleanup of such sessions).- A server restart or fast shutdown (
pg_ctl stop -m fast,SIGTERMto the postmaster) terminates all backends with this message. - A failover / promotion where the old primary’s connections are severed.
- A managed-service or orchestration action — a cloud provider’s maintenance, a Kubernetes operator recycling a pod, or a pooler recycling backends.
- An automated “long-running query killer” (a cron or monitoring job) enforcing a max query duration by terminating offenders.
Diagnostic Workflow
If sessions are being killed right now, watch who’s still connected and what’s being terminated:
SELECT pid, usename, application_name, client_addr, state,
now() - query_start AS running_for, left(query, 80) AS query
FROM pg_stat_activity
ORDER BY running_for DESC NULLS LAST;
Check whether idle-timeout settings are enabled and could be the reaper:
SHOW idle_session_timeout;
SHOW idle_in_transaction_session_timeout;
Look in the server log for the termination and any nearby shutdown/restart lines:
grep -iE 'terminating connection due to administrator command|received .*shutdown|database system is shut down' \
/var/log/postgresql/postgresql-16-main.log | tail -50
If a restart or failover is suspected, check uptime and the last start time:
SELECT pg_postmaster_start_time();
Determine whether a specific automated job issues terminations — search history/cron for pg_terminate_backend:
grep -rin 'pg_terminate_backend' /etc/cron* /opt /home 2>/dev/null
Example Root Cause Analysis
An analytics team reported that their long reporting queries were dying after exactly five minutes with FATAL: terminating connection due to administrator command. The timing was suspiciously precise, which pointed away from a random restart.
Checking session timeouts showed nothing at the server level:
SHOW idle_session_timeout; -- 0 (disabled)
SHOW statement_timeout; -- 0
So it wasn’t a built-in timeout. Searching for automation revealed a cron job on the database host:
grep -rin 'pg_terminate_backend' /etc/cron*
/etc/cron.d/pg-query-guard:*/1 * * * * postgres psql -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state='active' AND now()-query_start > interval '5 minutes';"
An internal “query guard” cron ran every minute and terminated any active query running longer than five minutes — a blunt instrument installed long ago to stop runaway queries. It was killing legitimate analytics reports. The fix was to replace the crude killer with a scoped statement_timeout applied only to the OLTP application role, leaving the analytics role free to run long reports:
ALTER ROLE app_oltp SET statement_timeout = '30s';
-- analytics role keeps no statement_timeout; the cron guard was removed
Prevention Best Practices
- Enforce query duration with a per-role
statement_timeoutrather than an externalpg_terminate_backendcron — it’s precise, produces a clear “canceling statement due to statement timeout” error, and is scoped per role. - Reserve
pg_terminate_backend()for genuine incidents (a stuck or blocking backend), and log/announce when you use it so it’s not mistaken for a bug. - Set
idle_session_timeoutandidle_in_transaction_session_timeoutdeliberately, and make connection pools aware so they reconnect gracefully instead of surfacing errors. - Make applications and pools retry idempotent work on connection termination with backoff, so a restart or failover is transparent.
- Coordinate restarts/failovers and drain connections where possible so terminations are expected, not surprising.
- Audit any automated “killer” jobs — they often outlive the problem they were installed for and start harming legitimate workloads.
Quick Command Reference
-- Who is connected and what is running
SELECT pid, usename, application_name, state,
now() - query_start AS running_for, left(query, 80)
FROM pg_stat_activity ORDER BY running_for DESC NULLS LAST;
-- Are idle timeouts enabled?
SHOW idle_session_timeout;
SHOW idle_in_transaction_session_timeout;
-- When did the server last start (restart/failover check)?
SELECT pg_postmaster_start_time();
-- Prefer a scoped statement_timeout over an external killer
ALTER ROLE app_oltp SET statement_timeout = '30s';
# Find automation that terminates backends
grep -rin 'pg_terminate_backend' /etc/cron* /opt 2>/dev/null
# Confirm restart/shutdown in the log
grep -iE 'administrator command|shutdown' /var/log/postgresql/*.log | tail
Conclusion
This message means a session was killed on purpose, so the whole investigation is about identity: a human pg_terminate_backend, an idle-session timeout, a restart or failover, or — very commonly — a forgotten automated “query killer” cron that now harms legitimate work. Use pg_stat_activity, the timeout GUCs, pg_postmaster_start_time(), and a search for pg_terminate_backend to pin the source. The durable fix for duration enforcement is a scoped per-role statement_timeout rather than an external terminator, and applications should retry idempotent work so intentional terminations during maintenance and failover stay invisible to users.
Fixed it? Get 500 Postgres & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.