Series MapLesson 44 / 60
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Deepen PracticeOrdered learning track

Local Development and Developer Workflow

Local Camunda developer workflow: Modeler setup, local Camunda 7/8/Zeebe, Docker Compose, test data, start process, inspect instance, complete task, trigger worker, correlate message, simulate timer/failure, and debug variables.

19 min read3753 words
PrevNext
Lesson 4460 lesson track34–50 Deepen Practice
#camunda#local-development#docker-compose#modeler+5 more

Part 044 — Local Development and Developer Workflow

1. Core mental model

Local workflow development is about shortening the feedback loop between three artifacts:

  1. the BPMN/DMN/form model;
  2. the Java/JAX-RS service and worker implementation;
  3. the runtime state visible in Camunda tooling and supporting infrastructure.

A developer should be able to answer quickly:

  • Can I deploy this model locally?
  • Can I start the process with realistic business data?
  • Can I see where the instance is waiting?
  • Can my worker pick up and complete the job?
  • Can I complete a human task?
  • Can I correlate an external message?
  • Can I simulate timeout/failure/retry/incident?
  • Can I inspect variables safely?
  • Can I reproduce a production symptom with local data?

Senior rule:

If a workflow cannot be run and debugged locally or in a disposable dev environment, production debugging will become guesswork.

Local development does not need to perfectly replicate production. It must replicate enough runtime behavior to expose model-worker-contract errors before deployment.

2. Local development goals

The local workflow environment should support:

  • editing BPMN/DMN/forms;
  • validating model syntax;
  • deploying process artifacts;
  • starting process instances;
  • completing service tasks via local workers;
  • completing user tasks via API/UI/tooling;
  • correlating messages;
  • testing timers without waiting real business time;
  • forcing worker failure;
  • observing incidents/failed jobs;
  • checking process variables;
  • checking database state;
  • checking Kafka/RabbitMQ/Redis side effects where relevant;
  • iterating quickly without shared-environment dependency.

A local setup that only opens the diagram is not enough.

3. Developer environment layers

A practical setup has layers.

LayerPurposeExample
Model layerauthor BPMN/DMN/formsCamunda Modeler/Web Modeler/Desktop Modeler
Runtime layerexecute processCamunda 7 engine, Camunda 8 local orchestration cluster, test runtime
Worker layerrun Java worker/delegate/external task codelocal JVM service
API layerstart/complete/correlate via JAX-RSlocal REST service
Data layerbusiness persistencePostgreSQL/Testcontainers/local DB
Messaging layerevent/command integrationKafka/RabbitMQ local containers
Cache/support layerlocks/cache/idempotencyRedis local container
Observability layerinspect process/logs/metricsOperate/Cockpit/Tasklist/log viewer

You do not need every layer for every task. Choose the smallest local stack that can reproduce the behavior being changed.

4. Camunda Modeler workflow

The modeler workflow should be disciplined.

Basic loop:

  1. open BPMN/DMN/form artifact;
  2. modify a small, reviewable part;
  3. validate model;
  4. deploy locally;
  5. start process with fixture data;
  6. inspect runtime behavior;
  7. update worker/API/test if contract changed;
  8. run scenario tests;
  9. commit artifact and tests together.

Modeling rules for local development:

  • do not edit BPMN only visually; inspect important XML properties;
  • check process ID, element IDs, job type/topic, message names, timer expressions, error codes;
  • keep element IDs stable unless migration/versioning impact is intentional;
  • do not rename job type/topic without updating workers and tests;
  • do not change variable names casually;
  • add documentation to complex gateways/events;
  • run model validation before commit.

5. Camunda 7 local development mental model

Camunda 7 can run as a Java process engine in different modes.

Local development usually falls into one of these patterns:

PatternDescriptionGood for
Embedded engine in serviceengine starts inside local appdelegate/process app debugging
Shared/container-like engineengine separate from process app styledeployment/classloading realism
Standalone distro/containerengine exposed via REST/UIAPI/external task experiments
Test runtimeprocess engine in testsscenario/unit tests

