Архитектура кастомной CRM-системы

22.06.202510 мин чтения
Макар Кучеренко
Python-разработчикМакар Кучеренко

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

В этой статье разберем техническую сторону: как разделить frontend и backend CRM, когда выбирать Node.js, где нужен брокер сообщений и как подключать 1С, сайт, телефонию и внешние API без дублей и потери данных. Если вам нужна оценка готового проекта, а не только выбор технологий, посмотрите условия разработки кастомной CRM-системы.

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

С чего начинается архитектура CRM

Выбор фреймворка не должен быть первым решением. Сначала команда фиксирует:

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

Эти данные превращаются в модель предметной области и карту интеграций. Подробный порядок сбора требований описан в руководстве по проектированию CRM.

Модульный монолит или микросервисная CRM

Модульный монолит

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

Преимущества подхода:

  • проще разработка, тестирование и развертывание;
  • транзакции между связанными сущностями остаются предсказуемыми;
  • меньше инфраструктурных расходов;
  • быстрее выпуск MVP и проверка процессов на реальных пользователях.

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

Микросервисы

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

Но за независимость приходится платить:

  • появляется распределенная трассировка и сложная диагностика;
  • данные между сервисами становятся согласованными не мгновенно;
  • нужны очереди, повторная доставка событий и защита от дублей;
  • усложняются DevOps, тестовые среды и контроль версий API.

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

Backend CRM: Node.js, Python, PHP или Go

Язык backend выбирают по нагрузке, компетенциям команды и экосистеме интеграций.

Node.js и TypeScript

Node.js подходит для CRM с большим количеством сетевых операций: API, WebSocket, телефония, чаты, уведомления и обмен с внешними сервисами. TypeScript помогает формализовать контракты данных между frontend и backend. Для структурированного приложения часто используют NestJS, для компактных сервисов — Fastify или Express.

Python

Python удобен, когда CRM тесно связана с аналитикой, обработкой документов, машинным обучением или AI-модулями. Django дает готовую административную часть и ORM, FastAPI подходит для API и отдельных сервисов.

PHP

Laravel и Symfony остаются рациональным выбором для бизнес-систем, особенно если у компании уже есть PHP-команда или интеграции с сайтом и 1С-Битрикс. Качество архитектуры зависит не от языка, а от границ модулей, модели данных, тестов и процесса разработки.

Go

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

База данных и модель хранения

Для основной транзакционной модели CRM обычно подходит PostgreSQL. Реляционная база обеспечивает ограничения целостности, транзакции, индексы, полнотекстовый поиск и работу с JSON-полями.

Дополнительные хранилища подключают под конкретную задачу:

  • Redis — кэш, блокировки, временные данные и очереди небольшого масштаба;
  • OpenSearch или Elasticsearch — сложный поиск по большой базе;
  • ClickHouse — события и аналитические срезы;
  • S3-совместимое хранилище — документы, записи звонков и вложения;
  • векторная база — семантический поиск и RAG по документам компании.

Не стоит переносить все данные в специализированные хранилища. Карточка клиента, сделка и платеж должны иметь один надежный источник истины.

API и интеграции CRM

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

Сначала определите владельца данных

До выбора REST, webhook или очереди составьте карту данных. Для каждого объекта должно быть понятно, какая система создает запись и какая имеет право менять критичные поля.

Данные Возможный источник истины Что синхронизировать
Лид и обращение CRM источник, контакты, согласия, ответственный, статус обработки
Номенклатура и остатки 1С или ERP SKU, цена, склад, доступность, налоговые признаки
Заказ на сайте интернет-магазин или CRM состав, доставка, оплата, внешний ID, клиент
Счет и реализация 1С или ERP номер, сумма, статус оплаты и закрывающие документы
Звонок телефония номер, запись, длительность, результат и связь со сделкой
Рекламные расходы рекламная система или хранилище аналитики кампания, затраты, метки и период

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

REST API, webhook или очередь

