【PostgreSQL】max_connections の上限に達した際のエラー "too many clients already" を再現してみた

【PostgreSQL】max_connections の上限に達した際のエラー "too many clients already" を再現してみた

PostgreSQL の同時接続数上限「max_connections」に達した際のエラー挙動を実際に再現し、pg_stat_activity での状況確認と pg_terminate_backend による対処方法を検証してみました。
2026.08.08

PostgreSQL では max_connections で同時接続数の上限が決まっており、
これを超えると新規接続が FATAL: sorry, too many clients already エラーで拒否されます。

今回はこの状況を再現してみました。実際にやることは以下です。

  1. max_connections の値を変更
  2. 接続数を上限まで埋める
  3. pg_stat_activity で状況確認
  4. 新規接続時にエラーが発生することを確認
  5. pg_terminate_backend で特定の接続を終了
  6. 新規接続ができるようになることを確認

(前提準備) PostgreSQL インストール

検証のための実行環境は EC2(AL2023)にインストールした PostgreSQL を使用しました。
EC2 に PostgreSQL をインストールする手順としては下記をご参照ください。

https://dev.classmethod.jp/articles/installing-postgresql-on-ec2-al2023/

PostgreSQL 17.10 を利用し、検証していきます。

[ec2-user@ip-xx-xx-xx-xx ~]$ sudo -u postgres psql
psql (17.10)
Type "help" for help.

postgres=# SELECT version();
                                                    version                                                    
---------------------------------------------------------------------------------------------------------------
 PostgreSQL 17.10 on x86_64-amazon-linux-gnu, compiled by gcc (GCC) 11.5.0 20240719 (Red Hat 11.5.0-5), 64-bit
(1 row)

現状確認

まず pg_stat_activity ビューを用いて、検証前の状態を確認します。

pg_stat_activityはサーバプロセス毎に、そのプロセスの現在の活動に関連する情報を表示する1行を持ちます。

27.2.3. pg_stat_activity

下記より、現在は 6 プロセス動いている状態です。
また、backend_typeclient backend となるプロセスは 1 件のみであることが分かります。これがクライアント接続になります。
(この client backend プロセスが max_connections の上限に影響します。その他の autovacuum launchercheckpointer などは PostgreSQL 内部プロセスであり、影響しません。)

ターミナルA: pg_stat_activity ビューの確認
postgres=# SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity;
 pid  | usename  | state  |         backend_type         |          query_start          
------+----------+--------+------------------------------+-------------------------------
 2834 | postgres | active | client backend               | 2026-08-05 00:38:07.754132+00
 2827 |          |        | autovacuum launcher          | 
 2828 | postgres |        | logical replication launcher | 
 2823 |          |        | checkpointer                 | 
 2824 |          |        | background writer            | 
 2826 |          |        | walwriter                    | 
(6 rows)
ターミナルA: backend_type が client backend のプロセス数を確認
postgres=# SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend';
 count 
-------
     1
(1 row)
クライアントから接続を増やすと `client backend` が増える

ちなみにターミナル B から以下のように新規接続をしてみます。

ターミナルB
$ sudo -u postgres psql -d postgres
psql (17.10)
Type "help" for help.

postgres=# 

その後、ターミナル A で改めて pg_stat_activity を確認すると、下記のように client backend が増えます。

ターミナルA
postgres=# SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity;
 pid  | usename  | state  |         backend_type         |          query_start          
------+----------+--------+------------------------------+-------------------------------
 2834 | postgres | active | client backend               | 2026-08-05 01:05:40.604094+00
 3635 | postgres | idle   | client backend               | 
 2827 |          |        | autovacuum launcher          | 
 2828 | postgres |        | logical replication launcher | 
 2823 |          |        | checkpointer                 | 
 2824 |          |        | background writer            | 
 2826 |          |        | walwriter                    | 
(7 rows)

以上より、backend_type = client backend はクライアントからの接続に対応していることが確認できました。

max_connections の変更