Local Camunda 7 checklist:

  • engine config is known;
  • history level is not misleading;
  • DB dialect matches production when testing persistence behavior;
  • job executor behavior is understood;
  • async jobs are executed in tests/local runtime;
  • delegate beans/classes resolve correctly;
  • external task workers can fetch-and-lock;
  • Cockpit/Tasklist access exists if used;
  • process deployment lifecycle matches production enough to catch wiring errors.

Common local trap:

Everything works locally because the process runs synchronously in one JVM, but production uses async jobs, DB transactions, multiple nodes, and retries.

If production has async continuations, test async continuations locally.

6. Camunda 8 local development mental model

Camunda 8/Zeebe local development is remote orchestration development.

Your Java service/worker is a client. The engine is not embedded in the application.

Local stack typically includes:

  • Camunda 8 local orchestration cluster or Zeebe runtime;
  • Gateway endpoint;
  • Operate for process inspection;
  • Tasklist for user tasks where applicable;
  • Connectors runtime if connectors are used;
  • Elasticsearch/OpenSearch or equivalent local dependency depending on version/config;
  • Identity/auth components depending on selected local profile;
  • Java worker/client application.

Camunda 8 local rules:

  • configure client endpoint explicitly;
  • verify credentials/auth mode for local runtime;
  • deploy BPMN using the same API/tooling style used by CI where possible;
  • run workers as separate local processes;
  • inspect process instances in Operate;
  • do not assume Operate visibility is perfectly instantaneous;
  • test job timeout and duplicate activation behavior;
  • keep local runtime version close to target environment.

7. Docker Compose local stack

Docker Compose is useful for local Camunda 8 self-managed development and for supporting dependencies.

Use it for:

  • local orchestration cluster;
  • connectors runtime;
  • PostgreSQL;
  • Kafka;
  • RabbitMQ;
  • Redis;
  • mock external APIs;
  • disposable integration testing.

Do not confuse Docker Compose with production architecture.

Docker Compose is for developer feedback. Kubernetes/GitOps/production manifests are separate concerns.

Local Compose quality checklist:

  • services have explicit names and ports;
  • volumes are disposable or intentionally persistent;
  • credentials are local-only;
  • health checks exist where useful;
  • startup order is understood but not over-trusted;
  • logs are easy to inspect;
  • version tags are explicit;
  • profiles exist for lightweight vs full stack;
  • reset command exists for clean state.

8. Minimal local workflow loop

For a service-task-heavy process:

  1. start local runtime;
  2. start local PostgreSQL/Kafka/RabbitMQ/Redis as required;
  3. run Java/JAX-RS service locally;
  4. run job worker/external task worker locally;
  5. deploy BPMN/DMN;
  6. call REST endpoint to start process;
  7. inspect process instance;
  8. verify worker receives task/job;
  9. verify DB state and outbox/message side effects;
  10. complete/correlate next step;
  11. assert process reaches expected wait state or completion;
  12. inspect logs/metrics/variables.

If the workflow has human tasks:

  • query task list;
  • claim task if claim semantics exist;
  • complete task with valid payload;
  • try stale or unauthorized completion;
  • check audit record.

9. Local process start

Starting a process locally should use realistic fixture data.

Avoid toy payloads like:

{
  "x": 1
}

Use domain-like payloads:

{
  "quoteId": "Q-LOCAL-1001",
  "customerId": "CUST-LOCAL-001",
  "requestedBy": "local.engineer",
  "approvalType": "PRICING_EXCEPTION",
  "correlationId": "corr-local-1001",
  "tenantId": "sandbox"
}

A local start script should capture:

  • process definition key;
  • process version if explicit;
  • business key/correlation key;
  • variables;
  • expected first wait state;
  • expected worker/job type;
  • expected task assignment if user task.

10. Inspecting process instance state

