Подписка ломается не на оплате, а на переходах между статусами и льготами
Жизненный цикл подписки нужно проектировать как конечный автомат, а не как набор разрозненных флагов. Базовые состояния: trial, promo, active, past_due, paused, canceled, grace. Между ними должны быть явные переходы с причинами, иначе апгрейд во время триала легко превращается в двойное списание или потерю права на скидку.
Триал и промо-период нельзя хранить как «дней осталось» без истории. Нужны: дата старта, источник права на льготу, правило завершения и приоритеты. Если пользователь получил промо поверх триала, система должна заранее понимать, что заканчивается первым, как считается первый платный цикл и что делать при раннем апгрейде. Идемпотентность в биллинге — это не рекомендация, а базовый вопрос выживания системы.
Апгрейды и даунгрейды лучше проводить через proration-логику, привязанную к биллинговому периоду, а не к календарю. Иначе возвраты, доплаты и переносы остатка начинают конфликтовать с dunning-процессом. Давайте разберем, что происходит с транзакцией в момент сетевого сплита шлюза: если смена плана уже принята, а платежный callback не дошел, система обязана восстановить исход по журналу событий, а не по попытке «переотправить как-нибудь».
Отдельно нужен слой правил для остановки льгот: отмена, неуспешный платеж, ручная блокировка, смена валюты, миграция между планами. Без этого промо-логика расползается по коду, а revenue leakage появляется там, где его никто не искал. Грамотно спроектированная dunning-стратегия способна спасти до 15% уходящей регулярной выручки.
Проверьте один принцип: каждый статус, льгота и переход должны быть воспроизводимы из событий и не зависеть от памяти сервиса.
Подписки: биллинг-лаб
@subscriptions_billing_lab_arb
Подписка ломается не на оплате, а на переходах между статусами и льготами
Этот пост опубликован в Telegram-канале Подписки: биллинг-лаб. Подписаться можно по ссылке: @subscriptions_billing_lab_arb.