Добавить в корзинуПозвонить
Найти в Дзене
Цифровая Переплавка

«Postgres — это всё, что нужно»: durable execution без оркестратора, как это устроено и где подвох

За последние полгода две независимые истории сошлись в одном тезисе: чтобы получить надёжное выполнение длинных процессов, отдельный оркестратор вроде Temporal или Airflow не нужен — хватит Postgres, который у вас и так есть. Сначала это сформулировал Армин Ронахер (автор Flask и Jinja2), выкатив крошечную библиотеку Absurd, потом то же самое аргументировала DBOS — стартап, сооснователь которого Майкл Стоунбрейкер, создатель Postgres. Идея по меркам индустрии древняя (очередь плюс хранилище состояния), но именно сейчас она дозрела до продакшена. Я проверил громкие цифры и формулировки — и, в отличие от иных «сенсаций», эта держит удар. Но дьявол, как обычно, в деталях: что Postgres даёт по-настоящему, что звучит чуть смелее реальности и где «голого Postgres» перестаёт хватать. Разберём по-инженерному. Durable execution (устойчивое выполнение) — это функция, которая переживает падения. Каждый шаг процесса сохраняется как чекпоинт в базе; если воркер крэшнулся, сеть отвалилась или сервер
Оглавление

За последние полгода две независимые истории сошлись в одном тезисе: чтобы получить надёжное выполнение длинных процессов, отдельный оркестратор вроде Temporal или Airflow не нужен — хватит Postgres, который у вас и так есть. Сначала это сформулировал Армин Ронахер (автор Flask и Jinja2), выкатив крошечную библиотеку Absurd, потом то же самое аргументировала DBOS — стартап, сооснователь которого Майкл Стоунбрейкер, создатель Postgres. Идея по меркам индустрии древняя (очередь плюс хранилище состояния), но именно сейчас она дозрела до продакшена.

Я проверил громкие цифры и формулировки — и, в отличие от иных «сенсаций», эта держит удар. Но дьявол, как обычно, в деталях: что Postgres даёт по-настоящему, что звучит чуть смелее реальности и где «голого Postgres» перестаёт хватать. Разберём по-инженерному.

Durable execution на пальцах

Durable execution (устойчивое выполнение) — это функция, которая переживает падения. Каждый шаг процесса сохраняется как чекпоинт в базе; если воркер крэшнулся, сеть отвалилась или сервер перезагрузили, воркфлоу возобновляется с последнего сохранения, а не с нуля. Аналогия с сейвом в видеоигре из исходной новости — на удивление точная: умер — продолжил с чекпоинта, а не с начала уровня.

Формулировка Армина бьёт в самую суть: durable execution — это комбинация очереди задач и хранилища состояния, которое помнит последний достигнутый шаг. А очередь и транзакционное хранилище Postgres умеет уже лет двадцать. Отсюда вывод: специализированный рантайм можно не разворачивать — нужны SQL-файл и тонкий SDK.

Как это устроено под капотом

Здесь начинается самое интересное — и где видно, что это не магия, а аккуратная эксплуатация того, что в Postgres уже есть.

⚙️ Разбор очереди через SELECT ... FOR UPDATE SKIP LOCKED. Это сердце всей конструкции. Воркер делает примерно SELECT id FROM queue WHERE status='pending' ORDER BY created_at LIMIT 1 FOR UPDATE SKIP LOCKED, лочит выбранную строку и помечает задачу как взятую. Магия в SKIP LOCKED: вместо того чтобы ждать освобождения залоченной строки (как сделал бы обычный FOR UPDATE), запрос просто пропускает занятые строки и берёт следующую свободную. В итоге тысячи воркеров параллельно разбирают непересекающиеся задачи без долгого ожидания на локах. Фича появилась ещё в Postgres 9.5 и десять лет используется как «бедняцкая очередь» — теперь на ней строят durable execution.

⚙️ Шаги, чекпоинты и повторные запуски. У Армина модель такая: задача (task) кладётся в очередь, воркер её забирает и выполняет по шагам (steps) последовательно; результат каждого шага пишется в Postgres как checkpoint. Если задача упала или была приостановлена, она запускается заново (это называется run) — но готовые шаги не переисполняются, их результаты подгружаются из базы. Плюс задачи умеют sleep и suspend-for-events: воркфлоу засыпает или ждёт события, а события кэшируются в базе, поэтому гонок нет.

