Кожна компанія, що зростає, доходить до моменту, коли CRM починає чинити опір. Воронка продажів не збігається зі стадіями, якими команда користується насправді, відділу доставки потрібні поля, яких вендор не пропонує, фінанси все одно експортують у таблицю, а рахунок за місця зростає за функції, які ніхто не відкриває. Ми самі дійшли до цього моменту, побудували Steppe Dev Box на заміну і тепер використовуємо той самий фундамент, коли клієнти просять CRM, бек-офіс або операційні інструменти. Ця стаття чесно пояснює архітектуру та компроміси, зокрема й те, коли власну CRM будувати не варто.
Коли власна CRM — погана ідея
Почнімо з незручного. Кастомна CRM — погана інвестиція, коли:
- Ваш процес стандартний (лід → кваліфікований → пропозиція → виграно) і SaaS підходить із легким налаштуванням.
- Вам потрібна велика екосистема інтеграцій з першого дня — email-послідовності, телефонія, маркетингова автоматизація.
- Ніхто в команді не володітиме продуктом після запуску. Внутрішні інструменти без власника швидко деградують.
Це хороша інвестиція, коли процес і є конкурентною перевагою, коли дані мають лишатися у вашій інфраструктурі, коли кільком командам потрібні різні подання одних і тих самих сутностей або коли рахунок за SaaS уже перевищує вартість сфокусованої розробки за два-три роки. У нас спрацювали друга і третя причини: продажам, доставці та фінансам потрібно було бачити проєкти, людей і гроші, кожному зі свого боку, і ми хотіли одне джерело правди.
Ключова ідея: все є модулем
Проєктне рішення, яке зробило систему підтримуваною, — відсутність жорстко закодованого поняття «лід» чи «угода». Є система модулів, а модуль — це пакет, що оголошує:
- схему сутності — поля з типами, валідацією та підказками відображення;
- подання — канбан-дошку, таблицю, сторінку деталей, кожне налаштовується, а не кодується;
- зв'язки з іншими модулями (проєкт належить клієнту; задача належить проєкту);
- права — хто може читати, створювати, редагувати й видаляти, аж до рівня поля;
- опційні хуки — серверні функції, що виконуються при створенні, оновленні чи зміні стадії.
Воронка продажів, проєкти, клієнти, рахунки, кандидати і навіть внутрішні активи — усе це модулі. Додати новий означає написати визначення схеми та, за потреби, хук. Ядро рендерить подання, забезпечує права, зберігає дані й транслює зміни. На практиці новий модуль займає в одного інженера приблизно день — і це метрика, яка нас цікавить найбільше.
Під капотом кожен модуль відповідає моделі Prisma на PostgreSQL. Ми розглядали повністю динамічне безсхемне сховище й відмовилися від нього: типізовані таблиці, міграції та справжні зовнішні ключі варті невеликої ціни генерації міграції при зміні модуля. Гнучкі JSON-колонки використовуються лише для справді динамічних атрибутів.
Реальний час за замовчуванням
CRM, якою одночасно користуються кілька людей, має специфічний режим відмови: двоє перетягують одну картку, один програє, і ніхто не помічає, поки не подзвонить клієнт. Ми рано вирішили, що кожна мутація транслюється, а кожне відкрите подання відображає її негайно.
Механізм навмисно простий:
- Усі записи йдуть через сервер (route handlers і server actions Next.js), який валідує їх за схемою модуля та правами, пише в PostgreSQL у транзакції й повертає канонічний запис.
- Після коміту сервер публікує подію зміни —
{ module, id, type: "created" | "updated" | "deleted", version }— у канал. - WebSocket-шлюз розсилає події підключеним клієнтам, фільтруючи за тим, що кожному клієнту дозволено бачити.
- Клієнт тримає нормалізований кеш для кожного модуля. На подію він або патчить запис на місці, або, якщо версія показує, що щось пропущено, перезавантажує цей запис.
Drag-and-drop використовує оптимістичні оновлення з відкатом: картка рухається негайно, сервер підтверджує або відхиляє, а відхилення повертає картку назад із повідомленням. Конфлікти вирішуються номерами версій — застарілий запис відхиляється, і клієнт оновлюється, — що просто й достатньо для команди нашого розміру. Справжнє спільне редагування довгих текстових полів потребувало б CRDT; нам це не знадобилося.
Інтерфейс: швидкий для щоденної роботи
Внутрішніми інструментами користуються годинами щодня, тому швидкість взаємодії важливіша за візуальні прикраси. Патерни, що заслужили своє місце:
- Канбан-воронки з drag-and-drop як основне подання для всього, що має стадії, з тим самим табличним поданням для масових операцій.
- Редагування на місці в таблицях і на сторінках деталей — клік по клітинці, зміна, Tab до наступної — з валідацією зі схеми модуля.
- Клавіатурна навігація та командна палітра для переходу між записами й запуску дій.
- Збережені фільтри та подання для кожного користувача, щоб кожна роль потрапляла на потрібний зріз даних.
- Серверний рендеринг для першого завантаження, далі клієнтська навігація з кешованими даними, що тримає застосунок придатним навіть на повільному з'єднанні.
Ми використовуємо Next.js і TypeScript на всьому стеку з Tailwind CSS для стилів; спільні типи між схемою Prisma, сервером і клієнтом — значна частина того, чому систему модулів безпечно швидко розширювати.
Права аж до поля
Ролі в CRM рідко бувають чистими. Продавець має бачити суми угод, але не зарплати; підрядник — свої задачі, але не бюджет клієнта. Ми реалізували права на трьох рівнях — модуль, запис і поле, — що обчислюються на сервері для кожного читання й запису. Подання генеруються з дозволеного набору полів, тож користувач ніколи не бачить колонку, яку не може читати, а WebSocket-шлюз застосовує ті самі правила перед трансляцією, тож заборонене поле ніколи не йде по дроту.
Це більше роботи, ніж простий поділ адмін/користувач. І це та функція, яка дозволила нам відкрити систему партнерам і підрядникам без окремого порталу.
Скільки це коштує в експлуатації
Цифри, про які питають:
- Інфраструктура: керована інстанція PostgreSQL, невеликий Node.js-процес для WebSocket-шлюзу та застосунок Next.js на Vercel. Для компанії нашого розміру місячний рахунок порівнянний із кількома місцями в SaaS.
- Підтримка: кілька годин на місяць на оновлення залежностей і невеликі зміни схем. Нові модулі — основна поточна робота, і її рухають потреби бізнесу, а не обслуговування.
- Початкова розробка: система з ядром модулів, синхронізацією в реальному часі, трьома-чотирма модулями та правами — проєкт на 6–10 тижнів для невеликої команди. Порівняйте це з трирічною вартістю SaaS за вашої кількості місць, перш ніж вирішувати.
Повторне використання фундаменту для клієнтів
Оскільки система модулів універсальна, Steppe Dev Box став відправною точкою для клієнтських проєктів, а не одноразовою розробкою: бек-офіси для маркетплейсів, партнерські портали, операційні дашборди. Ядро — модулі, подання, права, синхронізація в реальному часі — лишається; модулі підлаштовуються під процес клієнта. І це наша чесна порада, якщо ви оцінюєте кастомну CRM: не будуйте CRM — побудуйте систему модулів, а потім опишіть у ній свою CRM.