Почему мы ушли с Bitrix24
Bitrix24 — стандарт российского рынка малого бизнеса. Работает из коробки, куча интеграций, бесплатный тариф. Но когда доходишь до интеграции с собственным софтом — начинаются проблемы.
Что не устраивало
- Никаких self-hosted инсталляций API. Все webhook'и привязаны к облаку 1С-Битрикс. Ты не контролируешь ни данные, ни доступ.
- API — legacy REST. Не GraphQL. Каждый вызов — отдельный HTTP round-trip. Для создания сущности с кастомными полями — 3 запроса минимум.
- Кастомные поля через UF_CR_*. Документация — устаревшая вики на русском. Типы данных ограничены.
- Вендор-лок. Переехать с Bitrix24 сложнее чем начать с нуля. Это осознанный vendor lock-in.
После 3 месяцев эксплуатации стало понятно: нам нужна CRM которую мы контролируем. Данные, API, бэкапы, доступы — всё должно быть наше.
Почему выбрали Twenty CRM
Twenty — open-source CRM на NestJS + TypeORM + GraphQL. Не стартап на venture capital, а проект с MIT-лицензией. Для нас — идеальный кандидат на замену:
- Self-hosted. Docker Compose из 4 контейнеров (server, worker, postgres-16, redis). Никаких SaaS-зависимостей.
- GraphQL API. Один запрос — все нужные поля. Мутации, вложенные объекты, связи. Современный API, не legacy REST.
- MIT-лицензия. Можно форкнуть, допилить, деплоить где угодно.
- JWT-аутентификация. API-ключи генерируются из UI, ротируются, имеют срок жизни. Не webhook с секретом в URL.
Архитектура crm_adapter.php
Вместо переписывания всех 6 PHP-файлов сайта — написали один слой абстракции crm_adapter.php (935 строк). Он заменяет все вызовы Bitrix24 на GraphQL-запросы к Twenty.
9 транслированных методов Bitrix24
Адаптер транслирует методы Bitrix24 в GraphQL-мутации Twenty:
| Bitrix24 метод | Twenty мутация |
|---|---|
crm.lead.add | createPerson + createOpportunity |
crm.lead.update | updateOnePerson |
crm.deal.add | createOpportunity |
crm.deal.update | updateOneOpportunity |
crm.timeline.comment.add | createNote + createNoteTarget |
tasks.task.add | createTask + createTaskTarget |
crm.duplicate.findbycomm | GraphQL findPeople query |
im.notify | email fallback (нет аналога) |
bizproc.workflow.start | skip (нет аналога) |
Режим dual-write
Ключевая особенность — CRM_MODE = dual. Каждая заявка пишется одновременно в обе CRM:
// crm_adapter.php — основная логика dual-write function crm_create_person($data) { $twenty_success = twenty_create_person($data); $b24_success = b24_create_lead($data); // fallback // Если Twenty упал — лид всё равно создан в Bitrix24 return $twenty_success || $b24_success; }
Зачем dual-write а не сразу только Twenty? Потому что миграция CRM — это не переключение toggle. Должен быть период когда обе системы работают параллельно. Если Twenty упал (туннель отвалился, Docker перезагрузился) — лиды всё равно попадают в Bitrix24.
Инфраструктура: Docker + туннель
Twenty работает локально в Docker на Windows-машине. Доступ из интернета — через туннель:
- Docker Compose: 4 контейнера — twenty-server (NestJS :3001), twenty-worker (Redis queue), postgres-16, redis
- Туннель: localtunnel
lt --port 3001, URL динамически обновляется вcrm_url.txtна хостинге - Мониторинг: скрипт
twenty_monitor.ps1— каждые 30 минут проверяет контейнеры, healthz, туннель - Авто-восстановление:
twenty_tunnel.ps1— авто-перезапуск туннеля при обрыве
Когда Twenty стабильно отработает месяц в dual-write, переключимCRM_MODEнаtwentyи отключим Bitrix24.
Миграция исторических данных
Перенос 45 лидов и 50 контактов из Bitrix24 в Twenty — скрипт на Python (migrate.py). Экспорт из Bitrix24 в JSON, трансформация полей, создание через GraphQL API.
- Дедупликация: поиск по телефону (local digits, 7–10 цифр) и email перед созданием
- Создание связанных сущностей: Person → Opportunity → Note (трёхшаговый процесс через GraphQL)
- Rate limiting: 500ms задержка между запросами чтобы не перегрузить API
- Результат: 29 лидов создано (23 с телефоном, 29 с email), 16 пропущено как дубликаты
Что дальше
- Отключение Bitrix24. После месяца стабильного dual-write — переключаем
CRM_MODEнаtwenty. - Custom fields. Перенос UF_CRM_BL_INDUSTRY, UF_CRM_BL_BUDGET, UF_CRM_LEAD_SCORE из Bitrix24 в Twenty.
- Pipeline (воронка). 10 кастомных этапов вместо стандартных.
- Деплой на VPS. Перенос с локального Docker на выделенный сервер для продакшена.
- Telegram-уведомления. Замена email-алертов на Telegram-бота для оператора чата.
Главный урок: миграция CRM — это не техническая проблема, а проблема надёжности. Ты не можешь позволить себе потерять ни одного лида во время перехода. Dual-write решает это ценой дублирования данных на переходный период.
Нужна миграция CRM?
Спроектируем адаптер под вашу CRM, настроим dual-write и мигрируем данные без потерь.