# 12. Sync и async

Как выбирать между синхронным запросом и асинхронным событием, где нужны очереди, outbox, retries и backpressure.

- **Author:** Фёдор Чищин
- **Level:** advanced
- **Reading time:** ~25 минут чтения
- **Published:** 2026-05-23
- **Source:** https://fedorthinks.com/ru/learn/software-architect-12-sync-async

---

## 1. Главная идея

Выбор sync или async — это выбор между немедленным ответом и устойчивой обработкой во времени.

### Синхронный вызов подходит для вопроса

> Если кассир спрашивает цену товара, ответ нужен сейчас. Если магазин отправляет отчёт в бухгалтерию, это может занять очередь.

Синхронный запрос хорош, когда пользователю нужен результат прямо сейчас: проверить пароль, показать цену, подтвердить доступ. Он проще для UX и отладки, но связывает availability вызывающего и вызываемого сервиса.

Асинхронность подходит для работы, которую можно выполнить позже: email, indexing, analytics, webhook delivery, report generation, enrichment. Она снижает coupling, но требует статусов, повторов, dead-letter queue и observability.

### Событие — это факт, а не команда

> «Дверь открыта» — факт. «Открой дверь» — команда. Смешать их можно, но система начнёт спорить о намерениях.

Event описывает то, что уже произошло: `OrderPlaced`, `PaymentCaptured`, `UserRegistered`. Command просит что-то сделать: `CapturePayment`, `SendEmail`. В архитектуре полезно не смешивать эти формы.

Если событие используется как скрытая команда, consumer становится зависим от внутреннего намерения producer-а. Это ломает слабую связанность.

## 2. Пример и антипример

Асинхронность не должна быть местом, где ошибки исчезают.

### Пример: transactional outbox

> Секретарь сначала регистрирует письмо в журнале, а потом отправляет. Если почта упала, запись не потеряна.

При создании заказа сервис пишет order и outbox event в одной транзакции. Отдельный worker читает outbox и публикует событие в broker. Если broker временно недоступен, событие остаётся в базе и будет отправлено позже.

Outbox закрывает типичную дыру: данные сохранились, но событие потерялось между commit и publish.

### Антипример: очередь как мусорный бак

> Корзина для входящих писем не является процессом. Если её никто не разбирает, работа просто спрятана.

Команда отправляет все тяжёлые операции в очередь, но не задаёт retry policy, idempotency, ordering, visibility timeout, DLQ и алерты. В production сообщения зависают, дублируются или обрабатываются часами.

Очередь не делает систему надёжной автоматически. Она переносит сложность из request path в background processing.

#### Самопроверка

- Нужен ли результат пользователю прямо сейчас?
- Что произойдёт при дубле сообщения?
- Где хранится факт, что событие должно быть опубликовано?
- Как система показывает backlog и failed jobs?

Следующий модуль: [Производительность](./software-architect-13-performance).