⚙️ Что добавляет каждый игрок. DBOS даёт декораторы @DBOS.workflow() и @DBOS.step(), durable sleep (время пробуждения хранится в Postgres, так что сон переживает рестарт), cron-расписание и durable-уведомления. Absurd по своей сути — это одна миграция absurd.sql, которая переносит всю сложность в хранимые процедуры базы, плюс тонкий SDK для эргономики языка; в комплекте уже есть CLI (absurdctl) и веб-дашборд (Habitat). Подкупает именно минимализм: накатил один SQL-файл — получил движок.

И сразу бонус, которого нет в новости: идею тут же продолжили. Авторы Obelisk написали пост «SQLite — это всё, что нужно», доведя мысль до предела — для многих систем хватит вообще локального SQLite с бэкапом в S3, без сетевой базы и control plane. Тренд явно шире одного Postgres.

Exactly-once: где правда, а где нужно уточнение

Вот пункт, в котором новость чуть забегает вперёд, а сообщество регулярно спотыкается. Exactly-once — самый скользкий термин в распределённых системах, и точность тут важна. Что Postgres реально гарантирует:

Exactly-once на уровне dequeue. Два воркера не возьмут одну задачу: лок строки плюс SKIP LOCKED разводят их по разным задачам. А если вы при обработке пишете строку результата с уникальным ключом, то даже при теоретической гонке UNIQUE-констрейнт не даст записать дубль. Здесь новость абсолютно права.

Exactly-once для side-effect, который сам является записью в Postgres в той же транзакции, что и чекпоинт. Эффект и его «отметка о выполнении» коммитятся атомарно — это по-настоящему ровно один раз.

⚠️ А вот для внешних эффектов (дёрнуть платёжный API, отправить письмо) честная гарантия звучит как at-least-once плюс идемпотентность. Представьте: шаг вызвал внешний API, эффект случился — но воркер упал до того, как чекпоинт закоммитился. При восстановлении шаг выполнится повторно, и письмо уйдёт дважды. Поэтому durable execution на практике — это retries + idempotency, а не серебряная пуля: внешние вызовы должны быть идемпотентными (idempotency key), иначе «exactly-once» превращается в «effectively-once при условии, что вы сами сделали ручную работу». Это не недостаток подхода, это природа задачи — и комментаторы на Hacker News под постом Армина ровно на это и указывают. Для AI-агентов нюанс особенно острый: их шаги вероятностны, идемпотентность дёргающейся LLM — отдельная головная боль.

Цифры: проверка

DBOS опубликовала бенчмарк, и числа из новости — оттуда. Один сервер Postgres в их тесте выдаёт около 43K durable-воркфлоу в секунду при прямом запуске и 30.6K через очередь (очередь требует больше записей, отсюда просадка), а также до 144K мелких записей в секунду. В пересчёте — порядка 12 млрд записей или 4 млрд воркфлоу в сутки. Дальше — горизонтальный шардинг по нескольким серверам.

Но в том же бенчмарке зашита важная оговорка, которую пересказ опустил:

📈 SKIP LOCKED не отменяет contention на «голове» очереди. Когда все воркеры дерутся за несколько верхних строк одной очереди, производительность упирается в эту конкуренцию. Лечится это разбиением на много очередей или партиций (с убывающей отдачей) — именно так и достигаются те самые десятки тысяч в секунду.

📈 Язык имеет значение. DBOS прямо отмечает: Python относительно медленный, поэтому нужно много клиентов, чтобы насытить Postgres, а они добавляют contention; на Go клиентов потребовалось бы меньше. То есть «тысячи воркеров без блокировок» — с поправкой: без долгих блокировок да, но конкуренцию за одну очередь надо инженерно разводить.

📈 И мелкая корректность к новости: 4 млрд/день — это продемонстрированный потолок одного сервера Postgres в бенчмарке, а не «DBOS обрабатывает 4 млрд воркфлоу в день в проде». Разница между «способен» и «обрабатывает» здесь существенна.

Почему это особенно зашло именно сейчас: AI-агенты

Самая недооценённая часть истории — связь с агентами, и не зря на ней фокусируется сам Армин. Обычный воркфлоу — это DAG, заданный человеком заранее. AI-агент же сам прокладывает маршрут на ходу: по сути это воркфлоу с одним шагом, который крутится над меняющимся состоянием (история сообщений, вызовы инструментов), пока не решит, что закончил. Absurd поддерживает это автоматическим инкрементом повторяющихся шагов — агентный цикл while ложится на модель чекпоинтов почти дословно.

И главный практический довод: повторять упавший LLM-вызов дорого. Возобновление с последнего успешного шага, а не с начала диалога, — это прямая экономия на токенах и латентности. Тот же паттерн уже живёт в чекпоинтерах LangGraph поверх Postgres: фреймворки агентов и так сходятся к «состояние в базе, возобновляйся с чекпоинта». Durable execution в Postgres — это не нишевый бэкенд-трюк, а, похоже, дефолтная инфраструктура для агентных пайплайнов ближайших лет.

