Когда база данных становится оркестратором

Представьте: ваш ETL-пайплайн обрабатывает тысячи строк. На полпути сервер падает. Всё начинается с нуля. Знакомо? Именно от этой боли спасает концепция durable execution — «долговечного выполнения», при котором любой сбой не откатывает прогресс, а просто продолжает работу с последней контрольной точки.

Microsoft сделала шаг, который заставил сообщество PostgreSQL оживиться: компания открыла исходный код pg_durable — расширения, которое встраивает durable execution прямо внутрь PostgreSQL-сервера. Никаких Airflow, Temporal или Step Functions рядом. Только Postgres.

ℹ Статус проекта
pg_durable находится в стадии preview. Проект активно развивается, баг-репорты и предложения принимаются через GitHub Issues.

Что такое durable execution и зачем оно нужно

Durable execution — это способ запускать долгоживущие, надёжные функции, которые выживают при сбоях, перезапусках и сетевых отказах без потери состояния. По сути, это комбинация системы очередей и хранилища состояния, которое помнит последний выполненный шаг. Вместо того чтобы держать всю логику в памяти, система разбивает задачу на маленькие шаги (step functions) и записывает каждый шаг и каждое решение.

Когда процесс останавливается — из-за сбоя, намеренной паузы или падения машины — движок воспроизводит записанные события, чтобы восстановить точное состояние и продолжить выполнение с того места, где оно прервалось.

На практике это позволяет строить надёжные системы для LLM-агентов, платёжных процессов, email-рассылок, обработки заказов — всего, что может занимать минуты, дни или даже годы. Вместо того чтобы прикручивать ситуативную логику повторных попыток и ручные чекпоинты, durable workflows дают единую модель для гарантированного прогресса без двойного выполнения — это обещание семантики exactly-once в распределённых системах.

Архитектура pg_durable: всё внутри Postgres

pg_durable — это расширение PostgreSQL, собранное с помощью pgrx: всё выполняется внутри самого сервера PostgreSQL, без внешних сервисов. Расширение предоставляет SQL DSL для построения графов функций и регистрирует фоновый воркер, который выполняет их надёжным образом.

Под капотом расширение использует две Rust-библиотеки: duroxide — фреймворк надёжных задач, обеспечивающий оркестрационный рантайм (детерминированное воспроизведение, чекпоинты, суб-оркестрации, таймеры), и duroxide-pg — провайдер состояния на базе PostgreSQL для duroxide, который сохраняет состояние рантайма (инстансы, историю, рабочие очереди) в выделенной схеме duroxide.*.


graph TD
 A[SQL DSL / df.start] --> B[pg_durable Extension]
 B --> C[Background Worker]
 C --> D[duroxide Runtime]
 D --> E[duroxide-pg State Provider]
 E --> F[(PostgreSQL: duroxide.* schema)]
 F -->|Checkpoint| D
 D -->|Resume on crash| C
 B --> G[df.instances Table]
 G --> H[Observability / Monitoring]

Функция pg_durable — это граф SQL-шагов, который PostgreSQL выполняет и контролирует по мере продвижения. Если база данных падает, перезапускается или шаг завершается с ошибкой, выполнение возобновляется с последней надёжной контрольной точки — вместо того чтобы заставлять разработчика восстанавливать состояние вручную.

Язык определения воркфлоу: SQL DSL

Определение рабочего процесса переезжает в SQL и начинается с df.start(...). Состояние повторных попыток, отслеживание прогресса и чекпоинтирование переезжают в Postgres вместо специфичного кода приложения. Часть воркеров на уровне приложения, потребителей очередей или планировщиков может исчезнуть полностью. Видимость операций обеспечивают таблицы Postgres вроде df.instances — с той же моделью авторизации и резервного копирования, что и для ваших данных.

Воркфлоу определяется в SQL с помощью компонуемых операторов — таких как ~> и |=>. Запускается через df.start(), возвращая идентификатор инстанса.

Пример простого воркфлоу для векторного пайплайна:

-- Определяем шаги воркфлоу
SELECT df.define(
  'embed_and_store',
  df.step('chunk_text')     ~>
  df.step('call_embed_api') ~>
  df.step('upsert_pgvector')
);

-- Запускаем экземпляр для конкретной строки
SELECT df.start('embed_and_store', '{ "doc_id": 42 }'::jsonb);
💡 Мультиязычная поддержка
Если вы предпочитаете писать durable-функции на Rust, Python или Node, сохраняя состояние в PostgreSQL, можно использовать duroxide и duroxide-pg напрямую из вашего хост-языка — pg_durable является тем, что вы строите поверх этой пары, когда хотите работать в SQL.

Типовые сценарии использования

pg_durable явно ориентирован на команды, работающие с данными и AI. Вот что разработчики Microsoft выделяют как ключевые кейсы:

Векторные пайплайны: разбить на чанки, вызвать embedding API и сохранить в pgvector. Пайплайны приёма данных: стейджинг, дедупликация, трансформация и публикация больших батчей. Плановое обслуживание: обнаружить bloat, уведомить, дождаться согласования, затем выполнить следующее действие. Fan-out агрегация: запустить независимые запросы параллельно, затем объединить результаты. Внешние API-воркфлоу: обогащение, классификация и webhook-вызовы из SQL.

Расширение особенно подходит командам, строящим data- или AI-пайплайны, которым нужно надёжное выполнение на уровне строки, документа или батча.

Сравнение с альтернативами

Microsoft сама честно описывает, что pg_durable не заменяет:

ПодходКогда использоватьОграничения
pg_durableВоркфлоу тесно связан с данными в PostgresPreview, только SQL-логика
pg_cron + jobs tableПростые периодические задачиНет чекпоинтов, ручные retry
Temporal / AirflowСложная бизнес-логика вне БДВнешний сервис, сложный деплой
AWS Step FunctionsServerless-оркестрация в AWSVendor lock-in, ~100ms latency на шаг
DBOSПриложения на Python/Node поверх PostgresТребует внешнего кода приложения

pg_durable не стоит использовать, если требуется субмиллисекундная синхронная обработка запросов, если нельзя устанавливать расширения или запускать фоновый воркер в вашей Postgres-среде, если воркфлоу преимущественно живёт вне Postgres и охватывает множество разнородных систем, или если нужна произвольная логика приложения, которая не укладывается в SQL-шаги, ветвления, циклы или HTTP-вызовы.

«Retry state, progress tracking, and checkpointing move into Postgres instead of bespoke app code» — именно в этом ключевой смысл pg_durable: переносить операционную сложность туда, где уже живут данные.

Установка и первые шаги

После установки пакета нужно добавить pg_durable в shared_preload_libraries, перезапустить PostgreSQL и создать расширение в настроенной базе данных. По умолчанию база данных pg_durable — это postgres; настройка фонового воркера и привилегий описана в User Guide.

# Добавить в postgresql.conf
shared_preload_libraries = 'pg_durable'

# После рестарта Postgres
CREATE EXTENSION pg_durable;

Для локальной разработки Microsoft предоставляет готовый Dev Container:

VS Code Dev Container (.devcontainer/) включает предустановленные Rust, cargo-pgrx и PostgreSQL 17.

# Клонируем репозиторий
git clone https://github.com/microsoft/pg_durable

# Запуск через скрипт (собирает расширение при первом запуске)
./scripts/pg-start.sh

# Подключаемся
psql -h localhost -p 28817 -d postgres
⚠ Важно для продакшена
Проект находится в стадии preview. Не рекомендуется использовать pg_durable для production-нагрузок без тщательного тестирования. Следите за обновлениями в репозитории — API и поведение могут меняться.

Почему это важно для AI и data-инженеров

Сейчас отрасль переживает бум агентных систем. LLM-агенты делают вызовы к внешним API, выполняют многошаговые рассуждения, могут «засыпать» на часы в ожидании human-in-the-loop подтверждения. На практике это делает возможным строить надёжные системы для LLM-агентов, платёжных процессов, email-рассылок и обработки заказов — всего, что может занимать минуты, дни или годы.

Традиционно для этого разворачивали отдельный сервис: Temporal, Airflow, Step Functions. pg_durable предлагает альтернативу: строя durable workflows на Postgres, можно гарантировать, что шаги выполняются ровно один раз — если эти шаги выполняют операции с базой данных.

Поскольку всё находится в Postgres, вы получаете привычный инструментарий: бэкапы, GUI-клиенты, CLI-инструменты — всё что угодно.

Это особенно актуально для:

  • RAG-пайплайнов: chunking → embedding → upsert в pgvector — как единый надёжный воркфлоу
  • AI-агентов с human-in-the-loop: пауза и ожидание внешнего сигнала без потери состояния
  • ETL с частичными сбоями: продолжить с шага 47 из 100 после краша, не начиная с нуля
  • Периодического обслуживания: многоэтапные административные воркфлоу прямо в SQL
📝 Реальный кейс: vector embedding pipeline
Вместо того чтобы писать Python-скрипт с ручным трекингом прогресса в отдельной таблице и Celery для ретраев, весь пайплайн описывается как граф SQL-шагов в pg_durable. При падении сервера на 500-м документе из 10 000 — следующий запуск продолжает с 501-го автоматически.

Контекст: Microsoft и экосистема durable execution

Microsoft давно инвестирует в концепцию надёжного выполнения. Durable Task Framework (DTFx) — библиотека, позволяющая писать долгоживущие persistent workflows (оркестрации) на C# с помощью конструкций async/await. Это фундамент Azure Durable Functions.

Durable Task — это технология Microsoft для построения воркфлоу и оркестраций как обычного кода, который автоматически выживает при сбоях. Вместо управления сложной retry-логикой, стейт-машинами или очередями сообщений вы выражаете бизнес-логику в виде обычных функций, а Durable Task берёт на себя персистентность состояния, автоматическое восстановление и распределённую координацию. Воркфлоу могут выполняться часами, днями и даже месяцами, надёжно возобновляясь с последнего завершённого шага после любого краша, перезапуска или редеплоя.

pg_durable — логичное развитие этой философии, только вместо Azure Storage или Event Hubs бэкендом выступает сам PostgreSQL. Это снижает операционную сложность для команд, которые уже используют Postgres как основное хранилище.

Заключение

pg_durable — это не просто ещё одно расширение PostgreSQL. Это концептуальный сдвиг: база данных перестаёт быть пассивным хранилищем и становится активным участником оркестрации рабочих процессов.

Для data- и AI-инженеров, которые уже используют PostgreSQL, это означает возможность убрать из стека целый класс внешних сервисов — планировщики, менеджеры очередей, оркестраторы — и описать надёжное выполнение многошаговых пайплайнов прямо в SQL.

Проект находится в preview, но уже сейчас заслуживает внимания: Microsoft с его богатой историей в durable execution (Durable Functions, DTFx) — серьёзный автор для подобного инструмента. Следите за репозиторием, экспериментируйте в dev-окружении и подавайте feedback через GitHub Issues.

Ссылки: