The Jerusalem PostUS defense funding paths for Israeli tech: Navigating the Pentagon’s innovation gateways - opinionDaily MaverickDRAFT DODGING: Three years, 6,000 pages, no labels: Who’s stalling SA’s food warnings?ESPNMessi marks tearful Argentina farewell with goal: Wish I could play foreverRTP DesportoPortugal perde com Itália no Mundial feminino de hóqueiBollywood HungamaSalman Khan vs Kala Hiran: Delhi High Court seeks reply from actor on Amit Jani’s plea seeking stay on proceedingsPunchKano gov approves promotion of 18,984 SUBEB staffInquirer1,380 liters of diesel seized, 1 arrested in Occidental MindoroZDF heuteEntdecken Sie das ZDF-NachrichtenstudioThe Straits TimesP1 registration: 15% of Phase 2C students at 12 popular primary schools live in public housingHet Laatste NieuwsZelfs Boris Becker bemoeit zich ermee: hoe dit controversieel punt ervoor zorgde dat Coco Gauff bedolven werd onder “krankzinnige” racistische haatVarietyThe New Kindle Is Down to $100 for Amazon Prime Big Deals DaySRF NewsHistorischer Abend? – Kriens-Luzern schielt gegen Kolstad auf die ersten CL-Punkte
The Daily Newsstand · Free, Always
Wednesday, October 7, 2026

Бизнес-логика жила в базе 27 лет: как мы вынимали ее из Oracle, не останавливая дилерскую сеть

Translate

РОЛЬФтех — ИТ-компания группы РОЛЬФ. Мы разрабатываем ФЛОРУ, собственную дилерскую цифровую платформу, в которой система управления процессами автодилера (DMS) , CRM и электронная коммерция создается как набор продуктов командной разработки около 200 человек. ФЛОРА приходит на смену системам на СУБД Oracle. С 1998 года автоматизация компании строилась на этой технологии.  Это классическое монолитное решение своего времени, доведенное до абсолюта и совершенства, где база данных отвечала вообще за всё.

Меня зовут Александр Алехин, я CTO РОЛЬФтех, отвечаю за разработку ФЛОРЫ. В компании я 1.5 года и застал проект уже в активной стадии: первый код новой системы автоматизации бизнеса лег в репозиторий в мае 2025 года. В сентябре 2025 года начался процесс перехода пользователей на новую систему. Дальше я буду говорить «мы», потому что ни одно из решений, о которых пойдет речь, не принимал один человек. Архитектурные развилки проходили через сессии с командой, которые часто превращались в жаркие обсуждения.

Сразу оговорюсь про жанр. Это не история успеха. Переезд еще в процессе, часть функционала до сих пор работает в старой системе, и расхождения в данных тоже случаются.

Масштаб, чтобы понимать сложность и цену ошибки

В системах на базе СУБД Oracle работает около шести тысяч пользователей из тридцати  дилерских центров и центрального офиса . Если считать сделки и операции счет идет на тысячи в сутки. Объем данных в базе около 30 терабайт, отдельно храниться медиа еще на 40 терабайт: фотографии автомобилей, сканы документов, приложения к заказ-нарядам.

Если ты, дорогой читатель, работал с подобными системами, то поймешь объем кода внутри СУБД :

Пакетов – 8 503, в них 9 325 436 строк

Процедур – 15 091, в них 2 183 316 строк

Функций – 2 828, в них 183 873 строк

Триггеров – 18994, в них 310 162 строк

Что значит «все в базе»

Oracle у нас не только хранилище данных, но и среда исполнения бизнес-логики и организация пользовательского интерфейса . Генерация html страницы происходит с помощью хранимых процедур. Устроено это было по логике своего времени и работает до сих пор.

Что Oracle нам дал

Этот подраздел я пишу отдельно, потому что без него текст превращается в «было плохо, стало хорошо», а это неправда.

Транзакционная целостность на такой схеме доставалась бесплатно. Все в одной базе, все в одной транзакции, консистентность обеспечивает СУБД. Сейчас мы строим это сами: у нас есть оркестраторы распределенных бизнес-транзакций, и то, что раньше было свойством платформы, стало кодом, который надо писать, тестировать и сопровождать.

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

И главный аргумент в пользу той архитектуры: она проработала двадцать семь лет и все это время везла бизнес. Систем с таким сроком жизни немного, и относиться к ней свысока было бы странно.

Почему мы все-таки уходим

Итак, сложившаяся система автоматизации была нормальной для задач, под которые ее строили. С годами любая система накапливает сложность и связанность. Каждое следующее изменение делается дольше предыдущего, изменять приходится во все большем количестве мест. Несмотря на архитектурный контроль границы внутри него условны, их сложно охранять и через двадцать семь лет правок связи оказываются везде. В какой-то момент скорость изменений упирается не в людей и не в железо, а в саму форму системы.

Задача перед нами стояла не «поменять систему автоматизации». Нужна была архитектура, которая позволит независимо развивать разные направления бизнеса, включая те, которых сейчас еще нет. Плюс она должна выдерживать B2C-трафик: клиентские сервисы, где нагрузка приходит снаружи и не спрашивает, готовы ли мы.

Как выбирали целевую архитектуру

Готовые решения мы смотрели, и не один раз. В разные годы рассматривались коробочные DMS. Каждый раз все упиралось в уровень кастомизации: процессы компании не ложились в коробку без такого объема доработок, при котором смысл коробки теряется.

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

В микросервисной архитектуре, если следовать основным паттернам, сложность изолируется, а связанность может оставаться низкой. Система дольше сохраняет способность меняться с приличной скоростью. Цикл разработки при этом сложнее монолитного, особенно на старте, и первые месяцы вы за это платите. Потом выигрываете, если не накопили техдолг в виде взаимных вызовов между сервисами, обилия синхронного взаимодействия и размытых границ доменов.

Дальше по цепочке: если микросервисы, то DDD, потому что иначе непонятно, где проводить границы. Мы провели серию архитектурных сессий и что-то вроде Event Storming, и на выходе получили ландшафт ограниченных контекстов. Заняло это около полугода.

Полгода на разметку доменов до первой строчки продуктивного кода — это то место, где нас регулярно спрашивают, не многовато ли?  Архитектура это не только про границы доменов, но и правила их взаимодействия. В крупных системах цена ошибки в границах контекста выясняется не сразу, по мере развития функциональности. И когда два сервиса начинают ходить друг к другу за каждым чихом, это порождает ненужную связанность от которой хотели уйти и перестройка ландшафта стоит дорого.

Концепция и обзор архитектуры

На самом высоком уровне концепция предполагает разделение продукта Flora нанесколько функциональных подсистем:

  • CRM+: реализует и обрабатывает сценарии, типичные для бизнеса, построенного вокруг процессов закупок и продаж. Сюда входят подсистемы взаимодействия с клиентами, формирования юридических документов и обработки платежей

  • Плагины: являются расширением функционала CRM+ в точке формирования списка товаров и услуг, удовлетворяющих клиентские потребности

  • Источники данных: предоставляют списки товаров и услуг (в терминах бизнеса - стоки), а также дополнительную информацию, необходимую для взаимодействия с клиентами, формирования документов и проведения платежей

  • Аналитика и рекомендательные системы: выполняют функцию формирования операционной и стратегической отчетности, прогнозирования и ценообразования

  • Внешние интеграции: интеграции с внешними системами, а также внутренними системами Рольф, не входящими в контур Flora

CRM+ как подсистема состоит из пользовательских приложений (далее FE) и серверной части (далее BE). В общем случае, FE - это набор пользовательских интерфейсов, реализованных через отдельные приложения FE, встраиваемые виджеты и компоненты; логики пользовательских интерфейсов; бизнес-логики; логики взаимодействия с BE.

Для CRM+ интерфейс пользователя состоит из:

Общих экранов CRM+, позволяющих пользователям управлять теми или иными сущностями или процессами. Сюда входят интерфейсы управления коммуникациями, общими списками потребностей и позиций продаж, документов, платежей и взаиморасчетов. Также, CRM+ включает в себя интерфейсы задач и согласований, и предоставляет эти возможности другим компонентам системы.

Областей с заранее определенными позициями в рамках этих экранов, в которые встраиваются интерфейсы, предоставляемые плагинами (далее такие позиции описаны как слоты) . BE CRM+ состоит из микросервисов согласно архитектурному манифесту. В общем случае, для поддержки каждой бизнес-сущности выделяется отдельный микросервис.Также, микросервисы могут реализовывать отдельные бизнес-процессы, выступать в качестве агрегаторов данных, предоставлять точки интеграции с внешними системами и реализовывать иной функционал.