検証のため、max_connections の値をデフォルトの 100 から 10 に書き換えます。

max_connections (integer)
データベースサーバに同時接続する最大数を決定します。 デフォルトは典型的に100接続ですが、カーネルの設定が(initdbの過程で)それをサポートしていない場合、もっと少なくなることがあります。 このパラメータはサーバ起動時のみに設定可能です。

19.3. 接続と認証

ターミナルA
-- デフォルトでは 100 接続
postgres=# SHOW max_connections;
 max_connections 
-----------------
 100
(1 row)

postgres=# exit;

postgresql.conf ファイルを編集し、max_connections の値を 10 に書き換えます。

ターミナルA
$ sudo vi /var/lib/pgsql/data/postgresql.conf

# vim の使い方メモ
# 1. /max_connections と入力してEnter → 該当行にジャンプ
# 2. その行で数値を書き換え
# 3. :wq と入力してEnter → 保存して終了

# 以下のように書き換え
max_connections = 10

# 10接続になったかの確認
$ sudo cat /var/lib/pgsql/data/postgresql.conf | grep 'max_connections'
max_connections = 10                    # (change requires restart)

パラメータを反映させるために PostgreSQL サーバーを再起動します。

ターミナルA
$ sudo systemctl restart postgresql

再起動後、改めて PostgreSQL サーバーに接続し max_connections が 10 になっていれば OK です。

ターミナルA
postgres=# SHOW max_connections;
 max_connections 
-----------------
 10
(1 row)

10接続した時にどうなるか確認する

max_connections=10 の状態で、実際に接続を埋めていきます。
検証前は以下の通り、client backend は自分が接続する 1 接続のみの状態です。

ターミナルA
postgres=# SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity;
 pid  | usename  | state  |         backend_type         |         query_start          
------+----------+--------+------------------------------+------------------------------
 5347 | postgres | active | client backend               | 2026-08-05 01:32:22.39425+00
 2827 |          |        | autovacuum launcher          | 
 2828 | postgres |        | logical replication launcher | 
 2823 |          |        | checkpointer                 | 
 2824 |          |        | background writer            | 
 2826 |          |        | walwriter                    | 
(6 rows)

postgres=# SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend';
 count 
-------
     1
(1 row)

続いて、ターミナル B で 9 本の接続をバックグラウンドで一括生成します。
BEGIN でトランザクションを開始した状態のまま pg_sleep(600) を実行し、接続を 600 秒間占有させます。
末尾の & によって各コマンドをバックグラウンドで実行しているため、9 本の接続をほぼ同時に作ることができます。

ターミナルB
$ for i in $(seq 1 9); do
  sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
done

# 実行結果
[1] 5410
[2] 5411
[3] 5412
[4] 5413
[5] 5414
[6] 5415
[7] 5416
[8] 5417
[9] 5418

# jobs コマンドで確認 -> 9 プロセスあり
$ jobs
[1]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[2]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[3]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[4]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[5]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[6]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[7]   Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[8]-  Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &
[9]+  Running                 sudo -u postgres psql -d postgres -c "BEGIN; SELECT pg_sleep(600);" &

上記実行後、ターミナルA から pg_stat_activity を確認します。
下記の通り、接続が満杯(client backend が 10 本)になりました。

ターミナルA
postgres=# SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity;
 pid  | usename  | state  |         backend_type         |          query_start          
------+----------+--------+------------------------------+-------------------------------
 5483 | postgres | active | client backend               | 2026-08-05 01:34:38.423142+00
 5457 | postgres | active | client backend               | 2026-08-05 01:34:38.373395+00
 5347 | postgres | active | client backend               | 2026-08-05 01:35:03.564196+00
 5445 | postgres | active | client backend               | 2026-08-05 01:34:38.341128+00
 5450 | postgres | active | client backend               | 2026-08-05 01:34:38.355533+00
 5463 | postgres | active | client backend               | 2026-08-05 01:34:38.388967+00
 5480 | postgres | active | client backend               | 2026-08-05 01:34:38.410182+00
 5481 | postgres | active | client backend               | 2026-08-05 01:34:38.417854+00
 5462 | postgres | active | client backend               | 2026-08-05 01:34:38.388401+00
 5477 | postgres | active | client backend               | 2026-08-05 01:34:38.419452+00
 2827 |          |        | autovacuum launcher          | 
 2828 | postgres |        | logical replication launcher | 
 2823 |          |        | checkpointer                 | 
 2824 |          |        | background writer            | 
 2826 |          |        | walwriter                    | 
(15 rows)

postgres=# SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend';
 count 
-------
    10
(1 row)

この状態で、ターミナルBからさらに接続を試みてみます。
すると下記のエラーとなり、接続ができません。

ターミナルB
$ sudo -u postgres psql -d postgres
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  sorry, too many clients already

pg_terminate_backend 関数を用いて client backend プロセスを 1 つ削除し、接続を 9 つにします。

ターミナルA
postgres=# SELECT pg_terminate_backend(5445);
 pg_terminate_backend 
----------------------
 t
(1 row)

postgres=# SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend';
 count 
-------
     9
(1 row)

pg_terminate_backend ( pid integer, timeout bigint DEFAULT 0 ) → boolean
バックエンドが指定したプロセスIDを持つセッションを終了させます。

9.28. システム管理関数

再度、ターミナル B から新規接続を試みます。下記の通り、今度はエラーなく接続ができました。

ターミナルB
$ sudo -u postgres psql -d postgres
psql (17.10)
Type "help" for help.

postgres=# 

ターミナル A から確認した結果 client backend の数も 10 に戻ったことがわかります。

ターミナルA
postgres=# SELECT pid, usename, state, backend_type, query_start FROM pg_stat_activity;
 pid  | usename  | state  |         backend_type         |          query_start          
------+----------+--------+------------------------------+-------------------------------
 5483 | postgres | active | client backend               | 2026-08-05 01:34:38.423142+00
 5457 | postgres | active | client backend               | 2026-08-05 01:34:38.373395+00
 5347 | postgres | active | client backend               | 2026-08-05 01:42:32.214567+00
 5638 | postgres | idle   | client backend               | 
 5450 | postgres | active | client backend               | 2026-08-05 01:34:38.355533+00
 5463 | postgres | active | client backend               | 2026-08-05 01:34:38.388967+00
 5480 | postgres | active | client backend               | 2026-08-05 01:34:38.410182+00
 5481 | postgres | active | client backend               | 2026-08-05 01:34:38.417854+00
 5462 | postgres | active | client backend               | 2026-08-05 01:34:38.388401+00
 5477 | postgres | active | client backend               | 2026-08-05 01:34:38.419452+00
 2827 |          |        | autovacuum launcher          | 
 2828 | postgres |        | logical replication launcher | 
 2823 |          |        | checkpointer                 | 
 2824 |          |        | background writer            | 
 2826 |          |        | walwriter                    | 
(15 rows)

postgres=# SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'client backend';
 count 
-------
    10
(1 row)

終わりに

今回は接続数の上限に達した際の挙動と、その対処方法を検証してみました。
検証してみて以下が把握できました。

  • max_connections の上限に達すると、新規接続は FATAL: sorry, too many clients already エラーで拒否される
  • pg_stat_activitybackend_type = client backend の件数を確認することで、現在の接続数を把握できる
  • 原因となっている接続は pg_terminate_backend で強制終了させることができ、これにより新規接続を受け入れられる状態に復旧できる

実務でも「DBに繋がらない」という相談を受けた際、まず pg_stat_activity で状況を確認するのが第一歩になります。

本記事がどなたかのお役に立てば幸いです。

参考情報

https://dev.classmethod.jp/articles/installing-postgresql-on-ec2-al2023/
https://www.postgresql.jp/document/17/html/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW
https://www.postgresql.jp/document/17/html/runtime-config-connection.html
https://www.postgresql.jp/document/17/html/functions-admin.html

この記事をシェアする

関連記事