Microsoft pg_durable: PostgreSQL向けのインデータベース・デューラブル・エグゼキューション

Microsoftは、データベース内に直接デューラブル・エグゼキューション(永続的な実行)をもたらすために設計されたPostgreSQL拡張機能であるpg_durableをオープンソースとして公開しました。開発者がSQLを使用して、長時間実行されるフォールトトレラントなワークフローを定義できるようにすることで、pg_durableは、バックグラウンド作業を管理するための外部オーケストレーター、個別のキューシステム、または複雑なステータス追跡テーブルの必要性を排除します。

PostgreSQL内部でのデューラブル・エグゼキューション

pg_durableは、PostgreSQLが実行およびチェックポイントを作成するSQLベースの関数グラフの作成を可能にします。データベースがクラッシュしたり、再起動したり、特定のステップが失敗したりした場合、実行はプロセスの完全な再起動を必要とするのではなく、最後のデューラブル・チェックポイントから再開されます。このアプローチは、オーケストレーション・ロジック(リトライ状態、進捗追跡、およびチェックポイント作成)をアプリケーション層からデータベース自体へと移動させます。

コア機能

  • SQL-Native Definition: ワークフローは、~>|=> といった合成可能なオペレーターを使用して定義されます。
  • Zero Infrastructure: システムはPostgreSQL拡張機能として動作するため、Redis、Temporal、またはAirflowのような外部サービスを要件としません。
  • Database-Aware Primitives: この拡張機能は、スケジューリング、条件付きロジック、および並列実行のためのファーストクラスのサポートを提供します。
  • Fault Tolerance: 関数の状態はPostgreSQLに永続化されるため、クラッシュやフェイルオーバーが発生しても生存が保証されます。

ワークフローの例

ユーザーは、離散的なステップでデータを処理するためのデューラブル関数を開始できます。例えば、以下のSQLは、未処理のドキュメントを取得してバッチで更新するプロセスを開始します。

SELECT df.start(
    'SELECT id FROM documents WHERE processed = false LIMIT 100' |=> 'batch'
    ~> 'UPDATE documents SET processed = true WHERE id = ANY($batch)'
);

ターゲットとなるワークロードとユースケース

pg_durableは、レイテンシとアーキテクチャの複雑さを軽減するために、計算処理をデータに近づける必要があるワークロードに最適化されています。

推奨されるユースケース

  • Vector Embedding Pipelines: データのチャンク化、埋め込みAPIの呼び出し、および結果をpgvectorへのアップサート。
  • Ingest Pipelines: 大規模なデータのバッチをステージング、重複排除、変換、および公開。
  • Scheduled Maintenance: データベースの肥大化(bloat)の検出、管理者への通知、および承認後のクリーンアップ作業の実行。
  • Fan-out Aggregation: 独立したクエリを並列に実行し、結果を結合。
  • External API Workflows: 埋め込み、分類、およびWebhookスタイルの呼び出しをSQLから直接処理。

pg_durableを使用すべきでない場合

  • Simple Queries: ジョブが単一のINSERT ... SELECTまたは標準的なSQLステートメントである場合、pg_durableは不要です。
  • Low Latency: ミリ秒未満の同期的なリクエスト処理を目的としていません。
  • External-Heavy Workflows: ワークフローが多くの異種システムにまたがり、主にPostgreSQLの外部で動作する場合、汎用オーケストレーターの方が適切です。
  • Complex Application Logic: SQLのステップ、分岐、ループ、またはHTTP呼び出しにマッピングできないロジックは、アプリケーション層に留めるべきです。

技術アーキテクチャ

pgrxで構築されたpg_durableは、サーバー内で完全に動作するPostgreSQL拡張機能です。関数グラフを構築するためのSQL DSLと、実行を管理するバックグラウンドワーカーで構成されています。

基盤となるフレームワーク

  • duroxide: 決定論的なリプレイ、チェックポイント、およびタイマーを含む、オーケストレーション・ランタイムを提供するためのデューラブル・タスク・フレームワークです。
  • duroxide-pg: duroxideのためのPostgreSQLバックエンドのステート・プロバイダーであり、ランタイム状態(インスタンス、履歴、およびワークキュー)を専用のduroxide.*スキーマに永続化します。

データ構成

  • df.* スキーマ: DSLグラフ、ノード、インスタンス、および変数を格納します。

  • duroxide.* スキーマ: duroxide-pgプロバイダーによって所有される内部ランタイム状態を格納します。

インストールとデプロイメント

pg_durableは現在Preview段階にあります。タグ付けされたリリースでは、amd64上のPostgreSQL 17および18用のDebianパッケージが提供されています。

セットアップ・プロセス

  1. パッケージをPostgreSQLのインストールディレクトリにインストールします。
  2. shared_preload_librariespg_durableを追加します。
  3. PostgreSQLを再起動します。
  4. 拡張機能を生成します: CREATE EXTENSION pg_durable;

セキュリティとマルチテナンシー

アクセスは明示的な権限付与(grants)を通じて管理されます。管理者はSELECT df.grant_usage('app_role');を使用して、アプリケーション・ロールにアクセス権を付与する必要があります。行レベルセキュリティ(RLS)により、ユーザーは自身のデューラブル関数インスタンスとノードのみを管理できます。バックグラウンドワーカー・ロール(デフォルト: azuresu)は、RLSをバイパスしてすべてのユーザー・インスタンスを管理するために、スーパーユーザーである必要があります。

コミュニティの視点とトレードオフ

エンジニア間の議論では、「データベースをオーケストレーターとして使用する」アプローチを好む層と、従来の外部DAGスケジューラーを好む層との間で意見が分かれています。

主な対立点

  • Control Flow Location: 一部の開発者は、制御フローとキュー・ロジックがデータベース内ではなく、バージョン管理されたコード(Git)内に存在すべきであると主張しています。
  • Resource Contention: データベース(インフラストラクチャの中で最も拡張が困難な部分であることが多い)に、追加の長時間実行されるバックグラウンド・ジョブを負荷させることによる影響に関する懸念があります。
  • Comparison to Temporal: 一 some usersは、pg_durableがTemporalのようなツールと比較してどのように異なるのかを疑問視しており、「使用すべきでない場合」のセクションが、意図的にSQLの形状をしているため、スコープがより限定的であることを示唆していると指摘しています。
  • Inner-Platform Effect: 一部の批判者は、これが「インナー・プラットフォーム効果」の例である可能性を提案しています。これは、ツールがデータベース環境内でプログラミング言語の機能(状態の停止と再開など)を再構築することを示すものです。

Sources