Покупатель оплатил заказ, склад подтвердил резерв, а доставка так и не оформилась. С точки зрения клиента операция одна: он нажал «Оформить». Для компании это уже несколько самостоятельных действий, и часть из них необратима простым нажатием «отменить».
Такой разрыв возникает, когда заказ, остатки, платежи и логистика работают в отдельных системах. Saga — способ провести один бизнес-процесс через эти границы, заранее предусмотрев не только успешный результат, но и остановку посередине.

Почему нельзя просто отменить всё
В приложении с одной базой несколько изменений иногда можно объединить в одну транзакцию. Если операция не завершилась, база вернётся к прежнему состоянию. При условии, конечно, что всё действительно находилось внутри этой транзакции.
Когда сервисы самостоятельно сохраняют свои данные, такой общей кнопки уже нет. Склад успел зарезервировать товар, платёжный сервис зафиксировал списание, а перевозчик недоступен. Для первых двух систем действия уже произошли.
Saga связывает локальные транзакции в последовательность: выполнили шаг, получили подтверждение, перешли к следующему. Если процесс остановился, запускаются компенсирующие действия для уже завершённых шагов. Их нужно продумать и реализовать отдельно.
Возврат денег — это не rollback
Предположим, резерв на складе создан, деньги списаны, но отправку организовать не удалось. Можно освободить товар и инициировать возврат. Только клиент не обязательно увидит деньги мгновенно: возврат зависит и от платёжной системы.
Если деньги были лишь авторизованы, компенсацией может быть снятие блокировки, а не возврат списанного платежа. Это разные сценарии. Архитектура не должна путать их, даже если на диаграмме оба выглядят как стрелка назад.
Есть действия, которые вообще нельзя отменить в исходном смысле. Отправленное письмо уже прочитали, посылку передали перевозчику, внешний партнёр начал работу. В таких случаях компенсация — новое действие, уменьшающее последствия, а не путешествие во времени.
Значит, бизнесу нужно определить момент, после которого обычная отмена уже невозможна, и порядок действий до него. Иногда разумнее сначала зарезервировать ресурс, а окончательное списание или физическую отправку выполнить позже.
Кто отвечает за заказ, застрявший между системами
Самый неприятный вариант — не явный отказ, а неизвестность. Запрос к платёжному сервису не вернулся вовремя. Деньги списаны или нет? Повторить команду можно, но нельзя превращать повтор в двойное списание.
Поэтому одной последовательности шагов мало. Нужно сохранять состояние процесса, безопасно повторять операции, обрабатывать повторно доставленные сообщения и уметь восстановиться после перезапуска. Технически здесь помогают идемпотентность, надёжная публикация событий и контроль таймаутов.
Но остаётся управленческий вопрос: кто владеет процессом целиком? Если возврат не проходит, кому поступает сигнал, кто связывается с клиентом и когда ситуация переходит на ручную обработку? Передавать заказ между системами можно автоматически. Передавать ответственность в пустоту — плохая идея.
Оркестратор или обмен событиями
У Saga есть два распространённых способа координации. При оркестрации один компонент хранит маршрут процесса и говорит участникам, что делать дальше. Это облегчает понимание состояния и контроль сложных сценариев, но сам координатор становится важной частью системы.
При хореографии сервисы реагируют на события друг друга. Центрального диспетчера нет, зато со временем может стать трудно восстановить всю историю заказа и понять, кто запускает очередной шаг.
Не стоит выбирать хореографию только потому, что она выглядит «более распределённой». Для длинного процесса с возвратами, ожиданиями и ручными решениями явный координатор часто проще объяснить не только разработчикам, но и операционным подразделениям.
И ещё ограничение: Saga не обеспечивает автоматически ту же изоляцию, что транзакция одной базы. Пока один заказ ждёт подтверждения, другой может попытаться взять тот же остаток. Правила резервирования и конкурирующих изменений придётся проектировать отдельно.
Когда этот подход избыточен
Если все значимые изменения можно корректно провести одной локальной транзакцией, не нужно ради красивой схемы создавать распределённый процесс с компенсациями, очередями и обработкой дублей.
Saga имеет смысл, когда независимые системы уже оправданы, а бизнес-процесс обязан пересекать их границы. Но прежде чем внедрять её, я бы попросил команду показать не только путь успешного заказа, а три другие истории: что произойдёт при отказе, при неизвестном результате и при неудачной компенсации.
Ценность Saga не в том, что она делает распределённую систему похожей на одну транзакцию. Она заставляет компанию заранее решить, что делать с заказом, который не удалось довести до конца.
Техническое описание подхода и его ограничений можно найти в описании паттерна Saga.