PROD欧州主権の BaaS プラットフォームダッシュボードを開く →

パフォーマンス · 11 分読み取り

PgBouncer vs Supavisor vs PgCat: どの Postgres プーラーですか?

Affane Daylami · Fondateur · 2026年6月9日

ブログに戻る

PgBouncer、Supavisor、および PgCat はすべて Postgres 接続を共有しますが、同じ問題には対処しません。 PgBouncer は歴史的な標準であり、軽量で C 言語であり、CloudNativePG を介して Kubernetes エコシステムにネイティブに統合されています。 Supervisor は、データベースごとに 1 つのプロセスではなく、単一のサービスの背後に数千のデータベースを保持するという特定のニーズに合わせて Supabase によって構築されました。 Rust で書かれた PgCat は、レプリカ間のシャーディングと負荷分散の古典的なプーリングを追加します。 Aurabase では、データプレーンのトラフィックはトランザクション モードで PgBouncer を通過します。これはリポジトリ コードに直接示されています。Helm チャート、CNPG Pooler リソース、ローカル k3d 構成はすべて同じ選択に収束します。

この英語のテキストはフランス語のオリジナルから自動的に生成されたもので、まだレビューされていません。
このページは自動翻訳されました。英語版が正式です。

この記事では、言語、プーリング モード、シングル テナント モデルまたはマルチテナント モデル、純粋なプーリングを超えた機能という 3 つのプーラーのアーキテクチャを比較します。 Tembo と PkgPulse はこれら 3 つのツールの数値比較を公開していますが、私たち自身ではそれらの測定値を再現していません。 ベンチマーク方法論で詳述されているベンチマークに関する当社の編集上の立場は、当社自身が検証していない数値を決して再公開しないことです。代わりにここでは、各ツールの実際のアーキテクチャと、Aurabase が実際に Postgres トラフィックをルーティングする方法を、ソースコードのセクションごとに検証して説明します。

必需品
  • PgBouncer (C) は依然として最も実績のあるプーラーであり、Kubernetes との統合に最適です。CloudNativePG は Poolerリソースを PgBouncer (C) に直接依存しています。
  • Supavisor (Elixir、Supabase プロジェクト) は、データベースごとに 1 つのプーラーではなく、同じサービスから数千のデータベースを提供するという別の問題をターゲットにしています。
  • PgCat (Rust) は、アプリケーションのシャーディング、レプリカ間の負荷分散、および RAW プーリングへの自動フェイルオーバーを追加します。
  • Aurabase リポジトリには、共有フリートの共有デプロイメントと、専用テナントごとに CloudNativePG によって管理される Pooler リソースの 2 つのレベルで使用される PgBouncer が表示されます。どちらもトランザクション モードで動作します。
  • PostgREST とaura-db 管理プールは、プーラーを経由せずに、自主的に Postgres に直接接続されたままになります。トランザクション プーリングにより、スキーマの再ロードとセッション ロックが解除されます。
#
パノラマ

3 つのプーラー、3 つの哲学

PgBouncer は最小化、Supervisor はマルチテナント規模でプールし、PgCat は RAW プーリングにネットワーク機能を追加します。 3 つはいずれも他の 2 つの直接の代替品ではありませんが、同じページで用語ごとに比較されることがよくあります。

言語Cエリクサー(ビーム)さび
プーリングモードセッション、トランザクション、ステートメントセッション、トランザクションセッション、トランザクション、ステートメント
テナントモデルインスタンスごとに 1 つのターゲット クラスター、シングル テナントになるように設計ネイティブ マルチテナント: 多くのデータベース用のサービスターゲットクラスター、パーティションキーによるシャーディング
プーリングを超えて追加機能はなく、意図的に最小限に抑えられています管理HTTP API、動的テナント登録レプリカ間のシャーディング、負荷分散、フェイルオーバー
ネイティブ Kubernetes の統合はい: CloudNativePG リソース プーラー現在までネイティブに文書化されていない現在までネイティブに文書化されていない
起源Postgres プーリングの歴史的な標準Supabase が独自のマルチテナント クラウド用に構築Instacart で誕生し、現在は PostgresML によって維持されています

列は順に、PgBouncer、Supervisor、PgCat です。各プロジェクトの公式ファイリングによるアーキテクチャの特徴は、展開しているバージョンで確認する必要があり、この点でエコシステムは急速に進化しています。

#
Pgバウンサー

