できない.dev

PostgreSQL で「sorry, too many clients already」が出て接続できない

FATAL: sorry, too many clients already は同時接続数が max_connections に達したサイン。
接続リークを止めるかコネクションプーラを挟むのが本筋で、max_connections の引き上げは最後の手段。

公開: 更新:

実行例あり(2026-09-24 に実環境で検証)

要約

FATAL: sorry, too many clients already は、同時接続数がサーバーの max_connections 上限に達して新規接続を受け付けられない状態。
多くは接続リークか、プーラ無しでの接続乱立が原因。
まず溜まった接続を調べてリークを止め、恒常的に多い場合は PgBouncer などのプーラを挟む。max_connections の引き上げは共有メモリを増やすため最後の手段。

実行例

max_connections を 8 に絞った postgres:17 のサーバーで、接続を握ったままのセッションを並べてから新しく接続すると sorry, too many clients already で拒否された。
セッションが終われば接続は通り、ALTER SYSTEM で 40 に上げた値は再起動するまで SHOW max_connections に反映されない。

$ psql -U postgres -d postgres -f show_max.sql
max_connections 
-----------------
 8
(1 row)
$ psql -U postgres -d postgres -f ping.sql
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  sorry, too many clients already
$ echo $?
2
$ psql -U postgres -d postgres -f ping.sql
ok 
----
  1
(1 row)
$ echo $?
0
$ psql -U postgres -d postgres -f activity.sql
datname  | usename  | state  | count 
----------+----------+--------+-------
 postgres | postgres | active |     6
(1 row)
$ psql -U postgres -d postgres -a -f raise.sql
ALTER SYSTEM SET max_connections = 40;
ALTER SYSTEM
$ psql -U postgres -d postgres -f show_max.sql
max_connections 
-----------------
 8
(1 row)
$ psql -U postgres -d postgres -f show_max.sql
max_connections 
-----------------
 40
(1 row)
$ psql -U postgres -d postgres -f ping.sql
ok 
----
  1
(1 row)
$ echo $?
0

— 2026-09-24 時点の出力

検証環境

検証日
実行環境
postgres:17Debian GNU/Linux 13 (trixie)

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

よくある原因

  1. 上限到達: 既定の max_connections = 100 に対し、アプリのプールや並列ジョブの合計がそれを超えている。
  2. 接続リーク: 取得した接続を返していない、例外時に close し損ねているなどで未使用接続が居座る。
  3. 多インスタンス: サーバーレス関数やコンテナの水平スケールで、各インスタンスが独立に接続プールを持つと総数が膨らむ。
  4. プーラ不在: リクエストごとに新規接続して即切る設計だと、ピークで瞬間的に上限を超える。

現状確認

今どれだけ接続があるか、誰が握っているかを見る。

SELECT count(*) FROM pg_stat_activity;
SELECT datname, usename, state, count(*)
FROM pg_stat_activity
GROUP BY datname, usename, state
ORDER BY count DESC;

解決策

1. コネクションプーラを挟む

PgBouncer を前段に置き、アプリは少数の物理接続を共有する。
サーバーレスや高並列ではこれが定石。

2. アプリ側のプールを適正化する

物理接続は「max_connections ÷ インスタンス数」を超えない範囲に抑え、確実に解放する。

# 例: max_connections=100、4 インスタンスなら 1 インスタンス 20 程度に
pool size <= 20

3. 必要なら max_connections を上げる

postgresql.conf で引き上げる。max_connections は再起動が必要で、値に比例して共有メモリを確保する(Connections and Authentication(新しいタブで開く))。

max_connections = 200

この記事は役立ちましたか?