Где «голого Postgres» перестаёт хватать (честно)

Заголовок «забудьте Temporal и Airflow» красив, но требует честной сноски — и даже авторы подхода её делают:

🧱 Airflow и Temporal — про разное. Airflow — это про расписания и DAG-пайплайны данных; Temporal — про долгие durable-воркфлоу с богатым рантаймом, версионированием, детерминированным replay, видимостью и мультиязычностью. «Postgres-подход» перекрывает огромный пласт кейсов «надёжные фоновые джобы и агентные циклы», но не заменяет всё подряд.

🧱 Один сервер Postgres — одна точка давления. На него ложится и база приложения, и движок воркфлоу. На больших объёмах придётся шардировать или выносить выделенный кластер — и та самая операционная простота, ради которой всё затевалось, начинает таять.

🧱 У Absurd честно нет части фич. Сам Армин перечисляет: встроенного планировщика, push/webhook-поддержки, партиционирования таблиц. Это «достаточно для многих и приятно в работе», а не «готовая замена Temporal из коробки».

🧱 Сложная оркестрация, версионирование долгих воркфлоу, детерминированный replay — это ровно то, ради чего исторически и берут тяжёлые движки. Если вам это нужно, нужно по-настоящему.

Итог простой: «Postgres — это всё, что нужно» верно ровно до момента, когда нужно что-то большее. И в этом вся соль «boring tech» — это правильный дефолт, а не универсальный ответ.

Что в сухом остатке

Моё мнение: это здоровый разворот индустрии от «на каждый чих — отдельный сервис» обратно к «используй то, чему ты уже доверяешь». Огромная доля команд, которые тащат Temporal или Airflow ради десятка надёжных джоб, переусложнили на ровном месте. Если у вас уже есть Postgres и нужны устойчивые фоновые процессы или агентные циклы — начните с него. Оркестратор берите, когда упрётесь в конкретную стену (масштаб, мультиязычность, версионирование сложных воркфлоу), а не превентивно «чтобы было».

Прогноз: durable-execution-в-Postgres станет дефолтным паттерном для агентных пайплайнов — фреймворки уже двигаются туда; вокруг «одной SQL-миграции» вырастет слой тонких SDK под разные языки; а Temporal и Airflow займут честную нишу действительно тяжёлых и масштабных сценариев вместо позиции «по умолчанию».

И одна мысль на вынос, которая стоит всей статьи: единственная новая концепция, которую тут реально надо усвоить, — идемпотентность шагов. Освоите её — и «exactly-once» перестанет быть строчкой из маркетинга и станет свойством вашей системы. Всё остальное Postgres уже умеет — оставалось только перестать бояться использовать его по назначению.

Источники

Первоисточники:

📰 Исходная новость (источник) — DBOS, «Postgres Is All You Need for Durable Execution» — https://www.dbos.dev/blog/postgres-is-all-you-need-for-durable-execution

📰 Полный русскоязычный пересказ (Telegraph) — https://telegra.ph/Proshchaj-orkestrator-kak-my-perestali-boyatsya-i-polyubili-golyj-Postgres-dlya-nadyozhnyh-processov-05-28

🧩 Армин Ронахер, «Absurd Workflows: Durable Execution With Just Postgres» — https://lucumr.pocoo.org/2025/11/3/absurd-workflows/

🧩 Армин Ронахер, «Absurd In Production» (5 месяцев в проде, чего не хватает) — https://lucumr.pocoo.org/2026/4/4/absurd-in-production/

Чем проверял цифры и формулировки:

📚 Бенчмарк DBOS (43K/30.6K воркфлоу/сек, 4 млрд/день, contention и SKIP LOCKED) — https://www.dbos.dev/blog/benchmarking-workflow-execution-scalability-on-postgres

📚 DBOS Transact (механизм, durable sleep/cron/notifications, exactly-once) — https://github.com/dbos-inc/dbos-transact

📚 DBOS Transact (Python, PyPI) — https://pypi.org/project/dbos/

📚 Обсуждение на Hacker News (retries + idempotency, нюанс exactly-once) — https://www.hckrnws.com/stories/45797228

📚 «SQLite is All You Need for Durable Workflows» (как идею продолжили) — https://obeli.sk/blog/sqlite-is-all-you-need-for-durable-workflows/

📚 LangGraph Postgres-чекпоинтер (агентные фреймворки сходятся к тому же паттерну) — https://github.com/SerezhaGRig/langgraph-postgres-checkpointer