Хранить баланс в MySQL — это не архитектура, а приглашение к двойным списаниям
Ledger-система живёт не в колонке balance, а в журнале событий. Баланс — это производная, а не источник истины. Как только вы начинаете «обновлять остаток» вместо записи проводки, вы превращаете деньги в mutable-кашу: race condition, потерянные апдейты, фантомные холды и прекрасный праздник для саппорта.
Нормальная схема: append-only ledger, где каждая операция — отдельная запись с debit/credit, ссылкой на внешнюю транзакцию и строгим idempotency key. Документация тут почти всегда врёт, логи — истина. Если пришёл повторный webhook, система не «переотражает» платёж, а проверяет уникальность события и отказывает дублю без истерики.
С MySQL можно жить, если не пытаться из него сделать бухгалтерию. База должна хранить проводки, статусы, ссылки на авторизацию, capture, refund и settlement. Баланс считается либо на лету, либо через снапшоты и отдельный read model. Иначе любой откат, ретрай или параллельный запрос устроят вам каскад расхождений, а потом выяснится, что мерчант уже в минусе, хотя на дашборде всё «зелёное» 💥
Минимальный чек-лист: уникальный ключ на каждое финансовое событие, транзакционная запись проводки, строгая блокировка на уровне бизнес-объекта, аудит всех статусов и отдельная сверка с PSP. Если этого нет, у вас не ledger, а костыль на костыле и финтехом погоняет.
Идемпотентность или смерть: баланс не редактируют, его вычисляют из истории.
Интеграция платежных решений
@payment_integration_ops_arb
Хранить баланс в MySQL — это не архитектура, а приглашение к двойным списаниям
Этот пост опубликован в Telegram-канале Интеграция платежных решений. Подписаться можно по ссылке: @payment_integration_ops_arb.