When debugging locally, inspect runtime state in this order:

  1. process instance exists;
  2. process definition/version is correct;
  3. current active element is expected;
  4. variables are present and shaped correctly;
  5. jobs/tasks/subscriptions are created;
  6. worker received or failed to receive work;
  7. incidents/failures exist;
  8. DB state matches process state;
  9. messages/events/outbox state matches expected behavior;
  10. logs/trace IDs connect the API request, worker, and process instance.

Do not jump directly to worker code before checking whether the process is actually waiting at the expected task.

11. Completing user tasks locally

A local human task test should cover more than completion.

Workflow:

  1. start process until user task;
  2. verify task exists;
  3. verify candidate group/user or assignment;
  4. claim task if applicable;
  5. read expected form variables;
  6. submit valid completion payload;
  7. verify process moved forward;
  8. verify audit record;
  9. verify invalid/stale/unauthorized completion behavior.

Local scripts should include examples for:

  • list tasks by business key;
  • complete task;
  • complete task with missing required field;
  • attempt complete by wrong user;
  • re-submit after completion.

12. Triggering workers locally

Local worker debugging should make job lifecycle explicit.

Check:

  • job type/topic matches BPMN;
  • worker subscribed to correct endpoint/topic;
  • worker credentials/config are correct;
  • max active jobs/concurrency is reasonable;
  • job timeout is long enough for local debugging;
  • variables requested by worker exist;
  • output variables match gateway expectations;
  • worker logs include process instance key/business key/job key/correlation ID;
  • worker handles shutdown cleanly.

Local worker anti-pattern:

Worker starts, logs nothing, and developer guesses whether it is connected.

Better worker startup log:

worker=order-validation jobType=validate-order endpoint=http://localhost:26500 maxJobs=8 timeout=PT2M

No secrets or PII should appear in logs.

13. Correlating messages locally

Local message correlation should be scriptable.

A useful message script captures:

  • message name;
  • correlation key;
  • process/business ID;
  • TTL/expiration if relevant;
  • payload variables;
  • expected active wait state before correlation;
  • expected active/completed state after correlation.

Test locally:

  • correct message;
  • wrong key;
  • wrong name;
  • duplicate message;
  • late message;
  • message before process is waiting, if buffering/TTL is relevant;
  • message after process completed.

Message correlation debugging order:

  1. Is the process waiting for a message?
  2. Is the message name exactly correct?
  3. Is the correlation key exactly correct?
  4. Is the message published to the right runtime/tenant/environment?
  5. Did TTL expire?
  6. Did the process already move past the catch event?
  7. Is there more than one candidate instance?

14. Simulating timers locally

A local timer workflow should avoid waiting real business durations.

Options:

  • use short local timer values in dev-only process variant if safe;
  • use test runtime clock control where supported;
  • use configuration/expression to reduce duration in local profile;
  • isolate timer behavior in automated tests;
  • manually trigger or modify state only in disposable environment if tooling supports it.

Never commit local-only timer values into production BPMN accidentally.

Timer local checklist:

  • timer expression source is explicit;
  • timezone is documented;
  • duration/date/cycle format is valid;
  • local override cannot leak into production;
  • SLA timer and retry timer are distinguished;
  • timer backlog can be observed.

15. Simulating failures locally

Every workflow developer should know how to create a failure intentionally.

Simulate:

  • worker throws technical exception;
  • worker reports BPMN error;
  • worker times out after side effect;
  • DB is temporarily unavailable;
  • external API returns 500;
  • external API times out;
  • Kafka/RabbitMQ broker is unavailable;
  • Redis is unavailable;
  • message arrives with wrong correlation key;
  • user attempts unauthorized task completion;
  • variable serialization fails;
  • payload is too large.

For each simulation, observe:

  • process state;
  • job retry count;
  • incident/failure metadata;
  • logs;
  • DB state;
  • outbox/inbox state;
  • external message state;
  • operator-visible dashboard state.