Разбиение системы на микросервисы происходит в парадигме минимизации связности между компонентами системы и с учетом влияния такого разбиения на консистентность данных в моменте, производительность и отказоустойчивость.

компонентная диаграмма CRM+

компонентная диаграмма CRM+

На этой диаграмме прямоугольники соответствуют компонентам Flora. Здесь, компонент это либо один или несколько BE микросервисов, либо одно или несколько встраиваемых пользовательских приложений или виджетов, либо оба эти варианта одновременно (таким образом, компонент может состоять из произвольной комбинации FE и BE элементов). В самом частом случае, компонент - это один микрофронт и несколько микросервисов. Синим отмечены компоненты, формально входящие в состав подсистемы CRM+, красным обозначены плагины, серым - внешние относительно CRM+ компоненты.

Своя база на каждый сервис

Это базовый паттерн выбранного архитектурного стиля. Если ему не следовать собираешь все минусы микросервисной архитектуры и не получаешь ни одного плюса. Прямой путь к этому — свалить данные в одну общую базу и написать над ней кучу мелких приложений, каждое со своей логикой работы с этими данными. Результатом будет распределенная система по стоимости развития и эксплуатации и монолит по связанности.

Поэтому у каждого микросервисного компонента собственная система хранения и собственная логика обработки данных. Доступ снаружи только через публичные интерфейсы. Единственное исключение — пакетная передача данных в хранилище.

Больно от этого решения нам пока не стало, ровно потому что мы от него не отступали. Как только появляется первое исключение «ну тут же быстрее напрямую», дальше уже неважно, сколько у вас сервисов.

Где что лежит

Данные микросервисов живут в PostgreSQL и MongoDB, файлы и медиа в S3, индексы для поисковых запросов в OpenSearch. Выбор системы хранения по каждому сервису делается от задачи, единой целевой СУБД «на все» у нас нет.

Событийный контур

Брокер — Kafka. Событийная часть у нас устроена довольно просто, и я специально не буду делать вид, что там больше инженерии, чем есть.

Проблем с race conditions мы избегаем уникальным ключом в базе на каждое событие. На стороне отправки используется Outbox. Распределенные бизнес-транзакции ведет оркестратор, хореографию мы не используем: уровень нагрузки у нас не хайлоад, и мы можем позволить себе оркестратор со всеми его минусами в виде центральной точки. Для системы с другим профилем нагрузки этот выбор был бы спорным.

Часть ситуаций закрывается банальным мониторингом: бизнес-транзакций не так много, сбой видно вовремя, и его успевают вылечить руками. Часть спасает self-healing: автоскейлинг по лагу и circuit breaker, чтобы дать разобрать очередь.

Тема эта обширная, и серьезных проблем на ней мы пока не встретили. Возможно, просто не доросли по нагрузке.

Подход к миграции

На период миграции часть пользователей работает в новой системе, а часть в старой.

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

Исключения есть, их немного, и каждое стоило отдельного обсуждения. Главное — информация о складе автомобилей: она синхронизируется, потому что автомобиль физически один, а продать его могут из новой и из старой системы. Данные не заливаются в базы микросервисов напрямую. Обмен идет через микросервисы обмена и через стандартные публичные интерфейсы соответствующих сервисов, те же самые, которыми пользуется приложение.

Чего в новой системе нет и почему это нормально

Мы существенно поменяли логику работы и информационную модель. Из этого следует неочевидная вещь: старых данных по бизнес-транзакциям в новой системе нет. Мы их не переносили.

История отношений с клиентом и история автомобиля берутся из витрин корпоративного хранилища в рамках CRM-задач. В новой системе живут только те сделки, которые в ней и сделаны.

Логика тут такая. С точки зрения нового процесса наша задача максимально быстро и удобно провести пользователя и клиента по сделке, выполнить все нужные проверки, получить точные данные для первичных документов и корректно провести оплату. Это то, что контролируется безусловно. Вся остальная логика старой системы осталась в старой системе и не всегда соответствует новой, поэтому мы ее с новой реализацией и не сравниваем.

Здесь обычно возникает вопрос про тестирование эквивалентности: как вы проверяли, что новый сервис ведет себя так же, как старый код в базе. Ответ: никак, и это осознанно. Мы не воспроизводили старое поведение, мы писали новое, по современным процессам.. Проверять эквивалентность там, где процесс намеренно изменен, значит закреплять в новой системе решения двадцатилетней давности.

Что мы действительно проверяем, так это данные. По складским, справочным и клиентским данным в процессе перехода работают скрипты сравнения и ручные выверки. Ручные — именно так, глазами, по спорным позициям. Красиво это не выглядит и в докладах об этом обычно не рассказывают, но на переходе это работает лучше любой автоматики.

Порядок отключения: два независимых счетчика

Отключение старой системы у нас идет по двум направлениям . Первое направление — дилерские центры. Центры подключаются к новой системе по одному. Когда в конкретном центре все возможные операции делаются в новой системе, этот центр отключается от старой. Второе направление — модули. Когда какой-то функционал, например выкуп и продажа автомобилей с пробегом, полностью используется в новой системе всеми дилерскими центрами, в старой системе отключается соответствующий модуль. То есть центр может уже полностью жить в новом контуре, пока в старой системе для других центров еще крутится тот же модуль.

Люди в двух системах

Про эту часть в инженерных статьях пишут мало, а по трудозатратам она сопоставима с разработкой. Первые месяцы после запуска первых центров система активно дорабатывалась. В том числе по обратной связи первых пользователей: человек в дилерском центре видит проблему раньше и точнее, чем видит ее бизнес аналитик. Первые центры прошли через это, и им было тяжелее всех. Дальше мы выстроили нормальную схему: подключили службу поддержки, сделали видеоинструкции, добавили ИИ-помощника, который отвечает на вопросы пользователей по работе в системе. Сейчас дилерский центр переходит на новую систему за две недели. Первые центры переезжали существенно дольше, и большая часть этого времени уходила на доработки по ходу: научить людей оказалось проще, чем чинить систему под ними.

То, к чему мы оказались не готовы

Основные сложности пришли со стороны процесса разработки. Слабосвязанная система из большого количества компонент потребовала разрешения ситуации взаимозависимости команд разработки. До набора критической массы необходимого функционала в общих компонентах возникают кросс-зависимости.

По релизам и облачной инфре пришлось создавать отдельное подразделение DevOps-практик. Насаждать подход Infrastructure as Code. Поднимать требования к пирамиде тестирования: в монолите с ней можно было жить как жили, в распределенной системе нельзя. Внедрять cloud observability, потому что без нее вопрос «где именно тормозит» в системе из семидесяти семи сервисов не имеет ответа.

Если считать честно, перестройка процессов заняла у нас сопоставимое с разработкой время. Это то, что я бы вынес в отдельный пункт любому, кто собирается идти той же дорогой.

Что ломалось

Глобально ничего не ломалось. Пишу это и понимаю, как звучит, но врать смысла нет. Что было и есть — штучные расхождения в обменах по автомобилям. За этим пристально смотрят и ИТ и бизнес. Каждое расхождение разбирается индивидуально: заводится инцидент, ищется причина, исправляется. Автомобиль это не строчка в таблице, а физический объект со своей стоимостью и своим местом на площадке. То, что складской обмен остается единственным местом с двусторонней синхронизацией, и то, что расхождения ловятся именно там, вряд ли совпадение. Каждый кусок, где мы не смогли отказаться от синхронизации, отдает нам эту цену.

Что изменилось, в числах

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

Что осталось и что дальше

Из старой системы будет выводиться все. На сегодня из крупного там остались обмен данными с производителями и управление продажами запчастей и сервисом. Своя база на каждый сервис пока не создала нам проблем, о причинах я написал выше. Оркестратор распределенных транзакций — сознательная плата за то, что мы не хайлоад; при росте нагрузки к этому решению придется вернуться, и я это понимаю. Событийная часть проблем пока не приносит.

Вместо вывода

Метафора про пересборку двигателя самолета в трансатлантическом перелете затаскана, но точнее ничего не придумали. Разница в том, что двигатель у нас не один: сеть продолжает продавать автомобили, обслуживать клиентов и закрывать месяц, пока под ней меняется вся техническая основа. Главный вывод, к которому я пришел за этот проект: сильнее всего экономит не оптимизация кода, а решения, от которых вовремя отказались. Например, когда мы отказались делать полную синхронизацию данных, это сберегло нам больше ресурсов, чем любое другое решение. То же самое и с архитектурой: мы потратили полгода на проектирование и четкие границы доменов еще до того, как написали первую строчку кода, — и это окупилось сполна.

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.