軽量で Kubernetes に統合された歴史的な標準

PgBouncer は Postgres 接続をプールするという 1 つのことだけを行い、追加の機能はありません。この意図的に狭い範囲が、その寿命の長さと、本番環境のほとんどの Postgres スタックの基本構成要素としての採用の主な説明になります。

Three pooling modes are available. Session mode opens one server connection per client connection, the most permissive. Transaction mode reuses a server connection between several clients, released at each end of a transaction. Statement mode goes even further, and is rarely used in production. It is the transaction mode that brings the real pooling gain, but it imposes strict rules. Any session state (SETvariables, advisory locks, LISTEN/NOTIFY) does not survive beyond a transaction. We detail these rules and their pitfalls in our dedicated article on the transaction pooling mode of PgBouncer.

歴史的に単一プロセスである PgBouncer インスタンスは、デフォルトで単一の CPU コアを使用します。同じポートの背後で複数のインスタンスを実行する ( SO_REUSEPORT経由) は、プロジェクトの最近の進化であり、初期の設計機能ではありません。認証側では、PgBouncer は構成可能な auth_queryをサポートしています。これは、ロールのパスワードを動的に解決するために各接続で実行される SQL 関数です。このメカニズムにより、各ユーザーを事前にリストした静的ファイルに依存することがなくなります。 Aurabase がプロジェクトごとの役割に使用するのは、まさにこのメカニズムです (セクション 05)。

アストゥチェ

PgBouncer は、CloudNativePG が Poolerリソースの背後にネイティブにデプロイするプーラーです。 CloudNativePG オペレーターによって管理される Postgres クラスターでは、管理対象プーラーをアクティブ化すると、実際には、手動で構成せずに PgBouncer をアクティブ化することになります。

#
スーパーバイザー

Supabase のクラウドネイティブ マルチテナント プーラー

Supervisor は、PgBouncer がこの規模で解決するように設計されていなかった問題に対処します。これには、データベースごとに 1 つのプーラー インスタンスではなく、単一のサービスから非常に多数の異なるテナント データベースを提供することが含まれます。 Elixir で書かれ、Erlang 仮想マシン (BEAM) 上で実行されるこのプロジェクトは、Supabase によってオープン ソースで独自の GitHub リポジトリ上で開発および保守されています。

ネイティブ マルチテナント モデルが実際の構造的な違いです。従来の PgBouncer フリートではターゲット ベースごとに 1 つのプロセス (または一連の専用接続) が必要ですが、Supervisor の動作は異なります。 HTTP 管理インターフェイスを介してテナントを動的に登録し、サービスを再起動せずに各受信接続を正しいデータベースにルーティングします。 Supabase は、まさにこの理由から、独自のクラウド プロジェクトを PgBouncer から Supavisor に移行しました。従来のプーリング クラスター (データベースごとに 1 つ) は、数十万のプロジェクトをホストするマルチテナント クラウドには拡張できません。

このアーキテクチャ上の選択には、文書化された欠点があります。高度なケースにおける PgBouncer との機能同等性は、プロジェクトの開始後に安定するまでに時間がかかりました。 2 つの例: LISTEN/NOTIFYの特定の動作、およびトランザクション モードでのプリペアド ステートメントの詳細な管理。アプリケーションがこれらの特定の動作に依存している場合は、移行前にバージョンを確認してください。

#
PgCat

Rust の部外者: ネイティブ シャーディングとロード バランシング

PgCat は、Rust で書かれた PgBouncer の代替として明示的に位置付けられています。 PgBouncer も Supervisor もネイティブに埋め込まれていないネットワーク機能をクラシック プーリングに追加します。特に、パーティション キーによるアプリケーション シャーディング、リード レプリカ間の負荷分散、障害が発生したレプリカからの自動フェイルオーバーの 3 つです。このプロジェクトは Instacart で誕生し、現在では PostgresML によって引き継がれ、維持されています。

具体的には、PgCat は、複数の Postgres インスタンス間のルーティングのための接続プーラーとアプリケーション プロキシという 2 つの異なる層が通常占める役割を果たします。すでに手動でデータをシャーディングしていたチームは、PgCat を使用してコードを簡素化できます。内部で開発されたレプリカ間で読み取りを分散するロジックについても同様です。専用のネットワーク層がそれを直接置き換えます。

逆の妥協案も存在します。PgCat は若いプロジェクトであり、ドキュメントと制作フィードバックのエコシステムが PgBouncer よりもはるかに小さいです。シャーディング機能とフェイルオーバー機能を採用するということは、プーリング容量だけでなく、この特定のコンポーネントの成熟度に依存することに同意することも意味します。

#
コードをチェックインしました

Aurabase コードが示すもの: トランザクション プーリングがすべてを壊す場合を除いて、どこでも PgBouncer

Aurabase リポジトリは、PgBouncer を 2 つの別々の層に、両方ともトランザクション モードでデプロイします。共有フリートの場合、Helm チャートは共有データ プレーンの前に専用の PgBouncer デプロイメントを定義します (deploy/helm/aurabase/templates/infra/pgbouncer.yaml、イメージ edoburu/pgbouncer)。専用インスタンス上のテナントの場合、プロビジョナーは CloudNativePG によってネイティブに管理されるリソース Pooler (deploy/cnpg/tenant-pooler.yaml、 k8s_tenant.rsによってレンダリングされます) を生成します。どちらも Supervisor または PgCat を使用しません。このコードには、この選択に先立つ明示的な比較が記載されていません。一方で、PgBouncer がネイティブ プーリング ブリックであるという事実と一致して、CloudNativePG エコシステムとの緊密な既に運用可能な統合が示されています。

トランザクション
プーリングモード
専用テナントによる共有フリートとプーラー
1000
最大顧客接続数
同時顧客上限、Helm チャートのデフォルト
80
デフォルトのプールサイズ
(ベース、ロール) によるサーバー接続、デフォルトの Helm チャート

ただし、すべてがプーラーを通過するわけではなく、これはコード自体に文書化された意図的な選択です。 PostgREST は PgBouncer 経由ではなく、Postgres にライブ接続されたままになります。 Helm チャートのコメントでは、その理由が明示的に示されています。トランザクション プーリングにより、pgrstチャネルの LISTEN に依存するスキーマのリロードが中断されるからです。このメカニズムは、クライアント間のリサイクルされたサーバー接続と互換性がありません。aura-db 管理プール (スキーマ、DDL、セッション勧告ロック) も、同じ基本的な理由で、直接接続されたままになります。非トランザクション スコープの SET search_path およびセッション ロックは、トランザクション モード プーラーでは存続しません。

deploy/helm/aurabase/templates/infra/pgbouncer.yaml (extrait commenté)yaml
# データプレーン aura-db: PgBouncer 経由、すべてがトランザクション スコープ (SET LOCAL)
DATABASE_URL: postgresql://aura_authenticator:...@pgbouncer:5432/aura_db_master

# プール管理者 (DDL、イントロスペクション): Postgres に直接、PgBouncer ではありません
# SET search_path 非ローカル + セッション ロックによりトランザクション プーリングが中断される
ADMIN_DATABASE_URL: postgresql://aura:...@postgres:5432/aura_db_master

認証は、セクション 02: AUTH_QUERY: SELECT * FROM pgbouncer.user_lookup($1)で説明されている auth_query パターンに従い、静的な userlist.txt ファイルは使用されません。これにより、プロジェクトごとに動的に作成されたロール (project_<uuid>_authenticator) が、新しいプロジェクトごとにプーラーを再デプロイすることなく PgBouncer 経由で認証できるようになります。

この記事の執筆中に得られた運用上の教訓

ローカル Kubernetes マニフェスト内の PgBouncer healthcheck コメントには、すでに修正されている実際のバグが記載されています。 PgBouncer に対して実行される pg_isready はプロキシ ハンドシェイクのみを検証し、中継する Postgres バックエンドへの実際の接続は検証しません。 PgBouncer は、バックエンドが停止している場合でも「接続の受け入れ」に応答し、リクエストをキューに入れます。破壊的テスト中に観察された結果: Postgres に到達できない間、サービスは 5 サイクル連続して healthy のままでした。この修正により、チェックが、プーラーを介してバックエンドに至る真のエンドツーエンドの psql リクエストに置き換えられます。同じテストを再実行した修正後の結果: unhealthy が 7 サイクル、約 35 秒で検出されました。

最後に細かいことですが、明らかになります。Helm チャートはデフォルトで edoburu/pgbouncer:v1.24.1-p1 を固定しますが、ローカル k3d ベンチは v1.25.2-p0を使用します。これはアーキテクチャ上の選択ではなく、2 つの環境間でのバージョン同期がわずかに欠如しているだけです。このような詳細は、コード レビューの方がブログ投稿よりも早く把握できます。飾り立てるのではなく、ありのままを記録します。このプーラーが提供するスキーマ分割の詳細については、マルチテナント RLS 分離に関する記事を参照してください。

#
決定

3つの中から選ぶ方法

次の場合は PgBouncer を選択してください…

  • 一般的に CloudNativePG または Kubernetes によって管理される Postgres クラスター
  • 最も実績があり、十分に文書化されたプーラーが必要です
  • プーラー インスタンスごとのターゲット ベースは最適です

次の場合はスーパーバイザーを選択してください…

  • 同じサービスの背後にある数百または数千の基地
  • 再デプロイせずに API 経由でテナントを動的に登録する必要がある
  • すでに Supabase エコシステムに参加している、またはそれに依存する意思がある

次の場合は PgCat を選択してください…

  • アプリケーション共有はすでに導入されているか、プーラー レベルで計画されています
  • 別個のアプリケーション層を必要としない負荷分散およびフェイルオーバーレプリカ
  • PgBouncer ほどドキュメントが少なく、若いプロジェクトに慣れている

どのプーラーを選択しても、Postgres 自体のサイジングが置き換えられるわけではありません。プール サイズとサーバー max_connections は、順番に考えるのではなく、一緒に考える必要があります。低すぎる max_connections の前に十分なプールがあると、彩度が 1 つのレベルから別のレベルに移動するだけです。 の max_connections の調整に関するガイド では、プールのサイズを設定する前に適用するサイジング公式について詳しく説明しています。

#
よくある質問

最もよく聞かれること

PgBouncer と Pgpool-II の違いは何ですか?+
Pgpool-II は、レプリカ間の負荷分散、メモリ内クエリ キャッシュ、アプリケーション レプリケーションなど、接続プーリングを超えています。 PgBouncer はプール接続という 1 つのことだけを行います。これは、より広範なプラットフォームに置き換えられるのではなく、必要に応じて他のツールで補完される基本的な構成要素としてそれが選択されることが多い理由の一部を説明しています。
PgBouncer を Supabase で使用できますか?+
歴史的にはそうです: Supabase は、Supavisor を開発する前に PgBouncer に依存していました。どちらも、接続コンテキスト (IPv4 直接、プーラー トランザクション、プーラー セッション) に従って公式ドキュメントに記載されています。この正確な点は、プロジェクトを構成するときに確認するために急速に進化します。
PgCat はプリペアド ステートメントをトランザクション モードで管理しますか?+
バージョン 1.21 以降、PgBouncer はトランザクション モードでプロトコルの準備済みステートメントをオンザフライで追跡および再準備します。この動作は Aurabase Helm チャート自体に文書化されています。 PgCat も同様のサーバー側サポートを主張しています。実際の負荷条件でどちらかを測定したことはないため、決定的な選択基準とする前に、ご自身のトラフィックを確認してください。
Supervisor はオープンソースですか?+
はい、リポジトリは GitHub (supabase/supavisor) で公開されています。これは、Elixir で書かれた Supabase の Postgres コアとは異なるプロジェクトであり、後から適応するのではなく、最初からマルチテナント向けに設計されています。
#
要約すると

万能のプーラーはなく、テナントに適したプーラーのみが存在します

PgBouncer、Supavisor、および PgCat は、同じツールの 3 つのバージョンではなく、同じ問題の 3 つのバリエーションを解決します。プラットフォームがすでに Kubernetes と CloudNativePG に依存している場合、または単に最も文書化されたプーラーが必要な場合は、PgBouncer が最も安全な選択肢となります。スーパーバイザーは、同じサービスからサービスを提供する一定数のベースを超えて関連するようになります。ネットワーク レベルでのシャーディングとレプリカ フェイルオーバーを見逃している場合は、若いプロジェクトの成熟度を受け入れるのであれば、PgCat は回り道をする価値があります。

Aurabase コードは、中立ではなく一貫した選択肢を示しています。トランザクション モードの PgBouncer は、共有フリートと専用テナントごとの CNPG プーラーの 2 つのレベルです。 PostgREST とスキーマ管理の 2 つの例外が文書化されています。このプロジェクトのサイロ化を紙の上ではなく実際に確認したい場合は、パフォーマンス ページに関連する測定方法が記載されています。

導入の準備はできていますか?

5 分でバックエンドが完成します。

クレジット カードは不要 · 500 MB 無料 · 50,000 MAU