
pg_durable: Microsoft открывает durable execution внутри PostgreSQL
Microsoft открыла исходный код pg_durable — PostgreSQL-расширения для надёжного выполнения рабочих процессов прямо внутри базы данных без внешних оркестраторов.
Когда база данных становится оркестратором
Представьте: ваш ETL-пайплайн обрабатывает тысячи строк. На полпути сервер падает. Всё начинается с нуля. Знакомо? Именно от этой боли спасает концепция durable execution — «долговечного выполнения», при котором любой сбой не откатывает прогресс, а просто продолжает работу с последней контрольной точки.
Microsoft сделала шаг, который заставил сообщество PostgreSQL оживиться: компания открыла исходный код pg_durable — расширения, которое встраивает durable execution прямо внутрь PostgreSQL-сервера. Никаких Airflow, Temporal или Step Functions рядом. Только Postgres.
Что такое 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);
Типовые сценарии использования
pg_durable явно ориентирован на команды, работающие с данными и AI. Вот что разработчики Microsoft выделяют как ключевые кейсы:
Векторные пайплайны: разбить на чанки, вызвать embedding API и сохранить в pgvector. Пайплайны приёма данных: стейджинг, дедупликация, трансформация и публикация больших батчей. Плановое обслуживание: обнаружить bloat, уведомить, дождаться согласования, затем выполнить следующее действие. Fan-out агрегация: запустить независимые запросы параллельно, затем объединить результаты. Внешние API-воркфлоу: обогащение, классификация и webhook-вызовы из SQL.
Расширение особенно подходит командам, строящим data- или AI-пайплайны, которым нужно надёжное выполнение на уровне строки, документа или батча.
Сравнение с альтернативами
Microsoft сама честно описывает, что pg_durable не заменяет:
| Подход | Когда использовать | Ограничения |
|---|---|---|
| pg_durable | Воркфлоу тесно связан с данными в Postgres | Preview, только SQL-логика |
| pg_cron + jobs table | Простые периодические задачи | Нет чекпоинтов, ручные retry |
| Temporal / Airflow | Сложная бизнес-логика вне БД | Внешний сервис, сложный деплой |
| AWS Step Functions | Serverless-оркестрация в AWS | Vendor 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
Почему это важно для 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
Контекст: 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.
Ссылки: