ІНЖЕНЕРІЯ
Чому кожен баланс має походити з леджера з подвійним записом
27 липня 2026 р. · 9 хв читання · Coreza
У кожній банківській системі є таблиця, що відповідає на найважливіше питання продукту: скільки грошей у цього клієнта? Проєктне рішення, яке відділяє надійні ядра від крихких, — це те, чи це число зберігається — колонка, яку хтось оновлює, — чи виводиться — як сума записів леджера append-only. Звучить як деталь реалізації. Насправді це різниця між системою, що може довести свої баланси, і системою, що може їх лише стверджувати.
Це найвагоміше архітектурне рішення у фінтех-ядрі — і на демо воно майже невидиме. Два продукти можуть виглядати на екрані однаково, тоді як один оновлює колонку балансу на місці, а інший виводить кожен баланс із леджера з подвійним записом. Різниця проявляється пізніше — у розривах звірки, у тикетах підтримки, які ніхто не може пояснити, і в аудитах.
Що означає подвійний запис в інженерному контексті
Бухгалтерії подвійного запису п’ять століть, але в банківському бекенді це не облікова формальність — це інваріант, який забезпечує база даних. Кожен рух грошей — це транзакція щонайменше з двома записами: один рахунок дебетується, інший кредитується, і записи в сумі дають нуль. Гроші ніколи не створюються й не знищуються оператором UPDATE; вони лише рухаються між рахунками, і сам рух є записом.
Баланс клієнта тоді є проєкцією: сумою всіх записів леджера, що стосуються цього рахунку. Кешованою заради швидкодії — так, але завжди переобчислюваною, і саме переобчислення є правдою. Якщо кеш і леджер колись розійдуться, перемагає леджер, а сама розбіжність — сигнал, що щось потребує розслідування.
Інваріант нульової суми дає властивість, якої не запропонує жоден дизайн зі збереженим балансом: усю систему можна перевірити. Підсумуйте кожен запис на кожному рахунку — гаманці клієнтів, комісійні доходи, розрахункові рахунки провайдерів, транзитні рахунки — і разом вийде нуль. Будь-який баг, гонка чи часткова відмова, що губить гроші, ламає це рівняння і стає виявною, зазвичай того ж дня.
Як розходяться збережені баланси
Режим відмови дизайну з колонкою балансу не драматичний. Це повільний дрейф, який породжує звичайний продакшен-трафік:
- Конкурентність: два виводи читають той самий баланс в одну мить, обидва проходять перевірку, обидва записують. Без леджера немає жодного сліду того, яким баланс мав би бути.
- Повтори та часткові відмови: платіжний провайдер не відповідає вчасно, клієнт повторює запит, і зарахування лягає двічі — або збій між «оновити баланс» і «записати транзакцію» залишає їх назавжди неузгодженими.
- Ручні операції: інженер підтримки закриває скаргу прямим UPDATE. Клієнт задоволений; гроші, що з’явилися, не мають походження, і жоден звіт ніколи їх не пояснить.
- Комісії та округлення: комісія, порахована в одному місці й застосована в іншому, конвертація валюти, округлена по-різному з кожного боку, — частки цента, що накопичуються в реальні розбіжності.
Правила, які нав’язує леджер, — усі на краще
Прихильність до виведених балансів накладає дисципліну на решту ядра. Ці обмеження здаються суворими в перший день і виявляються причиною того, що система залишається коректною на третій рік:
- Цілочисельні суми в мінімальних одиницях — центи, сатоші, wei — ніколи не число з рухомою комою. Двійкові float не можуть точно подати 0,10; леджер, що має давати в сумі нуль, не побудуєш на числах, які сходяться майже.
- Незмінні записи: проведений запис ніколи не редагується й не видаляється. Помилки виправляють так, як банки виправляли їх завжди — сторнувальним записом, що залишає в реєстрі і помилку, і виправлення.
- Ідемпотентність: кожна операція несе ключ, тож повторений запит проводиться один раз. Леджер робить дублікати видимими; ідемпотентність їм запобігає.
- Атомарність: дебет, кредит і зміна бізнес-стану фіксуються разом або не фіксуються взагалі. Жоден шлях у коді не оновлює баланс поза транзакцією леджера — включно з адміністративними коригуваннями, які стають звичайними, атрибутованими записами замість тихих перезаписів.
Звірка: доказ перед зовнішнім світом
Внутрішній інваріант доводить, що система узгоджена сама з собою. Звірка доводить, що вона узгоджена з реальністю. Фінтех-ядро тримає позиції із зовнішніми сторонами — банківськими рейками, картковими процесорами, блокчейн-мережами — і кожна з них веде власну версію правди. Щоденна звірка порівнює кожну виписку провайдера і кожну ончейн-позицію з відповідними рахунками леджера й змушує пояснити кожну різницю: розрахунок у дорозі, ще не проведена комісія провайдера або справжній розрив, який того ж дня отримує транзитний запис і відповідального.
Звірка — це місце, де архітектура окупається. З леджером із подвійним записом розрив — це обмежений пошук: день, коли він з’явився, рахунки, яких він торкнувся, задіяні записи. Зі збереженими балансами те саме розслідування починається з числа без історії — саме тому незвірені різниці в системах із колонкою балансу частіше списують, ніж розв’язують.
Криптоактиви підвищують ставки. Ончейн-баланс публічний: будь-хто може порівняти гаманці, які ви контролюєте, з балансами, які ви показуєте клієнтам. Некастодіальність без леджера, що щодня звіряється з мережею, — це розбіжність, яка чекає, поки її знайде хтось поза компанією.
Що насправді запитують аудитори та регулятори
Рано чи пізно регульований фінтех стикається з якоюсь версією того самого питання: доведіть, що баланси клієнтів правильні. Практична відповідь — це ланцюг доказів: кожен баланс виводиться з леджера append-only; леджер у сумі дає нуль; він щодня звіряється з кожною зовнішньою позицією; а незмінний, скріплений хеш-ланцюгом журнал аудиту фіксує, хто ініціював кожен рух, з якого пристрою і за чиїм погодженням.
Команди, що будують на збережених балансах, відповідають на ці питання криміналістикою — відновлюючи історію з логів застосунку та вивантажень провайдерів, у найгірший можливий момент і під дедлайн. Команди з леджером відповідають одним запитом. Аудит не створює вимогу; він лише показує, чи відповідала їй архітектура від самого початку.
Тест, який варто провести будь-якій платформі core banking
Якщо ви оцінюєте платформу — або переглядаєте ту, яку побудували самі, — ці питання ставляться за п’ять хвилин, а відповіді важко підробити:
- Звідки береться число на екрані клієнта? Якщо відповідь — колонка балансу, а не проєкція леджера, все решта — декорація.
- Чи можна змінити баланс без створення записів у леджері? Запитайте конкретно про адмін-інструменти та процеси підтримки — саме там ховаються тихі UPDATE.
- Чи суми є цілими числами в мінімальних одиницях наскрізно, включно з криптостороною?
- Покажіть учорашню звірку: кожен провайдер, кожна мережа, кожна різниця пояснена. Платформа, яка не може цього показати, цього не робить.
- Як виправляється помилковий запис? Єдина хороша відповідь — сторнувальний запис, атрибутований конкретній людині, за процесом погодження.
Де стоїть Coreza
Coreza побудована на строгій версії цього дизайну: кожен баланс — фіатний і криптовий — виводиться з леджера з подвійним записом; суми всюди є цілими числами в мінімальних одиницях; проведені записи незмінні, а виправлення — сторнувальні записи за погодженням maker-checker; кожен інстанс щодня звіряється з кожним підключеним провайдером і кожною мережею, в якій він працює. Журнал аудиту — append-only і скріплений хеш-ланцюгом: фіксує хто, коли і звідки для кожного руху.
Нічого з цього не видно на демо продукту, і саме в цьому суть цієї статті: леджер — це та частина платформи core banking, яку неможливо оцінити, дивлячись на екрани. Версія цього ядра обробляє реальних клієнтів і реальні гроші в регульованому європейському фінтеху з 2024 року — а п’ять питань вище — це ті, які ми пропонуємо поставити будь-якій платформі, включно з нашою.
Готові побачити свій банк у дії?
Розкажіть нам про свій проєкт, і ми відповімо вам живою демонстрацією платформи та індивідуальною пропозицією для вашого ринку.
Записатися на зустріч