
Разговор про финтех‑платформу почти всегда начинается не с той стороны. Обсуждают выбор брокера сообщений, спорят про микросервисы против монолита, рисуют схему БД. А через полтора года выясняется, что команда из двенадцати человек написала полтора миллиона строк, из которых бизнес‑логики — тысяч двести, а остальное это транспорт, ретраи, дашборды, деплой и попытки понять, где ночью застрял платёж.
Эта статья — про вторую цифру. Про то, сколько стоит слой, который не приносит денег, но без которого система не живёт. И про то, какую его часть сегодня можно просто не писать.
Мы четыре года строим экосистему redb — типизированное хранилище поверх PostgreSQL, MS SQL и SQLite, интеграционный движок, рантайм с кластером и дашбордом, и сервер идентичности с поддержкой OAuth 2.1 и OpenID Connect. Всё это работает в проде, публикуется пакетами и образами, и — важное для этой статьи — все Pro‑возможности бесплатны на всей линейке 3.x, без ключей и лицензионного сервера.
Ниже — разбор платёжной платформы по трём слоям, с расчётом, где именно уходят человеко‑годы. Без кода: технические разборы у нас есть отдельно, здесь речь про деньги, сроки и риски.
Цикл про redb и redb.Route. Свежие статьи — сверху:
redb 3.4.0: переигрываем упавшее, патчим фреймворк без пересборки и раздаём права
redb 3.3.0: решение уровня энтерпрайз на.NET — своя БД, свой Apache Camel и рантайм с дашбордом
redb.Route — уходим от MassTransit, идём к Apache Camel: Kafka, Scatter‑Gather и транзакции
Apache Camel под.NET: HTTP‑коннектор без ASP.NET MVC + Content‑Based Router
Полный список — в профиле. Исходники: github.com/redbase‑app. Про саму БД: redb.ru.
Три слоя, три сметы
Любая платёжная платформа — от процессинга маркетплейса до казначейства холдинга — раскладывается на три части, и у каждой своя природа расходов.
Ядро. Хранит деньги и операции. Проводки, балансы, лимиты, тарифы, сверка. Здесь живёт то, за что вам платят, и здесь же цена ошибки максимальна: неверно посчитанная копейка — это не баг, а претензия.
Фасад. Пускает внутрь. Кто это, что ему можно, чем он подтвердил свои права, как это протоколируется для регулятора и службы безопасности. Слой, который целиком состоит из стандартов и который бизнес не видит — ровно до первого аудита.
Интеграции. Разговаривают с внешним миром. Банк на IBM MQ, эквайер по HTTP, реестры выплат по SFTP, бухгалтерия по расписанию, антифрод по очереди. Слой, где ломается чаще всего и где ломается дороже всего, потому что на другом конце — чужая система, которую вы не чините.
Дальше по каждому слою: что действительно надо писать самим, а что уже написано.
Слой первый: ядро. Деньги, которые не теряются на копейках
Начнём с вещи, которая выглядит технической деталью, а является бизнес‑риском первого порядка: как в системе устроено число, которым меряются деньги.
В большинстве.NET‑проектов сумма приезжает в базу как decimal с точностью, которую кто‑то однажды выставил в конфигурации ORM. Обычно это два знака после запятой, иногда четыре. Дальше начинается: комиссия считается процентом, процент даёт третий знак, третий знак округляется, округления копятся, и через год сверка с эквайером расходится на сумму, которую никто не может объяснить. Это не гипотетический сценарий — это классика жанра, и разбирают её обычно вручную, силами аналитика и разработчика, неделями.
В redb денежная точность зашита не в конфигурации приложения, а в самой схеме хранилища: числовые значения лежат в колонке с точностью 38 знаков, из них 18 после запятой. В комментарии к этой колонке в схеме БД прямым текстом написано, зачем: точные десятичные числа для финансовых расчётов, без потерь, для денег, налогов и процентов, где важна арифметическая точность.
Что это значит на языке бизнеса:
Комиссии, курсы и НДС считаются без накопления ошибки округления. Восемнадцать знаков после запятой — это запас, которого хватает на любую цепочку расчётов, а не «два знака и надеемся».
Мультивалютность и криптовалюты работают из коробки. Восемнадцать знаков — это ровно точность, в которой считается эфир. Если завтра продукт добавляет крипто‑направление, менять хранилище не придётся.
Точность не зависит от того, кто и как настроил проект. Разработчик не может «случайно» объявить сумму с двумя знаками, потому что решение принято уровнем ниже — на уровне хранилища.
Деньги не раздваиваются
Вторая базовая гарантия ядра — что одна операция не выполнится дважды и не выполнится наполовину. Здесь всё стандартно и скучно, как и должно быть в финансах: полноценные транзакции с явным управлением, атомарное выполнение группы операций и построчная блокировка записи на время изменения.
Последнее стоит пояснить, потому что именно на этом обычно ломаются самодельные решения. Классический сценарий: два запроса одновременно читают баланс, оба видят «хватает», оба списывают. Защита — заблокировать строку на время операции. В redb это штатный механизм, и он не декларативный: на нём работают внутренние подсистемы самой экосистемы — хранилище токенов сервера идентичности, счётчик неудачных попыток второго фактора, распределённая блокировка кластера. То есть механизм несёт нагрузку в проде у нас самих, а не существует «на случай, если понадобится».
Удаление, которое можно отменить
Ещё одна вещь, которую в финансах приходится изобретать в каждом проекте, — корректное удаление. Физически удалять нельзя: отчётность, регулятор, разбор инцидентов. Значит либо флаг «удалено» в каждой таблице и его вечное протаскивание во все запросы, либо архивные таблицы и синхронизация с ними.
В redb это встроено и сделано в два этапа. Сначала объект помечается — вместе со всем деревом связанных с ним записей — и мгновенно исчезает из всех обычных запросов, без единой правки в коде выборок. Физическое удаление происходит позже, фоновым процессом, пачками, с сохранением прогресса в базе, так что перезапуск приложения его не роняет и любой узел кластера может его подхватить.
Для бизнеса это два эффекта: интерфейс может честно показывать «Удалено, отменить» и это будет работать, а пользовательская операция удаления не начинает тормозить, когда данных становится много.
Отчётность там же, где данные
Сверка, реестры, отчёты для регулятора и расчёт вознаграждений — это агрегация. Обычно под неё поднимают отдельный контур: выгрузка, хранилище, BI. Отдельный контур — это отдельная команда, отдельные лицензии и вечный вопрос «почему в отчёте не то же, что в системе».
redb считает агрегаты, группировки, оконные функции и фильтрацию по агрегатам на стороне базы, по тем же данным, что обслуживают операции. Отчёт «покажи мерчантов, у которых расхождение по сверке больше порога» — это запрос к боевым данным, а не выгрузка в третью систему.
Справедливое возражение — и что с ним делать
Здесь опытный читатель обоснованно скажет: агрегация по операционному хранилищу на больших объёмах будет медленнее, чем по плоской заранее подготовленной таблице. Это правда, и спорить не с чем.
Только возражение это — про другую задачу. Тяжёлую аналитику на операционном ядре не делают вообще, и не потому что хранилище такое, а потому что это плохая архитектура на любом хранилище. Годовой срез в разрезе десяти измерений не считают на боевой базе ни на чистом PostgreSQL, ни на Oracle, ни на чём бы то ни было ещё: это конкурирует за ресурсы с обработкой платежей, а платежи важнее. Для такой аналитики строят плоские витрины — и будут строить дальше.
Разделим два разных запроса, которые в разговоре обычно склеиваются в один:
Операционные. Узкий срез, свежие данные, ответ нужен сейчас: остаток по лимиту, расхождение по сегодняшней сверке, топ отклонённых за час, сумма в окне для правила антифрода, ранжирование операций внутри партии. Это агрегаты по небольшому объёму горячих данных, и именно они должны считаться там, где данные лежат — иначе вы получаете витрину с задержкой в сутки там, где нужен ответ за секунду.
Аналитические. Широкий период, много измерений, терпит задержку: отчётность, продуктовая аналитика, поиск закономерностей. Это витрины, и так и должно быть.
Смысл встроенных аналитических функций именно в первом классе задач. Они закрывают то, ради чего в обычном проекте либо поднимают витрину раньше времени, либо пишут вручную оптимизированные запросы, либо тащат данные в приложение и считают в памяти.
И второе — витрину не нужно строить отдельным проектом. Регламентная задача «раз в час собрать агрегаты и разложить плоско в отдельную таблицу или поисковый индекс» на нашем стеке — это обычный маршрут с расписанием: планировщик, чтение агрегатов, запись в приёмник. Настройка, а не разработка контура загрузки данных с собственной командой.
Итого: витрины остаются там, где им положено. Просто они перестают быть обязательным условием запуска — а значит уходят из сметы первого года и появляются тогда, когда для них действительно есть повод.
Ничего не спрятано: всегда есть путь вниз
Отдельная гарантия, которую стоит проговорить, потому что она снимает целый класс рисков.
Любая надстройка над базой данных рано или поздно упирается в запрос, который она не умеет выразить. Дальше два пути: обходной манёвр в коде или заявка поставщику с непонятным сроком. В финансовой системе этот момент наступает предсказуемо — на первом же нестандартном требовании от службы безопасности, комплаенса или регулятора.
Здесь такого тупика нет. Структура хранения открыта и подробно задокументирована, и обратиться к ней напрямую обычным SQL можно всегда — силами вашего аналитика, вашего администратора базы, вашими существующими инструментами.
И это не «теоретически возможно, но неудобно». Структура спроектирована так, что нестандартные запросы получаются короткими и быстрыми.
Показательный пример — задача, которая в классической схеме почти невыполнима: найти все объекты, у которых хоть какое‑нибудь поле начинается с заданной строки, независимо от того, к какому типу эти объекты относятся. В обычной реляционной модели это объединение запросов по сорока таблицам с перечислением всех текстовых колонок — либо отдельная система полнотекстового поиска, куда данные ещё надо доставлять и синхронизировать.
Здесь значения всех объектов всех типов лежат в одной таблице, и над ней стоит специализированный индекс для поиска по образцу. Ответ приходит сразу — на миллионах записей и без всякого разбора, к какой сущности что относится. Тем же способом решается и вопрос «а у каких объектов это поле вообще заполнено»: под такие проверки в схеме заведены отдельные индексы по каждому типу значений.
Что это даёт бизнесу:
Внеплановый запрос перестаёт быть спринтом разработки. Комплаенс ищет операции по нестандартному критерию, безопасность разбирает инцидент, регулятор прислал требование в своей формулировке — это работа аналитика на час, а не задача в бэклоге на следующий квартал.
Собственная логика обходится дёшево. Представления, хранимые процедуры, выгрузки в вашу отчётность — штатными средствами СУБД, без обращения к нам и без ожидания доработки.
Данные не заперты. База читается обычными инструментами PostgreSQL или MS SQL без единой строки нашего кода. Это же и аргумент на закупке: сценарий «поставщик исчез» не оставляет вас с нечитаемым хранилищем.
Устройство хранилища расписано в открытой документации: redb.ru/architecture.
Что вы всё равно пишете сами — и почему это правильно
Двойной записи, плана счетов и правил проводок в redb нет. Это не пробел, это граница ответственности.
Модель учёта — это и есть ваш продукт. У процессинга маркетплейса она одна, у казначейства холдинга другая, у эмитента карт третья. Любая попытка вендора «дать готовый ledger» заканчивается тем, что бизнес полгода подгоняет свою модель под чужие абстракции, а потом ещё год живёт с костылями там, где не подошло.
Что даёт redb — это правильный фундамент под вашу модель: точное число, транзакции, блокировки, обратимое удаление и аналитика. Дальше вы описываете проводки обычными классами C#, и они становятся таблицами в базе.
Вот здесь — второй эффект, который бизнес обычно недооценивает.
Изменение схемы данных перестаёт быть событием
В обычном проекте добавление одного поля в платёжную сущность выглядит так: разработчик пишет миграцию, миграция уходит на ревью, ревью цепляет DBA, DBA просит откатный скрипт, скрипт тестируют на стенде, деплой ставят в ближайшее окно. Между «нужно поле» и «поле в проде» — от нескольких дней до нескольких недель, и это в здоровой организации. В банке — дольше.
В redb схема данных описывается обычными классами C#, и хранилище приводит себя в соответствие с ними само. Добавили свойство — оно появилось. Никакой миграции, никакого DDL, никакого согласования.
Три следствия, каждое из которых — деньги.
Первое: проектирование с колёс. Классический подход требует согласованную модель данных до начала разработки. В финансовой платформе эта модель заранее не известна: она выясняется по мере того, как становится понятно, что реально присылает банк‑партнёр и что бизнесу нужно видеть на экране. Значит либо фаза проектирования на месяц‑полтора с попыткой угадать, либо всё равно поток миграций потом. Обычно — и то, и другое.
Когда схема эволюционирует свободно, эта фаза просто не возникает. Команда стартует с базовым набором полей и наращивает по мере понимания. Экономия на масштабе платёжной платформы — 400–900 человеко‑часов, и это до первой строки полезного кода.
Второе: ошибка в модели перестаёт быть дорогой. Классика: поле спроектировали как текст, через месяц выяснилось, что нужен справочник. В обычном проекте это миграция с конвертацией данных, заполнением истории и планом отката — от рабочего дня до нескольких, плюс риск на проде. Поэтому в реальности такие решения чаще всего не принимают: отвечают «переделывать дорого» и живут с костылём до конца жизни системы.
Здесь смена типа поля — это правка класса. А в Pro‑редакции есть механизм, который досчитывает новое поле по уже накопленным данным: добавили «сумму с НДС» — она заполнилась из суммы и ставки по всей истории операций, выражением на C#, без выгрузок и скриптов.
Третье, и самое недооценённое: цена проверки идеи.
Посчитайте, во что обходится проверить продуктовую гипотезу, которая требует нового поля или новой сущности. Придумать, написать миграцию, поднять локальный стенд или подраться за общий, прогнать, а если не подошло — написать обратную миграцию и почистить данные. Честно — от половины дня до дня.
Здесь: добавил свойство, запустил на локальном файле базы, не подошло — удалил свойство. Двадцать минут.
Разница на порядок. И дело даже не в сэкономленных часах, хотя на жизненном цикле проекта это ещё 500 с лишним. Дело в том, сколько вариантов команда вообще успевает рассмотреть. При цене проверки в полдня рассматривают один и берут первый работающий. При цене в двадцать минут рассматривают три‑пять и берут лучший. Это уже не строка в смете, это качество продукта — и оно потом всплывает в конверсии, в количестве обращений в поддержку и в стоимости доработок через год.
Отдельно про локальный стенд. Одно и то же хранилище работает на PostgreSQL, MS SQL и SQLite — код не меняется. Значит разработчику, который правит один небольшой модуль, не нужно поднимать полный контур из базы, брокера, сервера идентичности и соседних сервисов: достаточно файла. Онбординг нового человека сокращается с дней до часов, а автотесты в CI перестают требовать поднятия инфраструктуры на каждую задачу.
Слой второй: фасад. Тот, который увидит аудитор
Свой сервер авторизации в здравом уме сегодня не пишут. Берут готовый — и вот тут начинается развилка, которая стоит денег ещё до первой строки кода.
Коммерческий.NET‑продукт — это лицензия, и для финансовой организации она не в базовом тарифе. Открытый Keycloak — это Java‑стек внутри.NET‑организации: отдельный рантайм, отдельная экспертиза, отдельное дежурство, отдельный цикл обновлений. Оба варианта работают. Оба стоят.
Наш redb.Identity — это OAuth 2.1 и OpenID Connect, встроенные в тот же стек, на том же хранилище, под тем же рантаймом. Что важно бизнесу в этой части:
Стандарты не на слайдах, а в коде. В исходниках сервера поимённо упомянуты 40 RFC — не как список желаний, а рядом с реализацией и тестами, которые эту реализацию проверяют. Полный набор того, что спрашивает безопасник: обязательный PKCE, привязка токенов к ключу клиента, предварительная регистрация запросов авторизации, динамическая регистрация клиентов, аутентификация клиента по подписанному ключу, обмен токенов, поток для устройств без браузера, интроспекция, отзыв, выход по обратному каналу.
Проверено внешним арбитром. Сервер прогоняется против официального пакета соответствия OpenID Foundation — того самого, которым Фонд сертифицирует провайдеров. Конфигурационный профиль проходит без единого замечания, модули основного профиля с кодом авторизации — зелёные. Формальная сертификация — следующий шаг, и мы её не заявляем как свершившуюся. Но факт прогона против внешнего эталона — это то, чего большинство самописных и даже покупных.NET‑решений не делают вообще, и на аудите это разговор совсем другого качества.
Аудит и вторые факторы — из коробки. Многофакторная аутентификация: одноразовые коды, коды по SMS и почте, аппаратные ключи по стандарту FIDO2, коды восстановления. Управление пользователями по корпоративному стандарту SCIM — то есть кадровая система заводит и отключает сотрудников автоматически. И 79 типов событий аудита в семи категориях, которые пишутся в базу и, если нужно, параллельно уезжают в вашу систему мониторинга безопасности. Не «логи, из которых можно что‑то восстановить», а типизированные события: вход не удался, второй фактор не прошёл, обнаружена попытка повтора токена, секрет клиента сменён, все сессии пользователя отозваны.
Один и тот же продукт на трёх базах. Полный набор тестов сервера — а это больше 1700 проверок — проходит одинаково на PostgreSQL, MS SQL и SQLite, переключением одной настройки. Для организации, где выбор СУБД — это отдельный разговор с инфраструктурой, снимает целый класс вопросов.
Экономия, которую не видно в смете
Есть архитектурная деталь, которая выглядит технической, но напрямую конвертируется в железо.
В обычной схеме каждый внутренний вызов между сервисами проходит авторизацию, а авторизация — это поход по сети к серверу идентичности. На заметном трафике сервер идентичности превращается в узкое место, в единую точку отказа и в постоянную добавку к времени ответа.
У нас модули, работающие в одном рантайме, обращаются к серверу идентичности внутри процесса — вообще без сети. Ни сокета, ни шифрования канала, ни сериализации ради самого себя. При этом снаружи он остаётся нормальным сервером со стандартными протоколами: браузерная часть работает по HTTP, потому что стандарт требует браузер, а всё остальное — выдача токенов, обновление, интроспекция, отзыв, управление, справочники — транспортно‑нейтрально.
По нашим замерам, трёхузловая конфигурация держит порядка пяти тысяч запросов на выдачу токена в секунду с временем ответа в районе 50–80 мс на девяносто девятом перцентиле. Для бизнеса это переводится просто: меньше узлов под авторизацию и на одну точку отказа меньше.
Вход в сервер вы делаете сами — на своём транспорте и со своим шифрованием
Здесь архитектурная развилка, последствия которой выходят далеко за финансы — она касается любой распределённой системы, где узлы общаются по разным каналам.
В обычном сервере идентичности протокол и транспорт склеены: сервер умеет HTTPS, и это всё, что он умеет. У нас транспорт отделён от протокола — HTTP это просто первый переходник, а не часть сервера. Все операции, кроме тех, что по стандарту требуют браузера, транспортно‑нейтральны.
Что это открывает.
Один источник правды о правах — много входов. Реальная распределённая система редко общается по одному каналу. Часть узлов сидит в закрытом контуре и ходит через туннель. Часть площадок связана корпоративной шиной сообщений, потому что так решили десять лет назад и менять никто не будет. Партнёрские интеграции идут по публичному каналу. Устройства на периметре не умеют современный HTTP вовсе. Филиалы и подрядчики — каждый со своим регламентом подключения.
Обычный сервер идентичности предполагает, что канал один и это HTTPS. Дальше выбор из двух плохих вариантов: либо тянуть всё в HTTPS — и тогда закрытый контур приходится приоткрывать, либо ставить несколько серверов под разные каналы — и тогда у вас несколько источников правды о том, кому что можно. Второе хуже: расхождение прав между контурами обнаруживается обычно постфактум и обычно неприятно.
Здесь ядро одно — то самое, стандартное, которое проходит проверку соответствия и понятно аудитору. А входов в него столько, сколько у вас каналов, и каждый вы делаете под свой: свой транспорт, свой конверт, своё шифрование, свой формат кадра. На входе развернули, на выходе завернули; ядро об этом не знает и знать не должно. Добавление такого входа не меняет в сервере ни строки — это отдельный модуль, который кладут рядом. Убрать его — удалить файл.
Частные случаи одного и того же механизма: межфилиальный контур со своей криптографией по требованию регулятора; закрытая площадка, где разрешена только корпоративная шина; партнёрский канал со своим форматом; устройства, говорящие по простому протоколу интернета вещей. Везде ядро общее, права общие, аудит общий — разные только переходники.
Сокращение поверхности атаки. Сценарий, который редко проговаривают. Сервер идентичности обязан стоять на публичном адресе: браузеры, мобильные приложения, обратные вызовы внешних провайдеров, выход из сессии по обратному каналу — всё это требует публично разрешаемого адреса. Универсальный туннель поверх него не натянуть.
Но административные операции — ротация подписных ключей, принудительный отзыв доступа, заведение первого администратора, изменение клиентов — публичными быть не обязаны. Их можно вынести на отдельный порт, в отдельную сеть и на собственный формат обмена: свои маркеры, своя версия протокола, своя проверка подлинности.
Эффект тут не криптографический, а практический: массовые сканеры и стандартные наборы эксплойтов такой формат просто не понимают. Атакующему сначала нужно разобраться в нём, чтобы сформировать хотя бы синтаксически корректный запрос. Каждый день этой задержки — день форы для службы безопасности. Приём давно известен банкам и госсектору, но раньше требовал переписывания стека под собственный протокол; здесь это отдельный модуль перед стандартным ядром.
Оговорка обязательная: это дополнительный слой, а не замена защите. Проверка прав и подпись остаются на месте на каждой операции. Нестандартный формат обмена не заменяет криптографию — он добавляет к ней асимметрию информации.
Где мы честно не закрываем
Если ваша платформа выходит в регулируемое открытое банкинг‑взаимодействие — то есть вы работаете как сторонний провайдер услуг или как банк, обслуживающий таких провайдеров, — потребуется доработка. Не реализованы взаимная аутентификация по сертификатам, детализированные запросы авторизации (когда согласие даётся на конкретный платёж конкретному получателю), развязанное подтверждение через банковское приложение и повышение уровня аутентификации под операцию.
Это осознанная граница, а не пробел. Криптографическая основа под всё перечисленное в сервере уже есть — привязка токенов к ключу владельца реализована и покрыта тестами, — так что речь про спринт доработки с понятным объёмом, а не про переписывание.
Для всего остального — процессинга собственной платформы, кошелька, маркетплейсовых выплат, корпоративного казначейства, B2B‑платежей, биллинга — сервер закрывает задачу сегодня и целиком.
И да, для обычного биллинга это тоже работает
Отдельно проговорим, потому что после разговора про платёжные ядра легко решить, что стек рассчитан только на тяжёлые сценарии.
Биллинг — подписочный, телеком, коммунальный, SaaS — попадает в наши сильные стороны едва ли не точнее, чем процессинг:
Тарифы меняются постоянно, и это главная боль биллинга. Новый тариф — это новые поля и новые правила. Там, где обычно каждый пересмотр тарифной сетки означает миграцию базы и релизное окно, здесь это правка класса и выкатка без остановки начислений.
Пропорциональные начисления — это дроби. Пересчёт при смене тарифа в середине периода, посуточные списания, частичные возвраты — всё это множится и делится, и именно тут копятся ошибки округления, из‑за которых потом расходятся акты. Точность на уровне хранилища снимает вопрос.
Регулярные начисления — это расписание. Планировщик встроенный, начисление по расписанию — обычный маршрут, а не отдельный сервис с собственным дежурством.
Неудавшийся платёж надо повторять по правилам. Повторные попытки списания с задержками, очередь недоставленного, ручное переигрывание из интерфейса поддержки — ровно то, что мы разбирали выше.
Счета и сверка — это агрегация, которая считается там же, где данные.
И главное для небольшой команды: входного взноса за сложность здесь нет. Кластер, координатор и дашборд не обязательны — стек нормально живёт одним процессом на одном сервере, а всё перечисленное включается настройкой тогда, когда дорастёте. Это принципиально отличается от корпоративных платформ, где вы платите за всю сложность сразу и на старте, независимо от того, нужна она вам сегодня или нет.
Слой третий: интеграции. Здесь ломается чаще и дороже всего
Финансовая интеграция устроена не так, как её рисуют на архитектурных схемах. На схеме — красивая шина и события. В жизни — банк‑партнёр, который принимает только IBM MQ, потому что его ядро написано в двухтысячных и переписывать его никто не будет. Реестр выплат, который приезжает файлом на SFTP в четыре утра. Эквайер с обычным HTTP и своим представлением о том, что такое идемпотентность. Бухгалтерия, которой нужна выгрузка по расписанию. И антифрод в очереди.
Ключевая мысль тут вот какая: в интеграции побеждает не тот, у кого красивее шина, а тот, кто говорит на языке контрагента. Потому что контрагента вы не поменяете.
redb.Route — это 27 транспортов из коробки. Для сравнения: популярные.NET‑библиотеки для обмена сообщениями дают от четырёх до семи, и все — брокеры. Они исходят из того, что вокруг вас такие же современные сервисы. В финансах это не так.
Что есть у нас и что реально нужно платёжной платформе:
Что в реальности |
Чем закрывается |
|---|---|
Ядро банка на IBM MQ |
Полноценный транспорт с транзакциями, а не самописный адаптер |
Реестры и выписки файлами |
SFTP, FTP, файловая система с опросом каталога |
Эквайеры и партнёрские API |
HTTP, gRPC, вебсокеты |
Событийная шина |
Kafka, RabbitMQ, AMQP, Azure Service Bus, Amazon SQS/SNS |
Legacy на прямых запросах к БД |
Опрос базы по расписанию и запись в неё |
Уведомления |
Почта, Telegram, push |
Клиринг и регламентные задачи |
Планировщик с расписанием |
Про IBM MQ стоит сказать отдельно, потому что это индикатор зрелости. У нас он поддержан не «чтобы был», а с настоящей транзакционной семантикой — включая счётчик неудачных обработок и автоматический перевод «отравленного» сообщения в отдельную очередь после порога. Кто интегрировался с банковским ядром, тот знает: без этого одно битое сообщение крутится в очереди сутки и забивает канал.
Платёж, который не уйдёт дважды
Главный технический риск интеграции в финансах — повторная доставка. Сеть моргнула, подтверждение не дошло, отправитель повторил, платёж ушёл дважды. Разбор такого инцидента — это претензия клиента, ручная сторнирующая проводка и объяснительная.
В redb.Route на это есть три уровня защиты, и их можно комбинировать:
Транзакционная обработка. Подтверждение получения сообщения брокеру и отправка результата дальше происходят вместе: либо и то, и другое, либо ничего. Реализовано одинаково для RabbitMQ, IBM MQ, AMQP и Kafka — то есть смена брокера не переписывает логику.
Защита от повторов с сохранением состояния. Ключ операции сначала резервируется, и только после успешной обработки подтверждается. Если процесс упал посередине, ключ остаётся неподтверждённым и операция корректно повторяется. Состояние живёт в базе, а не в памяти, — значит работает на всём кластере и переживает перезапуск.
Гарантированная публикация. Классическая схема, когда событие пишется в ту же транзакцию, что и бизнес‑операция, а отдельный процесс его потом публикует.
Здесь нам часто задают вопрос: почему это не одна кнопка «включить гарантии», как у некоторых конкурентов. Ответ практический. Готовый «контейнер гарантий» тащит свою таблицу, свою схему и своё представление о том, как выбирать неотправленное. В финансах эта таблица регулярно обязана жить в чужой базе, схему которой вы не контролируете, а условие выборки — не «где не отправлено», а бизнес‑правило с приоритетами, окнами и лимитами. Прибитая реализация в такой ситуации не удобство, а блокер. У нас это несколько строк настройки, где запрос ваш, таблица ваша и транзакция ваша.
Про международные форматы
Отдельный вопрос, который всегда возникает: а ISO 20022?
Готовых кодеков финансовых сообщений — ISO 20022, ISO 8583, SWIFT MT — в поставке нет. Это честно, и это ниша для тех, кому нужно: транспорт, кадрирование и валидация есть, сам разбор формата вы пишете под свой профиль. И, скажем прямо, всё равно пишете: профили ISO 20 022 у каждого банка свои, и «готовый кодек» всё равно допиливается.
Что помогает: ISO 20 022 — это XML со схемой, а проверка сообщения по XSD в наших маршрутах встроенная. То есть валидация платёжного поручения по официальной схеме — это шаг конвейера, а не отдельная разработка. Для JSON‑форматов то же самое через JSON Schema.
Три часа ночи: сколько стоит застрявший платёж
Теперь про то, чего нет ни в одной презентации, но что определяет реальную стоимость владения.
Платёж застрял. Не «система упала» — упавшую систему видно и её чинят. Именно застрял: одна операция где‑то в середине конвейера получила ошибку от внешнего сервиса и не доехала. Клиент звонит утром.
Как это выглядит в типичном проекте: разработчик идёт в логи, восстанавливает по ним, что было в сообщении, руками собирает запрос, отправляет повторно, молится, чтобы не задвоилось. Занимает от часа до дня, требует разработчика — не поддержку, — и делается под давлением.
Как это выглядит у нас:
Маршрут может нести точку сохранения. Не «лог того, что происходило», а снимок состояния операции в конкретном месте конвейера.
Если дальше по маршруту случилась ошибка, снимок автоматически попадает в очередь недоставленного, которая живёт в базе — на PostgreSQL, MS SQL или SQLite, на выбор.
Оператор поддержки открывает дашборд, видит список застрявших операций с причиной и временем, и нажимает «Переиграть». Операция уходит обратно в свой маршрут — из точки сохранения, а не из того мусора, в который состояние превратилось по дороге к падению.
Две детали, которые показывают, что это делалось для реальной эксплуатации, а не для галочки:
Захват включается осознанно. В очередь попадает только то, что разработчик пометил как переигрываемое. Система никогда не присваивает себе операцию, которую ей не отдали, — иначе очередь недоставленного превращается в свалку, куда никто не смотрит.
Есть защита от двойного владения доставкой. Если точку сохранения поставили на маршрут, где повторной доставкой и так управляет брокер или транзакция, движок предупреждает об этом. Именно эта ошибка — когда за повтор отвечают двое — и даёт двойное списание.
К этому прилагается сторож, который сам классифицирует маршруты и поднимает тревогу по зависшим, и отслеживание операций «в полёте» — видно, какое сообщение прямо сейчас в каком шаге конвейера находится.
Что это значит для бюджета. Разбор застрявших операций перестаёт быть работой разработчика и становится работой первой линии. По нашей оценке это 2–4 часа в неделю квалифицированного времени, которое возвращается в разработку, — но главное даже не часы, а то, что ночная эскалация к разработчику перестаёт быть нормой.
Регуляторика: утром разъяснение — вечером в проде
Финансовая организация живёт в потоке изменений, которые не она инициирует. Вышло разъяснение регулятора, поменялась ставка, добавилось обязательное поле в отчётности, изменился формат обмена с партнёром. Сроки — не ваши.
Посмотрите, из чего в обычном проекте складывается путь от «вышло разъяснение» до «работает в проде»:
Правка кода — часы.
Миграция базы, если изменилась структура, — дни на согласование.
Сборка, тестирование — часы.
Согласование окна релиза — дни или недели.
Остановка сервиса, деплой, проверка, план отката.
Обратите внимание: собственно разработка — это первый пункт и он самый короткий. Всё остальное — это право на деплой, и оно занимает основную часть срока.
Как этот путь выглядит на нашем стеке:
Правка — новое поле это свойство класса, миграции нет.
Модуль собирается и подписывается вашим ключом в вашем конвейере сборки. Ключевая пара генерируется одной командой, рантайму известна только публичная половина.
Загружается в рантайм — через управляющий интерфейс или файлом.
Рантайм проверяет подпись до того, как выполнится хоть одна строка кода из пакета. Решает публичный ключ, а не то, кто положил файл. Неподписанное отклоняется.
Замена на ходу: старая версия дорабатывает начатые операции, новая стартует параллельно, и только после подтверждения работоспособности старая снимается. В кластере это катится по узлам по одному.
Платёжный поток не останавливается. Право на деплой сведено к «подпись валидна». Откат — это загрузка предыдущего пакета.
Утром вышло разъяснение, днём правка и сборка, вечером выкатка по узлам. Не героизм дежурной смены, а штатная процедура.
Для бизнеса это две разные вещи сразу: скорость реакции на регулятора — и отсутствие простоя как класса. Второе в финансах часто дороже первого: согласованное окно обслуживания — это не только недоступность, это ещё и заявка, уведомление клиентов и репутационная стоимость.
Команда платформы, которой у вас нет
Есть слой, который в проектах до пятидесяти человек не пишут никогда. Не потому что не умеют — потому что он не окупается в рамках одного продукта. Речь про эксплуатационную обвязку: управляющий интерфейс, командную строку, дашборд, координацию узлов, метрики, сторожа, деплой.
Вместо него получается стандартный набор: три скрипта деплоя, просмотр логов, и «зайди на сервер, посмотри». Работает, пока система маленькая.
В нашем рантайме redb.Tsak этот слой приезжает вместе с продуктом:
Дашборд — 10 экранов: обзор кластера, трёхуровневое дерево топологии, детализация по узлу с живыми графиками нагрузки, все маршруты со счётчиками и долей ошибок, разбор конкретного маршрута с операциями «в полёте», очередь недоставленного с кнопкой переигрывания, сторож зависших, поиск по логам, управление ключами доступа.
Командная строка — 43 команды. Не «запустить‑остановить», а полноценный пульт: подписать модуль, выкатить, проверить, откатить, вывести узел из‑под нагрузки, вернуть, перераспределить, посмотреть диагностику, переиграть недоставленное, поставить планировщик на паузу.
Управляющий API — 16 контроллеров, больше 45 методов, с типизированным клиентом. То есть всё вышеперечисленное встраивается в ваш существующий контур управления, а не требует ходить в отдельную панель.
Наблюдаемость — метрики в формате Prometheus, готовый дашборд Grafana файлом, три раздельные пробы состояния под Kubernetes, полный набор манифестов включая интеграцию с оператором мониторинга. И отдельно — сквозная трассировка, о которой стоит сказать подробнее.
«Где мой платёж» — вопрос, на который обычно нет быстрого ответа
Клиент звонит и спрашивает, где его деньги. Операция прошла через входящий запрос, проверку прав, антифрод, очередь, банк‑партнёра и обратно — пять систем, у каждой свои логи со своим форматом времени.
В обычном проекте ответ ищут сопоставлением логов по временным меткам и обрывкам идентификаторов. Занимает это от получаса до дня и требует человека, который помнит, как всё связано.
Правильное решение известно — сквозная трассировка: одна операция получает идентификатор, который протаскивается через все системы, и потом весь её путь видно единой цепочкой с длительностью каждого шага. Проблема в том, что своими силами это отдельный проект: выбрать стандарт, протащить контекст через все границы процессов и все транспорты, инструментировать каждый коннектор, поднять сборщик, научить команды им пользоваться.
У нас трассировка встроена в интеграционный движок, а рантайм подхватывает её сам. Модуль положили — его маршруты уже в трассировках и метриках, без единой строки настройки в прикладном коде. Счётчики обработанных и упавших операций, распределение времени обработки, количество операций прямо сейчас в работе — всё это есть с первого запуска. Отправка в Jaeger или любой совместимый сборщик включается одной настройкой; свои спаны и свои счётчики добавляются в ту же трубу.
Две инженерные детали, которые показывают, что это делали для эксплуатации:
Сбор идёт всегда, отправка — по требованию. Трассировки формируются постоянно, независимо от того, включена ли выгрузка наружу. Значит подключить сборщик на время разбора инцидента можно не перевыкатывая систему.
Наблюдаемость не имеет права уронить систему и не имеет права быть дырой. Перед запуском экспорт метрик проверяет доступность порта и при неудаче просто пишет предупреждение, продолжая работу без метрик — потому что необязательная подсистема не должна ронять платёжный контур. А сам сборщик слушает только локальный интерфейс: наружу метрики отдаёт основной API, так что телеметрия физически не может случайно оказаться открытой в сеть.
Для бизнеса это переводится коротко: вопрос «где застряло» решается за минуты и силами поддержки — а не за день и силами разработчика, который помнит архитектуру.
Расти вширь — это запустить ещё один процесс
Отдельно про масштабирование, потому что это прямая статья капитальных затрат.
Переход от одного узла к трём в нашем рантайме — это тот же конфигурационный файл на всех узлах, отличаются только идентификатор узла и его адрес. Узлы находят друг друга через общее хранилище, выбирают ведущего, ведущий распределяет модули и катит обновления по одному узлу.
Ни отдельной системы обнаружения сервисов, ни внешнего координатора, ни сервисной сетки. И ни строки нового кода.
Обратно — так же: узел выводится из‑под нагрузки одной командой, дорабатывает начатое и снимается.
Важная деталь для больших платформ: узлы не обязаны быть одинаковыми. Размещение хранится по модулю, с привязкой к группе. Значит группа «эквайринг» может нести один набор модулей, «выплаты» — другой, «отчётность» — третий, всё под одним координатором. Это позволяет разделять контуры по нагрузке и по критичности, не разводя их в отдельные системы со своей эксплуатацией.
И контейнеры — как удобно. Три варианта образа: отдельный рабочий узел под Kubernetes, отдельный узел управляющего интерфейса, и всё‑в-одном для установки на один сервер. Готовые наборы для развёртывания, манифесты Kubernetes, вариант вообще без контейнеров архивом. Образы подписаны. Нужна своя сборка со своими коннекторами — обычная стандартная сборка.NET, без закрытого инструментария.
Во что это оценивается
Если бы этот слой пришлось строить самим — по компонентам, консервативно:
Компонент |
Человеко‑часы |
|---|---|
Управляющий API |
250–350 |
Командная строка |
150–250 |
Веб‑дашборд |
400–600 |
Координация узлов: выборы ведущего, реестр, распределение |
250–350 |
Обновление без простоя с корректным завершением |
100–150 |
Очередь недоставленного с переигрыванием |
100–150 |
Сторож зависших процессов |
60–100 |
Метрики, сквозная трассировка, пробы состояния |
310–480 |
Образы, наборы развёртывания, манифесты, подписи |
210–330 |
Проверка подписи загружаемых модулей |
40–60 |
Итого |
1870–2820 |
Это больше человеко‑года — до единственной строки бизнес‑логики. И, повторим, обычно этот слой просто не строят: живут без него, а цену платят потом, в виде ночных эскалаций и часов на разбор инцидентов.
Железо: почему на том же трафике нужно меньше узлов
В смете платформы есть строка, о которой в статьях про технологии не пишут почти никогда, — счёт за инфраструктуру. А он определяется не трафиком как таковым, а тем, сколько лишней работы система делает на каждой операции. Здесь два механизма, которые дают экономию не разово, а каждый месяц.
Не собирать заново то, что не менялось
Стандартное поведение почти любого слоя доступа к данным: запросили список из пятисот операций — пятьсот раз собрали объект из строк базы. Открыли следующую страницу, вернулись назад — собрали заново. Работа процессора, которая не создаёт никакой ценности.
В redb у каждого объекта есть контрольная сумма, и загрузка устроена в два шага. Сначала идёт дешёвый запрос — только идентификаторы и контрольные суммы, без обращения к значениям полей. Затем результат сверяется с тем, что уже лежит в памяти, и дозагружаются только реально изменившиеся объекты. Остальные отдаются из кэша без повторной сборки.
То же самое на запись: если объект не изменился, он до базы просто не доезжает.
И это корректно работает в кластере — вот что здесь важнее всего. Контрольная сумма приезжает из базы свежей при каждом запросе. Значит если один узел изменил операцию, второй при следующем обращении увидит расхождение и перечитает её сам. Не нужен ни отдельный кэш‑сервер со своей эксплуатацией и своим счётом, ни рассылка уведомлений об устаревании между узлами — механизм, который в распределённых системах ломается чаще всего и тише всего.
Режим выбирается настройкой, и по умолчанию стоит безопасный — с проверкой. Монолитное приложение может проверку отключить и стать ещё быстрее; распределённое оставляет как есть и получает корректность бесплатно.
Не держать поток ради ожидания
Второй механизм — про то, чем платёжная система занята большую часть времени.
А занята она ожиданием. Ответа эквайера. Подтверждения банка. Вердикта антифрода. Записи на диск. Собственно вычислений там доли процента.
В синхронной модели каждое такое ожидание удерживает поток выполнения. Потоки — это память и переключения контекста, и заканчиваются они значительно раньше, чем процессорное время. Отсюда знакомая картина: сервер загружен на пятнадцать процентов, а новые запросы уже становятся в очередь.
Движок маршрутов асинхронный по построению: в его ядре полторы сотни асинхронных методов против восьми блокирующих вызовов — и все восемь находятся в синхронных обёртках, сделанных для удобства вызова, а не в конвейере обработки. Пока операция ждёт ответа от внешней системы, поток обслуживает другие.
Практический смысл: один узел держит существенно больше одновременных операций на том же процессоре. Для платёжного шлюза, где ожидание составляет почти всё время обработки, это разница не в проценты.
Что это значит в деньгах
Экономия ресурсов конвертируется по цепочке, и каждое звено — отдельная строка бюджета:
Меньше ядер на узел — а лицензии на промышленные СУБД и часть корпоративного ПО считаются по ядрам.
Меньше узлов на тот же трафик — прямой счёт за облако или за железо.
Резервный контур дублирует основной, поэтому любая экономия на основном автоматически удваивается.
Меньше нагрузки на саму базу данных — а база в финансовой системе обычно самый дорогой компонент и самый трудный в масштабировании: приложение вы добавите узлом, базу — нет.
Конкретных процентов мы здесь намеренно не приводим: они зависят от профиля нагрузки, и любая красивая цифра в такой статье была бы цифрой из вакуума. Но механизм проверяемый, и на своих нагрузках вы его увидите сразу.
Важно, что это постоянная экономия. Сэкономленные человеко‑часы разработки — это разовая выгода. Счёт за инфраструктуру приходит каждый месяц, все годы жизни системы.
Люди: почему единый стек дешевле в эксплуатации
Есть эффект, который в сметах не появляется никогда, а в реальности стоит больше миграций.
Возьмите обычный.NET‑проект, который прожил два года и полсотни доработок. Что вы там найдёте: два стиля контроллеров, потому что подход менялся. Три подхода к валидации. Два способа фоновой работы — планировщик, который завели в начале, и второй, который добавили, когда первый не подошёл. Самописный маппер рядом с библиотечным. И слой доступа к данным, который половина команды обходит напрямую, потому что «так быстрее».
Это никого не удивляет, потому что так происходит всегда, когда каркас выбирается заново на каждой задаче.
Наша экосистема эту свободу ограничивает — намеренно. Правил ровно три: структура данных — это класс, точка входа — это маршрут, интеграция — это коннектор. Не потому что мы против разнообразия, а потому что разнообразие в фундаменте оплачивается вечно.
Что это даёт в деньгах:
Онбординг. Новый разработчик изучает один подход, а не пять «исторически сложившихся». Разница — 3–5 дней на человека. При команде в десять человек и нормальной текучке это 150–250 часов в год.
Ревью. Спор «а как правильно» просто не возникает, потому что форма одна. Полчаса‑час на запрос на слияние, полторы сотни запросов в год — ещё 75–150 часов.
Рефакторинг, которого не происходит. В разношёрстном проекте раз в полтора‑два года случается инициатива «приведём всё к единому виду» на 200–400 часов, которая наполовину не доводится до конца. Здесь приводить не к чему — уже едино.
Зависимость от людей. Это уже не про часы. Когда каркас однородный, уход ключевого разработчика не уносит с собой знание «почему здесь сделано вот так, а там иначе». Для финансовой организации, где смена команды — реальный операционный риск, это отдельная строка в оценке.
Закупка: то, о чём разработчики не думают, а директор думает
Три вопроса, которые всплывают на согласовании и способны остановить проект уже после того, как техническая часть всех устроила.
Лицензии. Все Pro‑возможности — оптимизированные запросы, частичная запись изменений, параллельная материализация, кластер, расширенная аналитика — бесплатны на всей линейке 3.x. Без ключа, без лицензионного сервера, без регистрации, включая коммерческую эксплуатацию. Не «бесплатно до определённого объёма», не «бесплатно для разработки». Просто бесплатно. Версии, которые вы уже используете, остаются бесплатными навсегда.
Открытая часть — это Apache 2.0. Pro‑пакеты закрытые, но бесплатные.
Исходный код. Компаниям, которые выбрали экосистему, исходники Pro отдаются по запросу — под аудит безопасности, депонирование или собственную сборку. В банковской закупке депонирование исходного кода — это не бонус, а строка в требованиях к проприетарному компоненту, и обычно она стоит отдельных денег и отдельных переговоров.
Отсутствие привязки к поставщику. Данные лежат в PostgreSQL или MS SQL — в вашей базе, вашей инфраструктуры, под вашим управлением. Структура хранения открыта и задокументирована, так что база читается обычным SQL, без нашего кода и без наших инструментов. Есть штатная выгрузка и загрузка всей базы, в том числе между разными СУБД. Закрытых форматов нет нигде. Худший сценарий — «поставщик исчез» — оставляет вас с работающей системой, вашими данными в читаемом виде и, при необходимости, исходниками.
Для сравнения: типичная альтернатива по фасаду — это либо коммерческая лицензия, которая для финансовой организации идёт по корпоративному тарифу, либо открытый продукт на чужом стеке, который требует собственной команды эксплуатации.
Смета целиком
Соберём всё, о чём говорили выше, в одну таблицу. Это модель с явными допущениями, а не замер двух параллельных команд — но допущения консервативные, и каждую строку можно оспорить отдельно.
Разовые затраты, которых не возникает:
Что не пишется |
Человеко‑часы |
|---|---|
Транспорты — 9 реально нужных платёжной платформе, промышленного качества |
900–1350 |
Шаблоны интеграции — защита от повторов, разделение, агрегация, маршрутизация, ретраи, автоматический выключатель, компенсации |
400–800 |
Эксплуатационный слой — API, командная строка, дашборд, кластер, наблюдаемость, деплой |
1870–2820 |
Фасад идентичности — внедрение, управление клиентами, аудит, второй фактор, федерация |
600–1000 |
Фаза проектирования модели данных, которой не происходит |
440–880 |
Проверка продуктовых гипотез — дешевле в 10–15 раз |
~560 |
Итого |
4770–7410 |
Это 2,8–4,4 человеко‑года.
Ежегодные затраты, которых не возникает:
Что |
Человеко‑часы в год |
|---|---|
Миграции базы данных |
360–600 |
Подготовка и проведение релизных окон |
~450 |
Разбор застрявших операций силами разработки |
100–200 |
Поддержка собственных коннекторов при обновлении внешних систем |
150–250 |
Онбординг и ревью на разнородном каркасе |
225–400 |
Итого |
1285–1900 |
Это 0,8–1,1 постоянной ставки.
По ставке 4 000 ₽/час это 19–30 млн ₽ разово и 5–7,6 млн ₽ ежегодно. Плюс отсутствие лицензионных платежей и закрытый вопрос депонирования исходников.
Ставка здесь — полная стоимость часа для компании: оклад, налоги, страховые взносы, рабочее место, управление, отпуска и простой. Не сумма в оффере — её обычно и подставляют по ошибке, занижая результат в два‑три раза. Четыре тысячи — это осознанно нижняя граница; подставьте свою и пересчитайте, часы от неё не зависят.
Оговорка честная: считать это экономией корректно только там, где команда действительно построила бы всё сама. Организация, которая закупила бы готовое, получает выгоду в другой форме — в отсутствии лицензий и в отсутствии интеграционного зоопарка. И часы на вашу бизнес‑логику — модель учёта, тарификацию, антифрод, сверку — не экономит никто и не должен: экономится инфраструктурный слой под ними.
Где мы вам не подойдём
Раздел, который обычно не пишут. Мы напишем, потому что понимать границу дешевле в начале, чем на середине проекта.
Модель учёта — ваша. Двойной записи, плана счетов и правил проводок в поставке нет и не планируется. Мы даём фундамент, вы описываете свой учёт. Если вы искали готовый процессинг «под ключ» — это не он.
Регулируемое открытое банкинг‑взаимодействие требует доработки. Если платформа выходит наружу как сторонний провайдер или как банк, обслуживающий таких провайдеров, — нужен спринт по нескольким стандартам, перечисленным выше. Основа под них есть, объём понятен, но сегодня из коробки этого нет.
Кодеки финансовых сообщений вы пишете сами. Транспорт, кадрирование и валидация по схеме есть, разбор конкретного профиля ISO 20 022 или ISO 8583 — ваш.
Мультирегиональный кластер из коробки не поддерживается. Координация рассчитана на низкие задержки до общей базы. Схема для географического резервирования — кластер на регион, связка выше уровнем.
Горизонтальное разделение базы на части — конструктор, а не готовая функция. Все необходимые механизмы в хранилище есть: генерация ключей блоками с возможностью вынести источник в отдельную базу, изоляция кэшей по подключению, несколько независимых хранилищ в одном модуле. Собранного решения «включить и поехали» пока нет. Это тема отдельной статьи, и она в работе.
Изоляция модулей — не песочница. Загружаемый модуль работает с правами процесса: доверие обеспечивается подписью на входе, а не ограничением прав после запуска.
На корпоративную практику это почти не влияет. Подрядчик сдаёт исходный код, сборка идёт в вашем конвейере и подписывается вашим ключом — пара генерируется одной командой, проверяющая сторона знает только публичную половину. Тогда подпись означает не «мы доверяем подрядчику», а «это ровно тот код, который прошёл наше ревью и нашу сборку», и это строже, чем любая песочница вокруг чужого бинарника.
Настоящее ограничение остаётся для одного сценария: если модуль приходит готовым бинарником от поставщика, которого вы не контролируете и чей код не видели. Здесь потребуется изоляция уровня операционной системы — отдельный процесс или контейнер на модуль.
Итог
Платёжную платформу нельзя купить готовой — та часть, за которую вам платят, всегда пишется под вас. Но она составляет меньшую часть кода и меньшую часть бюджета.
Большая часть — это транспорт до банка, который говорит на IBM MQ. Это защита от двойного списания. Это сервер авторизации, который пройдёт аудит. Это дашборд, где видно, где застряла операция. Это деплой без остановки платежей. Это координация узлов, когда одного стало мало. И это примерно три человеко‑года плюс постоянная ставка на поддержку — если писать самим.
Наша ставка последних четырёх лет в том, что этот слой должен быть общим. Один стек на все три части платформы, одна версия на всю экосистему, одни правила для всей команды. Хранилище, которое считает деньги без потерь и меняет схему без миграций. Интеграционный движок, который говорит на языке контрагента, а не заставляет контрагента говорить на вашем. Сервер идентичности, проверенный внешним эталоном. Рантайм, который выкатывает изменения без окна обслуживания и даёт поддержке кнопку вместо ночного звонка разработчику.
И всё это — бесплатно на всей линейке 3.x, с исходниками по запросу.
Если у вас похожая задача — напишите в комментариях, что из перечисленного болит сильнее всего. По каждому слою у нас есть подробные технические разборы, и следующие мы напишем под реальные вопросы, а не под то, что нам самим кажется интересным.
Исходники и релизы: github.com/redbase‑app. Про хранилище redb: redb.ru. Прошлые статьи цикла — в профиле.
If this was useful — a ⭐ on GitHub helps others find it.