Архітектура фінтеху: те, що не підлягає обговоренню

·11 хв читання

У більшості програм баг — це інцидент. У фінтеху баг — це зобов'язання, яке, можливо, вже коштувало грошей, і цього ще ніхто не помітив.

В архітектурі фінтеху є невелика кількість рішень, що справді не підлягають обговоренню. Помиліться в них — і жодна подальша інженерія цього повністю не надолужить: ви успадкуєте систему, де гроші можуть бути беззвучно неправильними, а це єдиний режим відмови, якого фінансовий продукт не витримує.

1. Баланси виводяться, а не зберігаються як істина

Найпоширеніша і найруйнівніша помилка — змінна колонка балансу, яку код оновлює напряму. Це зручно, швидко і невідновно: коли вона поїде, немає способу визначити, якою вона мала бути.

Правильна модель — журнал проводок лише на дозапис. Нічого ніколи не оновлюється і не видаляється; виправлення — це нові компенсаційні проводки. Баланс є сумою проводок: кешується для швидкодії, але завжди відтворюється з журналу.

Змінний балансЖурнал append-only
UPDATE accounts SET balance = balance - 100INSERT проводка (дебет 100), INSERT проводка (кредит 100)
Історія втрачається при кожному записіПовна історія за самою конструкцією
Розбіжність невиявна і невиправнаБудь-який стан відтворюється на будь-який момент
Помилки конкурентності псують стан назавждиІнваріант подвійного запису ловить помилки
Аудит означає читати логи застосункуАудит означає читати журнал

2. Кожен грошовий шлях ідемпотентний

Мережі повторюють запити. Користувачі клікають двічі. Платіжні провайдери доставляють вебхуки більше одного разу — це задокументована поведінка, а не крайній випадок. Будь-яка операція, що рухає гроші, має бути безпечною при повторному виконанні.

  • Кожна грошова операція несе ключ ідемпотентності від викликача, унікальний для логічного наміру
  • Ключ зберігається з обмеженням унікальності до побічних ефектів, а не після
  • Повторений ключ повертає початковий результат замість виконувати роботу знову
  • Обробники вебхуків спершу зберігають сирий payload за ідентифікатором події провайдера, а вже потім обробляють — так повторна доставка розпізнається навіть посеред обробки

3. Гроші — це цілі числа в мінорних одиницях

Число з плаваючою комою не може точно представити десяткові дроби, тому арифметика над грошима у float накопичує похибку. Зберігайте мінорні одиниці цілими числами (або десятковим типом фіксованої точності) і робіть валюту явною біля кожної суми — сума без валюти це баг, що чекає на першого міжнародного клієнта.

4. Звірка — це функція, а не запізніла думка

Припускайте розбіжність між вашим журналом і платіжним провайдером — вона станеться через таймаути, часткові відмови і виправлення на боці провайдера. Питання в тому, чи ви її виявите.

  • Регулярна задача, що порівнює внутрішній стан із даними сетлменту провайдера
  • Сповіщення при розбіжності, з визначеним відповідальним і runbook
  • Визначений шлях розв'язання — компенсаційні проводки, ніколи тиха корекція
  • Прочісування завислих станів: транзакції в pending довше, ніж мали б

5. Ізоляція в обох сенсах

  • Ізоляція орендарів — забезпечена на рівні даних, а не сподіванням, що кожен запит містить правильний фільтр
  • Ізоляція відмов — повільний провайдер не має вичерпувати пул запитів і класти непов'язану функціональність
  • Ізоляція середовищ — жодних тестових транзакцій у продакшн-журналах

6. Будуйте під аудит, який зрештою настане

Ні. Він надає технічні висновки в погоджених межах. Правова оцінка й формальна сертифікація потребують відповідних кваліфікованих спеціалістів.

  • Незмінний аудиторський слід, хто що і коли робив — включно з внутрішніми адміністративними діями
  • Дані карток ніколи не торкаються ваших серверів, якщо ви справді не збираєтесь бути PCI-сумісними (використовуйте hosted fields або hosted-сторінку)
  • Зберігання і видалення даних, які реально можна виконати на запит
  • Контроль доступу, який можна переглянути — хто може рухати гроші, хто це схвалив
У звичайному ПЗ ви оптимізуєте швидкість змін. У фінтеху ви оптимізуєте здатність довести згодом, що саме сталося і чому.

П'ять питань до власної системи

  1. Якщо цей вебхук прийде двічі, чи зміниться щось на другий раз?
  2. Чи можу я відтворити баланс будь-якого клієнта на будь-який момент минулого лише з журналу?
  3. Чи виявили б ми розбіжність із провайдером, чи нам сказав би про неї клієнт?
  4. Чи може підроблений запит прочитати або перемістити гроші іншого орендаря?
  5. Якби регулятор запитав, хто схвалив ручне коригування торік у березні, чи відповіли б ми за кілька хвилин?

Розділяйте прийняття транзакції та розрахунок

Платіжні стани мають пояснювати запізнілі й повторні події. Перевіряйте фінансові записи разом із процедурою корекцій.

  1. Використовуйте точні десяткові або цілі мінімальні одиниці за правилами валюти.
  2. Зіставляйте події й записи без подвійного зарахування повторів.
  3. Зберігайте оригінали та слід погоджених корекцій.

Часті запитання

Чи потрібен подвійний запис для простого фінтех-продукту?

Якщо ви тримаєте баланси або рухаєте гроші від імені користувачів — так. Журнал лише-на-дозапис не бухгалтерська формальність: саме він робить стан відтворюваним, а помилки — виявними. Додавати його після того, як баланси поїхали, значно важче, ніж почати з нього.

Який найпоширеніший серйозний недолік у ранніх фінтех-системах?

Змінні баланси без журналу, а одразу за ними — відсутність ідемпотентності на платіжних шляхах і вебхуках. Обидва дозволяють грошам стати беззвучно неправильними, і це найважчий для виявлення та найважчий для подальшого усунення режим відмови.

Чи варто зберігати дані карток у себе?

Майже напевно ні. Використовуйте hosted fields або hosted-сторінку оплати провайдера, щоб дані карток ніколи не потрапляли на ваші сервери. Робота з ними самостійно втягує всю вашу інфраструктуру в область дії PCI DSS, а це значний постійний тягар відповідності та аудиту.

Коли фінтех-стартапу робити аудит архітектури?

До першого суттєвого зростання обсягів і перед будь-яким раундом, де очікується технічний due diligence. Наведені структурні рішення дешево перевіряються рано і дорого виправляються після того, як через систему пройшли справжні гроші.

Чи всі валюти мають два десяткові знаки?

Ні. Визначте точність і округлення за валютою та операцією і перевірте вимоги провайдера. Уникайте binary float там, де потрібні точні десяткові обчислення.

Хочете перевірити це на своїй системі?

Ми аудитуємо фінтех-архітектуру саме за цим переліком — цілісність журналу, ідемпотентність, звірка, ізоляція.

Фінтех-аудит →

Читати далі за темою

Технічний due diligence для інвесторів: повний посібник

Технічний due diligence — це не code review. Це відповідь на одне питання: скільки коштуватиме привести цю технологію туди, де її потребує інвестиційна теза?

Аудит архітектури системи: коли він потрібен і що знаходить

Аудит архітектури — це не думка про ваш стек. Це карта того, де система ламається під планом, який ви справді маєте.