Эти механизмы решают разные задачи и часто используются вместе.

Механизм Когда подходит Ограничение
REST API пользователь ожидает немедленный ответ: поиск клиента, расчет цены, получение карточки внешний сервис может замедлить или сорвать запрос пользователя
Webhook нужно сообщить о произошедшем событии без постоянного опроса доставка может повториться, прийти не по порядку или временно завершиться ошибкой
Очередь сообщений обработка занимает время, нужна повторная доставка или изоляция внешней системы требуется мониторинг, политика retry и обработка необработанных сообщений
Периодическая сверка внешняя система не поддерживает события или нужно подтвердить полноту данных изменения появляются с задержкой, растет нагрузка на API

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

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

Как защититься от дублей

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

Минимальный контракт события включает:

{
  "eventId": "order-18452-paid-v1",
  "eventType": "order.paid",
  "occurredAt": "2026-08-26T08:30:00Z",
  "source": "online-store",
  "entityId": "18452",
  "schemaVersion": 1
}

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

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

Retry, backoff и очередь ошибок

Повторять нужно только временные ошибки: timeout, недоступность сервиса, 429 или часть ответов 5xx. Ошибку валидации 400 бессмысленно отправлять снова без изменения данных.

Практическая схема:

  1. Зафиксировать событие и бизнес-операцию в своей базе.
  2. Отправить задачу в очередь после успешной транзакции.
  3. При временной ошибке повторить попытку с увеличивающейся задержкой.
  4. Ограничить число попыток.
  5. Переместить необработанное сообщение в dead-letter queue.
  6. Уведомить ответственного и сохранить понятную причину сбоя.
  7. После исправления безопасно переиграть событие.

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

Версионирование контрактов

Документированное API полезно не ради красивой страницы Swagger. Спецификация фиксирует названия полей, типы, обязательность, коды ошибок и схемы авторизации. Это позволяет проверять совместимость CRM, сайта и интеграционного сервиса до развертывания.

При изменении контракта:

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

Журнал обмена и сверка данных

Интеграция не должна быть черным ящиком. Для каждой операции храните:

  • корреляционный ID;
  • источник и получателя;
  • тип события и идентификатор сущности;
  • время первой и последней попытки;
  • код и краткий ответ внешней системы;
  • число повторов;
  • финальный статус;
  • ссылку на запись или трассировку без сохранения секретов.

Метрики и распределенная трассировка помогают увидеть рост ошибок, но не заменяют бизнес-сверку. Например, раз в сутки можно сравнивать количество оплаченных заказов, суммы и отсутствующие внешние ID между CRM и 1С. Такая проверка находит тихие расхождения, которые не сопровождаются 500.

Особое внимание требуется интеграциям с:

  • 1С и ERP;
  • сайтом и формами заявок;
  • IP-телефонией;
  • почтой и мессенджерами;
  • платежными сервисами;
  • рекламными кабинетами и сквозной аналитикой.

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

Как принять интеграцию CRM перед запуском

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

  1. Новая запись передается один раз и получает внешний ID.
  2. Повтор того же события не создает дубль.
  3. Временный 500 приводит к retry, а не к потере данных.
  4. Ошибка валидации попадает ответственному с понятной причиной.
  5. События, пришедшие не по порядку, не возвращают сущность в старый статус.
  6. Изменение контакта синхронизируется по согласованному правилу владельца данных.
  7. Недоступность 1С, телефонии или CRM не блокирует оформление заявки на сайте.
  8. Секреты и персональные данные не выводятся в открытые логи.
  9. После восстановления можно безопасно переиграть очередь ошибок.
  10. Ежедневная сверка находит пропущенные документы и расхождение сумм.

Для интеграции с 1С отдельно проверяют часовые пояса, округление, ставки НДС, частичные оплаты, возвраты, отмену заказа и изменение состава после создания документа. Именно граничные сценарии чаще отличают рабочий обмен от демонстрационного прототипа.

