---
source_url: https://www.dbos.dev/blog/postgres-listen-notify-scalability
source_title: "Postgres LISTEN/NOTIFY Actually Scales"
source_site: "DBOS"
source_published_at: 2026-07-24T19:12:59.331Z
hero_image: https://cdn.prod.website-files.com/672411cbf038560468c9e68f/6a62e3a5eb32f7dd71332477_Scaling-Postgres-Listen-Notify.jpg
tags: postgresql,performance-optimization,streaming
generated_at: 2026-07-25T00:00:33.975Z
model: claude-haiku-4-5
---
# PostgreSQL LISTEN/NOTIFY のスケーラビリティを実現

TL;DR: DBOS は PostgreSQL の LISTEN/NOTIFY 機能をバッファリングとバッチ処理で最適化し、初期実装の 2.9K から 60K 書き込み/秒へ 20倍の性能向上を達成した。グローバルロックがボトルネックだったが、バッチ フラッシュ時にのみロック取得することで解決した。

DBOS は PostgreSQL の LISTEN/NOTIFY 機能を対象にスケーラビリティの最適化を行った。初期実装では、ストリームテーブルのトリガーが通知を送信するたびに NOTIFY を実行していたが、単一の PostgreSQL サーバー上でも 2.9K 書き込み/秒を超える処理ができず、ボトルネックに直面していた。

## 最適化の背景

LISTEN/NOTIFY は従来からスケーラビリティの課題を抱えていた。その根本原因は、PostgreSQL がトランザクションのコミット時に取得するグローバルな排他ロック（global exclusive lock）である。このロックはトランザクションがコミットを開始してから、ディスクへの fsync() によるフラッシュまで解放されず、通知を含むトランザクションのコミットをシリアライズする。そのため、CPU、メモリ、IOPS といった PostgreSQL リソースに顕著な消費がないにもかかわらず、スループットが制限されていた。

## 最適化ソリューション

DBOS の最適化は、NOTIFY をメモリ内でバッファリングおよびバッチ処理し、一定周期でこれらを単一のバッチ トランザクションで一括フラッシュするアプローチを採用した。この手法により、グローバルロックは個別の書き込みのたびではなく、バッファをフラッシュするときだけ取得される。

![PostgreSQL LISTEN/NOTIFY パフォーマンス比較](https://cdn.prod.website-files.com/672411cbf038560468c9e68f/6a62e413c65ce4c0d0d761a4_13f2e588.png)

最適化版の実装は、並行リーダーの存在下で最大 60K 書き込み/秒を達成し、遅延は 15–100 ミリ秒である。これは初期実装比で 20 倍の改善である。最大スループット時には PostgreSQL の CPU が完全に使用される。

![バッチ処理ベンチマーク結果](https://cdn.prod.website-files.com/672411cbf038560468c9e68f/6a63b627c7ac5219e5d501b1_Batched-Notifications-Benchmark.png)

## PostgreSQL 19 のパッチとの関係

PostgreSQL 19 のリリースに向けた本体パッチは、多数の通知チャネルと特定チャネル購読リスナーのシナリオを最適化するが、グローバルロック自体は除去していない。通知が未配信となった場合には、リーダーが定期的にデータベースをポーリングする仕組みが機能する。PostgreSQL は通知をトランザクション コミット順で送信することを保証している。

## 筆者の見立て

- LISTEN/NOTIFY がスケールしない場合、それは残念なことである。なぜなら、これは強力なツールだからである。（意見）
- グローバルロックは観測されたスケーラビリティの低さと PostgreSQL リソース消費の乏しさを説明している。（解釈）
- 通知自体はストリームの信頼できる情報源ではなく、多くの LISTEN/NOTIFY アプリケーションでは、リーダーがデータベース テーブルをチェックするためのシグナルに過ぎない。（解釈）
- NOTIFY をバッファリングおよびバッチ処理することで、個別の書き込みのたびではなく、バッファをフラッシュするときだけグローバルロックを取得する必要があるため、ボトルネックを回避できる。（解釈）

*この記事は元記事の事実のみに基づいて自動生成されました。*

## 出典

DBOS「Postgres LISTEN/NOTIFY Actually Scales」https://www.dbos.dev/blog/postgres-listen-notify-scalability (PostgreSQL パッチについてのオンライン議論による)
