CRM и Автоматизация

Как мы мигрировали с Bitrix24 на Twenty CRM без потери ни одного лида

Михаил Шувалов
27 июля 2026
~7 мин чтения

Три месяца назад мы сидели на Bitrix24. Стандартный выбор для малого бизнеса в РФ: бесплатный тариф, CRM, лиды, воронка. Но когда наш AI-чат начал создавать по 20+ лидов в день и каждый из них шёл через webhook в облако 1С-Битрикс — стало ясно: мы не контролируем собственную базу клиентов.

Решили мигрировать на self-hosted CRM. Выбрали Twenty — open-source NestJS/GraphQL решение. Написали PHP-адаптер на 935 строк, настроили dual-write (две CRM работают параллельно) и мигрировали исторические данные. Ни одного потерянного лида. Вот как это устроено.

Почему ушли с Bitrix24

Bitrix24 — отличный продукт для тех кто работает «из коробки». Но как только начинаешь программировать интеграции — вылезают ограничения:

  1. Облачный webhook. API-ключ — это URL. Кто угодно с этим URL может создавать лиды. Нет ротации, нет scopes, нет audit log.
  2. REST API. Для создания лида с кастомными полями (lead_score, stage, industry) нужно 3 HTTP round-trip'а. На shared-хостинге это 2–3 секунды на заявку.
  3. Кастомные поля — UF_CRM_*. Именование полей привязано к user field ID. При переносе между порталами — ад.
  4. Vendor lock-in. Выгрузить данные можно только в Excel. API для массового экспорта нет. Миграция с Bitrix24 — это ручной труд.
После 3 месяцев эксплуатации стало ясно: нам нужна CRM, которую мы контролируем на уровне базы данных. Self-hosted, open-source, с нормальным API.

Почему Twenty CRM

Искали open-source CRM с GraphQL API и Docker-деплоем. Рассматривали:

Twenty выиграл по трём пунктам: GraphQL API (один запрос — все нужные поля), TypeORM (PostgreSQL а не MySQL), и MIT-лицензия (можно форкнуть и допилить под себя).

Архитектура адаптера: не переписывать, а обернуть

На сайте 6 PHP-файлов которые отправляют данные в Bitrix24: send_lead.php, chat_api.php, partner/api.php и так далее. Переписывать каждый — месяц работы и куча багов.

Вместо этого — написали один слой абстракции: crm_adapter.php. Он предоставляет те же функции что и Bitrix24 (crm_create_person, crm_create_opportunity, crm_add_note), но внутри вызывает GraphQL Twenty. Все 6 файлов подключили require_once 'crm_adapter.php' и заменили вызовы. Два дня работы вместо месяца.

9 транслированных методов

Адаптер переводит методы Bitrix24 в GraphQL-мутации Twenty:

Bitrix24 Twenty GraphQL Статус
crm.lead.addcreatePerson + createOpportunity✅ работает
crm.lead.updateupdateOnePerson✅ работает
crm.deal.addcreateOpportunity✅ работает
crm.timeline.comment.addcreateNote + createNoteTarget✅ работает
crm.duplicate.findbycommfindPeople query✅ работает
im.notifyemail (нет push в Twenty)⚠ email
bizproc.workflow.startнет аналога в Twenty⏸ skip

Dual-write: ключевая идея

Самое опасное в миграции CRM — потеря лидов во время перехода. Решение: dual-write. Каждая заявка пишется одновременно в обе CRM.

// crm_adapter.php — конфигурация
define('CRM_MODE', 'dual');  // twenty | bitrix | dual

// Каждая функция адаптера:
function crm_create_person($data) {
    $twenty_ok = twenty_create_person($data);
    $b24_ok    = b24_create_lead($data);

    // Возвращаем успех если хоть одна CRM приняла лид
    return $twenty_ok || $b24_ok;
}

Twenty упал (Docker перезагрузился, туннель отвалился)? Не страшно — лид всё равно в Bitrix24. Через месяц стабильной работы в dual режиме — переключаем CRM_MODE = 'twenty' и отключаем Bitrix24.

Twenty на локальном Docker а не на VPS. Почему? Потому что shared-хостинг не даёт PostgreSQL, а ставить CRM на тот же сервер что и сайт — плохая практика. Туннель (localtunnel) связывает хостинг с локальным Docker-контейнером. Да, добавляет ~3 секунды latency на запрос. Но для CRM это не критично — заявка всё равно обрабатывается асинхронно.

Дедупликация лидов

Самое интересное в миграции — поиск дубликатов. Bitrix24 ищет дубликаты по телефону/email через crm.duplicate.findbycomm. Twenty — через GraphQL query findPeople.

Адаптер ищет по:

Если контакт уже существует — добавляется Note «Повторное обращение» вместо создания дубликата Person. При миграции исторических данных из 45 лидов Bitrix24 было создано 29 в Twenty, 16 пропущено как дубликаты.

Инфраструктура: Docker + туннель + мониторинг

Twenty живёт в Docker на Windows-машине. Состав:

Доступ из интернета — через localtunnel. crm_url.txt на хостинге динамически обновляется скриптом twenty_tunnel.ps1 при перезапуске туннеля. PHP-адаптер читает этот файл чтобы знать актуальный URL.

Мониторинг: twenty_monitor.ps1 каждые 30 минут проверяет Docker-контейнеры, healthz-эндпоинт и состояние туннеля. При падении — алерт.

Результаты и планы

Что получили:

Что дальше:

Главный вывод из этого проекта: миграция CRM — это не про «перенести данные из А в Б». Это про обеспечение непрерывности бизнеса в момент перехода. Dual-write — простой но эффективный паттерн, который даёт время на стабилизацию новой системы без риска потери лидов. Рекомендую всем кто планирует переезд с одного вендора на другого.