16. Local incident debugging loop

When an incident/failure appears locally, debug systematically:

  1. identify process instance;
  2. identify active element/job/task;
  3. read failure message and stack trace;
  4. classify business error vs technical error;
  5. inspect variables needed by the failing element;
  6. inspect worker input mapping;
  7. inspect worker logs by correlation ID;
  8. inspect DB/event side effects;
  9. fix root cause;
  10. retry or restart only after understanding side effects;
  11. add regression test.

Do not retry blindly. Even locally, retrying blindly trains bad production behavior.

17. Local database workflow

If workflow touches PostgreSQL/MyBatis, local setup should make DB state easy to inspect.

Recommended local artifacts:

  • schema migration scripts;
  • seed data for quote/order scenarios;
  • processed job/inbox/outbox tables;
  • SQL snippets for state inspection;
  • reset script;
  • query to find entity by business key;
  • query to find duplicate side effect;
  • query to inspect state transition history.

Example local debug questions:

  • Did the worker commit the business state?
  • Did it write processed-job/idempotency marker?
  • Did it write outbox event?
  • Did it complete the job after DB commit?
  • What happens if job completion failed after commit?
  • Can the duplicate job be safely ignored?

18. Local Kafka workflow

For Kafka-backed workflow paths, local developer workflow should include:

  • topic creation;
  • sample event publication;
  • consumer group reset if needed;
  • event key/correlation key convention;
  • schema validation if schema registry is used;
  • duplicate event script;
  • replay script;
  • out-of-order event script;
  • dead-letter/error topic inspection if used.

Debug order:

  1. Was event produced?
  2. Is topic correct?
  3. Is event key correct?
  4. Is schema compatible?
  5. Did consumer receive it?
  6. Did consumer start/correlate process?
  7. Was duplicate/replay handled idempotently?

19. Local RabbitMQ workflow

For RabbitMQ-backed workflow paths, local workflow should include:

  • exchange/queue/binding setup;
  • routing key examples;
  • command message publication;
  • reply queue/correlation ID setup;
  • ack/nack behavior check;
  • DLQ inspection;
  • retry delay behavior;
  • duplicate redelivery simulation.

Debug order:

  1. Was message routed to the expected queue?
  2. Did worker consume it?
  3. Was message acked only after safe processing?
  4. Was reply correlated to the right process/entity?
  5. Did retry/DLQ interact with workflow retry policy safely?

20. Local Redis workflow

If Redis is used around workflow, local workflow should include:

  • cache inspection commands;
  • lock key naming convention;
  • TTL check;
  • idempotency key check;
  • feature flag/kill switch toggle;
  • Redis flush/reset script;
  • outage simulation.

Debug questions:

  • Is Redis used only as support, not source of truth?
  • What happens if cache is stale?
  • What happens if lock expires while worker is still running?
  • What happens if Redis is unavailable?
  • Does process still recover using DB/engine state?

21. Local API workflow

JAX-RS/API endpoints should have local scripts for:

  • start process;
  • get workflow status;
  • complete task;
  • correlate external message/callback;
  • cancel process/request;
  • retry or repair action if exposed;
  • list tasks by user/group;
  • test authorization failure;
  • test duplicate request with same idempotency key;
  • test missing/invalid payload.

API local debugging should always capture:

  • HTTP request ID;
  • correlation ID;
  • business key;
  • process instance key/id;
  • response status;
  • error body;
  • log trace.

For long-running workflow, prefer local scripts that demonstrate 202 Accepted and status polling/callback semantics rather than fake synchronous success.

22. Environment configuration discipline

Local workflow config should be explicit and safe.

Configuration to externalize:

  • Camunda endpoint;
  • authentication mode;
  • worker name;
  • job types/topics;
  • max jobs/concurrency;
  • job timeout;
  • database URL;
  • Kafka/RabbitMQ/Redis endpoint;
  • feature flags;
  • timer durations for local testing;
  • log level;
  • connector runtime settings.

Never hardcode:

  • production endpoint;
  • production credentials;
  • tenant/customer secrets;
  • real PII;
  • production SLA override;
  • production broker topics without local prefix/profile.

23. Local observability

A local workflow stack should make observability visible during development.

Minimum:

  • structured logs with correlation ID;
  • process instance key/id in worker logs;
  • job key/external task ID in worker logs;
  • business key/quote/order ID in safe form;
  • worker success/failure metrics if available;
  • DB state inspection;
  • message broker inspection;
  • process runtime UI: Operate/Cockpit/Tasklist as applicable.

Local logs should answer:

  • Which API request started this process?
  • Which worker processed this job?
  • Which DB row changed?
  • Which message was published?
  • Why did the job fail?
  • Was this retry safe?

24. Reset and reproducibility

Local workflow development needs reset discipline.

Provide commands to:

  • stop runtime;
  • clear runtime state;
  • reset PostgreSQL schema/data;
  • clear Kafka topics or use new topic prefix;
  • purge RabbitMQ queues;
  • flush Redis local state;
  • remove Docker volumes when needed;
  • redeploy process artifacts;
  • re-seed test data;
  • restart workers.

A bug that only reproduces after three days of local state is hard to share.

Good local reproduction includes:

  • exact branch/commit;
  • exact runtime version;
  • process model version;
  • fixture payload;
  • commands executed;
  • expected vs actual state;
  • logs and screenshots only if safe.

25. Version discipline in local development

Local Camunda version should be tracked.

Record:

  • Camunda 7 version or Camunda 8 version;
  • Zeebe client version;
  • Java client version;
  • Modeler version;
  • connector runtime version;
  • database/search dependency version;
  • local Docker image tags.

Version mismatch can cause false confidence.

Examples:

  • modeler allows BPMN feature not supported by deployed runtime;
  • local runtime supports feature not available in target environment;
  • worker client version differs from cluster compatibility range;
  • connector behavior differs across versions;
  • Tasklist/user task behavior differs between local and production config.

26. Developer workflow for changing BPMN

When changing BPMN:

  1. identify affected process versions and running instances;
  2. change model in small diff;
  3. validate BPMN;
  4. update tests for changed paths;
  5. update worker contract if job type/variables/error codes changed;
  6. run local scenario;
  7. inspect active element and variables;
  8. test failure path;
  9. update deployment/versioning notes;
  10. prepare PR review checklist.

Do not change BPMN and worker code independently if the contract changes.

27. Developer workflow for changing worker code

When changing worker code:

  1. identify job type/topic;
  2. list input variables;
  3. list output variables;
  4. list side effects;
  5. update unit tests;
  6. run integration test with DB/broker if side effects changed;
  7. run local process path that reaches the worker;
  8. simulate duplicate job;
  9. simulate transient failure;
  10. inspect retry/incident behavior;
  11. verify old process instances remain compatible.

A worker change is a process contract change if it changes variable names, error codes, side effects, retry classification, or completion semantics.

28. Developer workflow for changing task UI/API

When changing human task UX/API:

  1. start process to target user task;
  2. verify task search/listing;
  3. verify task authorization;
  4. verify form schema/data;
  5. save draft if supported;
  6. complete with valid payload;
  7. complete with invalid payload;
  8. complete concurrently/stale;
  9. verify process state after completion;
  10. verify audit record;
  11. verify SLA/escalation behavior if affected.

Human task changes must be tested with actual assignment and authorization assumptions, not only direct engine calls.

29. Local-to-CI alignment

Local scripts and CI should not drift.

Prefer:

  • same Docker Compose profile or container images;
  • same test fixtures;
  • same process deployment command;
  • same schema migration command;
  • same environment variable names;
  • same model validation command;
  • same worker config defaults where safe.

If a developer can only reproduce workflow locally using undocumented manual clicks, CI cannot protect production.

30. Common local development anti-patterns

Avoid:

  • editing BPMN without running it;
  • testing only with Modeler validation;
  • running toy payloads unrelated to CPQ/order domain;
  • using production-like secrets locally;
  • relying on real-time sleeps for timers;
  • ignoring duplicate job/message behavior;
  • starting process directly in engine when production starts through JAX-RS API;
  • testing user task completion without authorization layer;
  • mocking DB transaction for idempotency-critical worker;
  • ignoring old running process versions;
  • using Docker Compose as proof of Kubernetes readiness;
  • no reset script;
  • no documented reproduction command.

31. Internal verification checklist

Verify in the actual CSG/team environment:

  • Which local Camunda runtime is expected: Camunda 7, Camunda 8, remote dev cluster, or custom workflow engine.
  • Whether developers use Desktop Modeler, Web Modeler, or internal tooling.
  • Where BPMN/DMN/forms live in repository.
  • How process artifacts are deployed locally.
  • Whether Docker Compose is available for Camunda/dependencies.
  • Whether local PostgreSQL/MyBatis schema setup exists.
  • Whether Kafka/RabbitMQ/Redis local setup exists.
  • Whether local test fixtures represent quote/order scenarios.
  • Whether start process scripts exist.
  • Whether complete task scripts exist.
  • Whether message correlation scripts exist.
  • Whether timer/failure simulation is documented.
  • Whether worker local config is documented.
  • Whether process instance inspection uses Cockpit, Operate, or internal UI.
  • Whether local logs include correlation/process/job IDs.
  • Whether reset scripts exist.
  • Whether local runtime version matches CI/staging/prod enough.
  • Whether local profile prevents production endpoint/secret usage.
  • Whether developers know how to reproduce a stuck process locally.
  • Whether onboarding includes workflow local development exercises.

32. PR review checklist

Ask these questions when reviewing workflow developer experience:

  • Can this process/model change be run locally?
  • Is there a fixture for the changed business scenario?
  • Are local start/correlate/complete commands updated?
  • Can the changed worker be triggered locally?
  • Can the failure path be simulated locally?
  • Does the local setup use safe credentials and local endpoints?
  • Are local and CI commands aligned?
  • Are version assumptions documented?
  • Is reset/reproduction documented?
  • Can another engineer reproduce the issue/change without tribal knowledge?

33. Senior engineer heuristics

  1. Local workflow development must execute state, not just draw diagrams.
  2. The smallest useful local stack is better than a full stack nobody starts.
  3. Run through the API path when API contract matters. Direct engine starts can hide integration bugs.
  4. Run through the worker path when side effects matter. Manual completion can hide worker bugs.
  5. Make duplicate/failure simulation easy. If it is hard locally, it will be ignored.
  6. Keep fixtures business-realistic. Toy variables create false confidence.
  7. Treat local reset as a product feature for developers. Bad reset kills reproducibility.
  8. Do not let local overrides leak into production. Timer and credential overrides are especially risky.
  9. Version mismatch is a hidden source of ghosts. Track runtime/client/modeler versions.
  10. Developer workflow is production risk control. A system that is hard to run locally becomes hard to debug under pressure.

34. Official documentation anchors

Use these as starting points, then verify exact deployed version:

  • Camunda Modeler download and modeling documentation.
  • Camunda 8 self-managed developer quickstart with Docker Compose.
  • Camunda 8 Docker Compose local deployment documentation.
  • Camunda 8 Java client and worker getting started documentation.
  • Camunda 8 Operate and Tasklist documentation.
  • Camunda 8 Camunda Process Test documentation.
  • Camunda 7 getting started, process engine bootstrapping, testing, Cockpit, and Tasklist documentation.
  • Docker Compose, Testcontainers, PostgreSQL, Kafka, RabbitMQ, and Redis local development documentation.

Documentation explains how to start tools. Your internal developer workflow must explain how to reproduce real quote/order workflow behavior safely and repeatedly.

Lesson Recap

You just completed lesson 44 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.