Распределенный биллинг ломается не на оплате, а на границе консистентности данных
В биллинговой системе нельзя полагаться на «почти точно» и «потом досчитаем». Любой расход, подписка, возврат или промо должны проходить через строгий жизненный цикл: авторизация события, запись факта, расчет, публикация результата. Если один из шагов выполняется вне транзакционной границы, появляется revenue leakage: дубли, пропуски, расхождения между ledger и витриной.
Главный паттерн — разделять source of truth и производные представления. Денежный факт фиксируется в журнале событий или бухгалтерском ledger с идемпотентным ключом; все остальное — асинхронные проекции. Это позволяет пережить повтор доставки, сетевой сплит шлюза и рестарт воркера без двойного списания. Идемпотентность в биллинге — это не рекомендация, а базовый вопрос выживания системы.
Для согласованности между сервисами используйте не распределенную транзакцию как правило, а сагу с компенсациями: списание, начисление бонуса, отмена, перерасчет. Каждый шаг должен быть повторяемым, а сообщение — дедуплицируемым. Особенно опасны пограничные сценарии: таймаут после успешного списания, падение consumer после записи, расхождение валютных курсов между этапами расчета.
Если проектируете систему с высокой нагрузкой, сразу закладывайте: уникальный business key, версионирование записей, атомарную запись состояния и outbox-паттерн для публикации событий. Иначе любая ретрай-логика dunning начнет работать против вас, превращая защиту выручки в генератор шумных расхождений.
Практика простая: сначала проектируйте цепочку доказуемой неизменяемости денежных фактов, и только потом витрины, отчеты и аналитические агрегаты.
Подписки: биллинг-лаб
@subscriptions_billing_lab_arb
Распределенный биллинг ломается не на оплате, а на границе консистентности данных
Этот пост опубликован в Telegram-канале Подписки: биллинг-лаб. Подписаться можно по ссылке: @subscriptions_billing_lab_arb.