> ## Documentation Index
> Fetch the complete documentation index at: https://omniflow-vpn.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 0002 — PostgreSQL — единственное надёжное хранилище

> Почему в Valkey нет ничего, что нельзя потерять, и почему очередь заданий и outbox лежат в той же базе, что и деньги

**Статус:** принято.

## Контекст

Omniflow работает с двумя хранилищами. Со вторым хранилищем всегда есть соблазн
дать ему разрастись: сюда сессию, туда незавершённый заказ, потом очередь
заданий, потому что база «не очередь». Каждый шаг по отдельности защитим, а в
итоге получается система, где восстановление после перезапуска Valkey означает
воссоздание состояния, которое никто не записал.

Конкретное давление — очередь. У долговременной фоновой работы (выдать доступ в
Remnawave после оплаты, повторить неудавшееся списание, просрочить корзину) есть
очевидное место в отдельном брокере. Но задание, выдающее доступ, должно
фиксироваться вместе с оплатой, которая его оправдывает. Если оплата попадает в
PostgreSQL, а задание — куда-то ещё, возникает окно, в котором клиент заплатил и
никто никогда на это не отреагирует. Это окно не теоретическое: именно так
выглядит недоступность брокера.

## Решение

PostgreSQL — единственное надёжное хранилище приложения. Там лежит всё, потеря
чего расстроит оператора: клиенты, заказы, платежи, книга проводок кошелька,
права на услуги, поддержка, журнал аудита, очередь долговременных заданий (River)
и транзакционный outbox.

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

Долговременное задание ставится в очередь в той же транзакции, что и изменение
состояния, которое его требует. Это правило написания кода, а не возникающее
свойство: обработчик, который фиксирует заказ, а затем ставит задание, создал
окно выше и неверен, даже когда его тесты проходят.

## Последствия

База несёт нагрузку, которую взял бы на себя брокер: опрос очереди, сканирование
outbox и запасные пути ограничения частоты, когда Valkey недоступен. Это реальная
цена, и она ограничена односерверной топологией из
[записи 0001](https://omniflow-vpn.mintlify.site/ru/architecture/decision-0001-modular-monolith.md).

Потеря Valkey деградирует платформу, но не останавливает: ограничения частоты и
кэши отказывают в безопасную сторону, а поверхности продолжают работать. Потеря
PostgreSQL останавливает всё — поэтому резервное копирование, проверенное
восстановление и учение по восстановлению являются условиями выпуска, а не
пожеланиями.

У outbox сегодня нет потребителя. Это намеренно: пока от него не зависит ни один
внешний эффект, поэтому спекулятивный отправитель означал бы поддержку интеграции,
которой никто не пользуется. Следствие в том, что счётчик неопубликованных
событий растёт и не является сигналом отставания, — и это сказано там, где
оператор иначе прочитал бы его неверно.

Собственная схема River поставляется как миграция Atlas, без изменений
скопированная из собственной линии миграций River, поэтому на стандартной
установке есть таблицы очереди, нужные воркеру и точкам входа для просмотра
заданий. Интеграционный тест падает, если мигратор River видит неприменённую
версию, и это привязывает копию к версии River, с которой собрана программа:
обновление River не может попасть в репозиторий без своей схемы.

## Когда пересматривать

* Пропускная способность очереди на реальной установке измеримо ограничена
  PostgreSQL, а не самой работой заданий.
* Появился внешний потребитель доменных событий; тогда outbox нуждается в
  отправителе, а отправитель — в гарантии доставки, которую эта запись не
  описывает.
* Появилась возможность, требующая долговременного состояния, которое
  действительно нельзя выразить реляционно. Такой не было.

## Смежное

* [Владение данными](https://omniflow-vpn.mintlify.site/ru/architecture/data-ownership.md) — разделение на надёжное, эфемерное и только-для-добавления.
* [Задания и очереди](https://omniflow-vpn.mintlify.site/ru/operations/jobs-and-queues.md) — что повторяется, что попадает в очередь недоставленных и что показывают точки входа.
* [Резервные копии, восстановление и аварийное восстановление](https://omniflow-vpn.mintlify.site/ru/operations/backup-restore.md) — чего стоит потеря единственного надёжного хранилища.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.