Frontend CRM: интерфейс рабочего инструмента

Менеджер может проводить в CRM весь рабочий день, поэтому frontend влияет на производительность не меньше backend. React, Next.js, Vue и Nuxt позволяют строить динамические интерфейсы, но выбор библиотеки сам по себе не решает UX-задачи.

Важнее обеспечить:

  • быстрый поиск и открытие карточки;
  • сохранение черновиков и защиту от потери данных;
  • виртуализацию длинных таблиц;
  • понятные состояния загрузки и ошибки;
  • клавиатурную навигацию;
  • адаптацию критичных сценариев под планшет и телефон;
  • обновления через WebSocket там, где действительно нужен real-time.

Например, в кейсе SPA Booking & CRM System синхронизация через Node.js и сокеты использовалась для мгновенного обновления бронирований у сотрудников ресепшн. Это конкретная бизнес-задача, а не технология ради технологии.

Безопасность CRM

CRM содержит персональные данные, историю коммуникаций и коммерческую информацию. Базовый контур безопасности включает:

  • ролевую модель и принцип минимальных полномочий;
  • MFA для сотрудников с расширенным доступом;
  • шифрование соединений и секретов;
  • журналирование действий с чувствительными данными;
  • резервное копирование и регулярную проверку восстановления;
  • ограничение и ротацию ключей внешних интеграций;
  • отдельные production, staging и development среды;
  • контроль выгрузок и массовых операций.

Требования ФЗ-152, GDPR и внутренних политик нужно учитывать до выбора места размещения и схемы резервного копирования.

Как выбрать технологический стек CRM

Практический алгоритм выглядит так:

  1. Описать роли, процессы, сущности и интеграции.
  2. Определить нефункциональные требования: нагрузку, доступность, безопасность и сроки восстановления.
  3. Выбрать минимальную архитектуру, которая закрывает эти требования.
  4. Проверить, сможет ли текущая команда поддерживать выбранный стек.
  5. Зафиксировать границы модулей и контракты API.
  6. Назначить владельца данных и внешние идентификаторы для каждой интеграции.
  7. Создать прототип наиболее рискованных обменов и проверить сбои.
  8. Запустить первый полезный контур и проверить его на реальных пользователях.

Для большинства CRM разумная стартовая точка — модульный монолит, PostgreSQL, документированное API, очередь фоновых задач и отдельные сервисы только для действительно независимых или нагруженных функций.

FAQ

Обязательно ли строить CRM на микросервисах?

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

Подходит ли Node.js для backend CRM?

Да, особенно для API, WebSocket и большого количества интеграций. Но выбор нужно соотносить с компетенциями команды, требованиями к данным и существующей инфраструктурой.

Какую базу данных выбрать для CRM?

PostgreSQL закрывает большинство транзакционных задач CRM. Поиск, аналитика и семантическая обработка могут использовать дополнительные специализированные хранилища.

Как интегрировать CRM с 1С без дублей?

Нужно назначить источник истины для заказов, клиентов, номенклатуры и оплаты, использовать стабильные внешние ID и идемпотентные события. Повторная доставка не должна повторно создавать документ, а ошибки обмена должны попадать в контролируемую очередь.

Нужна ли очередь сообщений для интеграции CRM?

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

Почему webhook создает дубли в CRM?

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

Как оценить срок разработки CRM-интеграции?

Срок зависит не от количества endpoint, а от качества документации, модели данных, авторизации, лимитов, обработки ошибок и тестового контура внешней системы. До оценки полезно собрать примеры объектов, карту полей и список граничных сценариев.

Когда архитектуру нужно пересматривать?

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

Итог

Хорошая архитектура кастомной CRM начинается с процессов и требований, а не со списка модных технологий. Backend, frontend, база данных и интеграции должны образовывать систему, которую команда может безопасно развивать после первого релиза. Надежность обмена определяется не фактом подключения API, а поведением при повторе, задержке, частичном сбое и расхождении данных.

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

Источники

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