MAATRIX / Блог / Camunda ради трёх согласований — где BPMN превращается в оверинжиниринг

Camunda ради трёх согласований — где BPMN превращается в оверинжиниринг

MAATRIX

Кто-то на встрече произносит «нам нужен нормальный движок бизнес-процессов», и через месяц в инфраструктуре появляется Camunda: JVM, отдельная база под движок, BPMN-диаграммы, Tasklist для исполнителей задач. А сам процесс, ради которого всё это разворачивали, — это заявка на отпуск, которую подписывает руководитель, потом кадры. Три шага подряд, без единого ветвления. Через полгода выясняется, что обслуживание движка съедает больше времени, чем сэкономил сам процесс, а исходную задачу решило бы одно поле status в таблице Postgres. Разберём честно, когда Camunda и BPMN — это правильный инструмент, а когда это дорогая надстройка над очередью из трёх шагов.

Что вообще такое Camunda и зачем нужен BPMN-движок

Camunda — это open-source платформа для исполнения бизнес-процессов, описанных в нотации BPMN (Business Process Model and Notation) — стандартном языке диаграмм, где процесс рисуется как схема из задач, шлюзов (gateway) и событий. Диаграмма — не картинка для презентации, а исполняемый артефакт: вы загружаете BPMN-файл в движок, и он буквально по нему исполняет процесс, продвигая каждый экземпляр (инстанс процесса) от узла к узлу.

Существуют две линейки продукта с разной архитектурой:

  • Camunda 7 (Camunda BPM Platform) — классический движок, встраиваемый в Java-приложение (как библиотека внутри Spring Boot) либо разворачиваемый как отдельное веб-приложение на Tomcat/WildFly. Состояние процессов хранится в реляционной БД — PostgreSQL, MySQL, Oracle — где движок создаёт полсотни служебных таблиц: историю выполнения, переменные процесса, задачи, инциденты.
  • Camunda 8 — переписанная с нуля платформа на движке Zeebe, изначально спроектированная как cloud-native и горизонтально масштабируемая. Вместо реляционной БД для истории использует Elasticsearch/OpenSearch (для Operate и Tasklist), а сам Zeebe хранит состояние в собственном логе событий. Self-managed развёртывание — это уже не один контейнер, а связка Zeebe + Operate + Tasklist + Identity (и опционально Optimize), которую вендор рекомендует разворачивать через Helm-чарты на Kubernetes.

Что даёт движок, помимо самого исполнения: Tasklist — веб-интерфейс, где исполнитель видит свои задачи и заполняет форму; Cockpit/Operate — панель мониторинга, где видно, на каком шаге завис конкретный инстанс и почему; встроенный аудит — полная история переходов процесса как факт, доступный для выгрузки. Это то, чего не даёт очередь задач: живая визуализация процесса для бизнеса и юридически значимый след «кто, когда и с какими данными принял решение».

Когда BPMN-движок — это правильный выбор

Camunda оправдана, когда в процессе есть то, что действительно требует движка, а не просто последовательности шагов:

  • Ветвления по условиям (exclusive gateway). Заявка на закупку до определённой суммы идёт по одному пути, выше — по другому, с дополнительным согласованием у финансового директора. Условие само может зависеть от нескольких полей заявки одновременно, и таких условных развилок в процессе не одна, а несколько подряд.
  • Параллельные ветки (parallel gateway). Документ одновременно уходит на юридическую и на финансовую проверку, и процесс должен дождаться обеих, прежде чем продолжить — независимо от того, какая ветка завершится раньше.
  • Тайм-ауты и эскалации (boundary timer event). Если согласующий не отреагировал за N часов, задача автоматически уходит его руководителю или процесс переключается на запасной путь. Реализовать такое вручную — это отдельный планировщик с состоянием по каждой задаче, а в BPMN это один элемент на диаграмме.
  • Обработка ошибок как часть процесса (error boundary event). Внешний сервис (например, платёжный шлюз) вернул ошибку — процесс не падает, а идёт по заранее описанной альтернативной ветке: повтор, ручное вмешательство, откат.
  • Процесс меняется чаще, чем готов деплоиться код. Если бизнес-аналитик регулярно правит логику согласования (добавил ступень, поменял порог суммы), редактируемая BPMN-диаграмма отделяет логику процесса от кода приложения.
  • Нужен формальный аудит для комплаенса. В страховании, банках, производстве с регуляторными требованиями важно доказать не просто факт «согласовано», а точную последовательность шагов, кто и когда принял решение, с какими данными на входе — и чтобы это хранилось неизменяемо.
  • Объём инстансов такой, что нужна масштабируемость движка. Тысячи параллельных процессов в час — это тот случай, ради которого в принципе существует Zeebe с его горизонтальным партиционированием.

Если у вас есть хотя бы два-три пункта из этого списка одновременно — Camunda, скорее всего, окупает себя. Один параллельный шлюз без тайм-аутов и без требований к аудиту — ещё не повод.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Три последовательных согласования — типичный случай оверинжиниринга

Возьмём реальный и частый сценарий: сотрудник подаёт заявку на компенсацию расходов. Её смотрит непосредственный руководитель, затем бухгалтерия, затем деньги переводятся. Три шага, строго последовательно, без ветвлений, без параллельности, без SLA-эскалаций — просто цепочка «одобрил → перешло дальше».

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

Ответ по существу: ничего, что оправдывало бы JVM, отдельную схему БД на полсотни таблиц и Tasklist как интерфейс для трёх человек. Та же задача решается таблицей:

CREATE TABLE expense_requests (
    id SERIAL PRIMARY KEY,
    employee_id INT NOT NULL,
    amount NUMERIC(10,2) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'pending_manager',
    -- pending_manager -> pending_finance -> approved / rejected
    manager_id INT,
    manager_decided_at TIMESTAMPTZ,
    finance_decided_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Переход между статусами — это UPDATE ... SET status = 'pending_finance' внутри обычной транзакции приложения. Уведомление следующему согласующему — вебхук в Telegram-бота или письмо, отправленное тем же обработчиком, что сменил статус. История переходов, если она реально нужна для аудита, — это отдельная таблица expense_requests_history с триггером AFTER UPDATE, а не полноценный движок с REST API, XML-моделью и веб-консолью.

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

Практическое правило простое: если процесс можно нарисовать одной прямой линией без единого ромбика-развилки — это не BPMN-кандидат, а последовательность статусов в одной таблице. О похожем антипаттерне — когда для периодической задачи ставят брокер сообщений вместо cron — есть отдельный разбор: очередь сообщений там, где хватило бы cron. Логика та же: инструмент выбирают по репутации «правильной архитектуры», а не по факту требований задачи.

Цена Java-стека, которую не видно в момент выбора

Решение поставить Camunda принимается на этапе проектирования, а считать его стоимость приходится потом, в эксплуатации — и это почти всегда дороже, чем кажется на старте.

Сам стек. Camunda 7 — это JVM плюс контейнер приложений (Tomcat/WildFly) либо Spring Boot-обёртка, плюс реляционная БД под служебные таблицы движка. Даже для скромной нагрузки это означает: настройку JVM-хипа и параметров сборщика мусора, обновление минорных версий Java по мере выхода патчей безопасности, миграции схемы БД движка при апгрейде версии Camunda (у движка бывают breaking changes между мажорными релизами, которые требуют отдельного плана миграции, а не просто docker pull новой версии образа).

Camunda 8 — стек тяжелее на порядок. Self-managed развёртывание — это не один сервис, а Zeebe (сам движок), Elasticsearch или OpenSearch (без него не работают Operate и Tasklist), Identity для авторизации, и опционально Optimize со своей БД. Официально рекомендуемый способ раскатки — Helm-чарты на Kubernetes, то есть поверх Java-стека появляется ещё и оркестратор контейнеров. Если у вас три последовательных согласования, а инфраструктура под них — это Kubernetes-кластер с Elasticsearch, вопрос «а точно ли нам это нужно» стоит задать себе ещё раз, до того как всё это развёрнуто. О том, когда переход на Kubernetes от простого docker-compose действительно оправдан (а когда это решение проблемы, которой ещё нет), — в отдельной статье: из Docker Compose в Kubernetes: когда это оправдано.

Экспертиза и ресурсы. Java и Spring — не всегда родной стек для команды, которая пишет продукт на Node.js, PHP или Python. Найм или обучение человека, способного разбираться в инцидентах движка (зависший инстанс процесса, ошибка десериализации переменной, конфликт версии при деплое новой BPMN-модели поверх запущенных инстансов), — постоянная статья расходов, а не разовая. Плюс сама JVM ощутимо прожорливее по памяти, чем условный Node.js-сервис на том же объёме запросов; точную цифру под свою нагрузку нужно измерять профилированием, а не брать из общих ориентиров в документации.

Ещё один сервис, который может упасть в 3 часа ночи. У каждого дополнительного компонента в стеке — свой режим отказа. Elasticsearch, на который завязаны Operate и Tasklist в Camunda 8, — это ещё один кластер, за здоровьем которого кто-то следит: сегменты, дисковое пространство, ребалансировка шардов. Для процесса из трёх шагов это избыточная плата за операционную сложность, которую вы теперь несёте бессрочно.

Что развернуть вместо — простая очередь задач

Если после списка выше стало ясно, что ваш процесс — это последовательность без развилок, вариантов проще Camunda несколько, и выбор зависит от того, что уже есть в инфраструктуре.

Вариант 1 — таблица статусов в существующей БД приложения. Показан выше: одно поле status, переходы в коде приложения, уведомления через существующий канал (бот, письмо, вебхук). Ноль новых сервисов, ноль новых зависимостей. Подходит, когда процесс живёт внутри уже существующего продукта и не нужен отдельный UI для согласующих — они реагируют на уведомление и переходят по ссылке в уже знакомый интерфейс.

Вариант 2 — лёгкая тикет-система, если согласующим нужен отдельный UI. Когда согласование происходит не внутри вашего продукта, а как отдельная сущность (внутренние заявки сотрудников без доступа к основному приложению), проще поднять лёгкий helpdesk и вести согласование как переходы тикета между статусами — без движка процессов вообще. Пример готового docker-compose: Zammad в Docker Compose — тяжелее, чем таблица с двумя полями, но кардинально легче Camunda: одно Rails-приложение с PostgreSQL и Redis, без JVM и Elasticsearch.

Вариант 3 — no-code/low-code автоматизация, если шагов больше одного-двух, но развилок всё ещё нет. Для цепочки «уведомление → ожидание ответа → следующий шаг → запись результата» без сложной бизнес-логики подходят инструменты вроде n8n — они дают визуальный конструктор шагов без полноценной модели процессов BPMN и без Java-стека под капотом.

Общий принцип для БД под любой из этих вариантов не меняется — понадобится обычный PostgreSQL, и базовая установка описана в статье как установить и настроить PostgreSQL на VPS, если у вас его ещё нет под рукой.

Сравнение по сути:

КритерийТаблица статусов / ботЛёгкий helpdesk (Zammad/Freescout)Camunda 7Camunda 8
Ветвления процессанет, пишете в кодеограниченно, вручнуюда, BPMN gatewayда, BPMN gateway
Параллельные шагивручную, сложнонетдада
Визуальная диаграмма для бизнесанетнетдада
Тайм-ауты/эскалациивручную (cron)частичнода, встроеннода, встроенно
Стектот же, что у приложенияRuby/PostgreSQL/RedisJVM + реляционная БДZeebe + Elasticsearch/OpenSearch + Identity
Порог входа для командыминимальныйнизкийсредний-высокийвысокий
Аудит с юридическим весомнужно делать самимбазовыйвстроенныйвстроенный

Как понять, какой инструмент вам действительно нужен

Перед тем как разворачивать движок, стоит честно ответить на несколько вопросов о самом процессе, а не об инструменте:

  • Можно ли нарисовать процесс одной прямой линией шагов без единого ромбика-развилки? Если да — это не BPMN-кандидат.
  • Есть ли хотя бы одна точка, где путь реально зависит от условия (сумма, тип заявки, роль согласующего)? Одна такая точка ещё не оправдывает движок, три-четыре — уже да.
  • Нужна ли параллельная обработка, где процесс ждёт завершения нескольких независимых веток одновременно?
  • Есть ли требование по SLA — автоматическая эскалация, если согласующий не отреагировал за определённое время?
  • Меняется ли логика процесса чаще, чем вы готовы деплоить код, и меняет ли её не разработчик, а бизнес-аналитик?
  • Есть ли регуляторное требование к аудиту в форме неизменяемого журнала переходов, а не просто лога приложения?

Если на большинство вопросов ответ «нет» — сэкономьте себе JVM, схему на полсотни таблиц (или Elasticsearch-кластер, если смотрели в сторону Camunda 8) и порог входа для команды. Простая таблица статусов с уведомлениями решит задачу быстрее и дешевле в поддержке. Если же ответов «да» набирается три и больше — Camunda окупит себя тем, что не даст вам самим написать урезанную и хуже протестированную версию движка процессов внутри бизнес-логики приложения — а это неизбежно происходит, когда простую очередь начинают дотягивать до BPMN руками.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Можно ли начать с простой очереди, а потом мигрировать на Camunda, если процесс усложнится?

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

Camunda 7 или Camunda 8, если процесс всё-таки оправдывает движок?

Camunda 7 проще развернуть (один сервис плюс реляционная БД) и достаточна для процессов среднего объёма без требований к горизонтальному масштабированию. Camunda 8 на Zeebe тяжелее в эксплуатации (Elasticsearch/OpenSearch, обычно Kubernetes), но даёт масштабируемость под высокую пропускную способность. Для типичного внутреннего согласования в компании среднего размера Camunda 7 реже избыточна, чем Camunda 8.

А если процесс сейчас простой, но в компании считают, что он усложнится через полгода?

Тогда стоит закладывать движок заранее — но проверьте предположение фактами (roadmap продукта, реальные заявки бизнеса на новые ветки процесса), а не общим ощущением «наверняка усложнится». Такое ощущение — самая частая причина оверинжиниринга задним числом, ровно как и с очередями сообщений вместо cron.

Нужен ли отдельный сервер под Camunda, или можно на том же VPS, где крутится основное приложение?

Camunda 7 разворачивается рядом с приложением на среднем VPS без проблем, если нагрузка невелика. Camunda 8 с Elasticsearch и, как правило, Kubernetes уже требует отдельных ресурсов — совмещать с production-нагрузкой основного продукта на одной машине рискованно из-за конкуренции за память и диск.

Что делать, если Camunda уже развёрнута под простой процесс, а хочется упростить?

Оцените реальную стоимость миграции назад — вынести три шага из движка в таблицу статусов дешевле, чем кажется: логика согласования и так уже описана в BPMN-диаграмме, её нужно просто переписать в код state machine. Дороже обходится не сама миграция, а страх «а вдруг процесс усложнится» — его стоит проверить фактами, а не бояться абстрактно.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →