Migrating from Camunda 7
This guide describes how to migrate process solutions developed for Camunda Platform 7 to run them on Camunda Cloud.
You will see the basic differences of the products, learn about necessary steps, and also limitations of migration.
It's important to note that migration of existing projects to Camunda Cloud is optional. Camunda Platform 7 is a great product with ongoing support.
Camunda 7 vs. Camunda Cloud​
Before diving into concrete steps on migrating your models and code, let's cover some important conceptual differences between between Camunda 7 and Camunda Cloud and how this affects your projects and solutions. After this section, we'll dive into a concrete how-to.
Conceptual differences​
This section does not compare Camunda Platform 7 with Camunda Cloud in detail, but rather lists differing aspects important to know when thinking about migration.
No embedded engine in Camunda Cloud​
Camunda Platform 7 allows embedding the workflow engine as a library in your application. This means both run in the same JVM, share thread pools, and can even use the same datasource and transaction manager.
In contrast, the workflow engine in Camunda Cloud is always a remote resource for your application, while the embedded engine mode is not supported.
If you are interested in the reasons why we switched our recommendation from embedded to remote workflow engines, please refer to this blog post.
The implications for your process solution and the programming model are describeed below. Conceptually, the only really big difference is that with a remote engine, you cannot share technical ACID transactions between your code and the workflow engine. You can read more about it in the blog post "Achieving consistency without transaction managers".
Different data types​
In Camunda Platform 7, you can store different data types, including serialized Java objects.
Camunda Cloud only allows storage of primary data types or JSON as process variables. This might require some additional data mapping in your code when you set or get process variables.
Camunda Platform 7 provides Camunda Spin to ease XML and JSON handling. This is not available with Camunda Cloud, and ideally you migrate to an own data transformation logic you can fully control (e.g. using Jackson).
To migrate existing process solutions that use Camunda Spin heavily, you can still add the Camunda Spin library to your application itself and use its API to do the same data transformations as before in your application code.
Expression language​
Camunda Platform 7 uses JUEL (Java Unified Expression Language) as the expression language. In the embedded engine scenario, expressions can even read into beans (Java object instances) in the application.
Camunda Cloud uses FEEL (Friendly-Enough Expression Language and expressions can only access the process instance data and variables.
Most expressions can be converted (see this community extension as a starting point, some might need to be completely rewritten, and some might require an additional service task to prepare necessary data (which may have been calculated on the fly when using Camunda Platform 7).
Different connector infrastructure​
Camunda Platform 7 provides several connectors. These connectors are not supported in Camunda Cloud, as Camunda Cloud aims to create a much more powerful connector infrastructure.
To migrate existing connectors, create a small bridging layer to invoke these connectors via a custom job workers.
Process solutions using Spring Boot​
With Camunda 7, a frequently used architecture to build a process solution (also known as process applications) is composed out of:
- Java
- Spring Boot
- Camunda Spring Boot Starter with embedded engine
- Glue code implemented in Java Delegates (being Spring beans)
This is visualized on the left-hand side of the picture below. With Camunda Cloud, a comparable process solution would look like the right-hand side of the picture and leverage:
- Java
- Spring Boot
- Spring Zeebe Starter (embeding the Zeebe client)
- Glue code implemented as workers (being Spring beans)
The difference is that the engine is no longer embedded, which is also our latest greenfield stack recommendation in Camunda 7. If you are interested in the reasons why we switched our recommendation from embedded to remote workflow engines, please refer to this blog post.
The packaging of a process solution is the same with Camunda 7 and Camunda Cloud. Your process solution is one Java application that consists of your BPMN and DMN models, as well as all glue code needed for connectivity or data transformation.
Process solution definition taken from "Practical Process Automation".
You can find a complete Java Spring Boot example, showing the Camunda Platform 7 process solution alongside the comparable Camunda Cloud process solution in the Camunda Platform 7 to Camunda Cloud example.
Programming model​
The programming model of Camunda 7 and Camunda Cloud are very similar if you program in Java and use Spring.
For example, a worker in Camunda Cloud can be implemented like this (using spring-zeebe):
@ZeebeWorker(type = "payment", autoComplete = true)
public void retrievePayment(ActivatedJob job) {
// Do whatever you need to, e.g. invoke a remote service:
String orderId = job.getVariablesMap().get("orderId");
paymentRestClient.invoke(...);
}
You can find more information on the programming model in Camunda Cloud in this blog post.
JUnit testing with an embedded in-memory engine is also possible with Camunda Cloud, see spring-zeebe documentation.
Platform deployment​
A typical deployment of the workflow engine itself looks different because the workflow engine is no longer embedded into your own deployment artifacts.
With Camunda 7 a typical deployment includes:
- Your Spring Boot application with all custom code and the workflow engine, cockpit, and tasklist embedded. This application is typically scaled to at least two instances (for resilience)
- A relational database
- An elastic database (for Optimize)
- Optimize (a Java application)
With Camunda Cloud you deploy:
- Your Spring Boot application with all custom code and the Zeebe client embedded. This application is typically scaled to at least two instances (for resilience)
- The Zeebe broker, typically scaled to at least three instances (for resilience)
- An elastic database (for Operate, Taskliste, and Optimize)
- Optimize, Operate, and Tasklist (each one is a Java application). You can scale those application to increase availability if you want.
Camunda Cloud deployments happen within Kubernetes. There are Helm charts available if you want to run Camunda Cloud self-managed.
Camunda cloud is also available as a SaaS offering from Camunda, in this case, you only need to deploy your own process solution and Camunda operates the rest.
For local development purposes, you can spin up Camunda Cloud on a developer machine using Docker or Docker Compose. Of course, developers could also create a cluster for development purposes in the SaaS offering of Camunda.
Other process solution architectures​
Besides Spring Boot there are also other environments being used to build process solutions.
Container-managed engine (Tomcat, WildFly, Websphere & co)​
Camunda Cloud doesn't provide integration into Jakarta EE application servers like Camunda Platform 7 does. Instead, Jakarta EE applications need to manually add the Zeebe client library. The implications are comparable to what is described for Spring Boot applications in this guide.
CDI or OSGI​
Due to limited adoption, there is no support for CDI or OSGI in Camunda Cloud. A lightweight integration layer comparable to Spring Zeebe might evolve in the feature and we are happy to support this as a community extension to the Zeebe project.
Polyglot applications (C#, NodeJS, ...)​
When you run your application in for example NodeJS or C#, you exchange one remote engine (Camunda Platform 7) with another (Camunda Cloud). As Zeebe comes with a different API, you need to adjust your source code. Camunda Cloud does not use REST as API technology, but gRPC, so you will need to leverage a client library instead.
Plugins​
Process engine plugins are not available in Camunda Cloud, as such plugins can massively change the behavior or even harm the stabilty of the engine. Some use cases might be implemented using exporters. Note that exporters are only available for self-managed Zeebe clusters and not in Camunda Cloud SaaS.
Migrating Modeler Plugins is generally possible, as the same modeler infrastructure is used.
Cockpit or tasklist plugins cannot be migrated.
Migration overview​
Let's discuss if you need to migrate first, before diving into the necessary steps and what tools can help you achieve the migration.
When to migrate?​
New projects should typically be started using Camunda Cloud.
Existing solutions using Camunda 7 might simply keep running on Camunda 7. The platform has ongoing support, so there is no need to rush on a migration project.
You should consider migrating existing Camunda 7 solutions if:
- You are looking to leverage a SaaS offering (e.g. to reduce the effort for hardware or infrastructure setup and maintenance).
- You are in need of performance at scale and/or improved resilience.
- You are in need of certain features that can only be found in Camunda Cloud (e.g. BPMN message buffering, big multi-instance constructs, the new connectors framework, or the improved collaboration features in web modeler).
Migration steps​
For migration, you need to look at development artifacts (BPMN models and application code), but also at workflow engine data (runtime and history) in case you migrate a process solution running in production.
The typical steps are:
- Migrate development artifacts
- Adjust your BPMN models (only in rare cases you have to touch your DMN models)
- Adjust your development project (remove embedded engine, add Zeebe client)
- Refactor your code to use the Zeebe client API
- Refactor your glue code or use the Java Delegate adapter project.
- Migrate workflow engine data
In general, development artifacts can be migrated:
BPMN models: Camunda Cloud uses BPMN like Camunda Platform 7 does, which generally allows use of the same model files, but you might need to configure different extension atrributes (at least by using a different namespace). Furthermore, Camunda Cloud has a different coverage of BPMN concepts that are supported (see Camunda Cloud BPMN coverage vs Camunda Platform 7 BPMN coverage), which might require some model changes. Note that the coverage of Camunda Cloud will increase over time.
DMN models: Camunda Cloud uses DMN like Camunda Platform 7 does. There are no changes in the models necessary. Some rarely used features of Camunda Platform 7 are not supported in Camunda Cloud. Those are listed below.
CMMN models: It is not possible to run CMMN on Zeebe, CMMN models cannot be migrated. You can remodel cases in BPMN according to Building Flexibility into BPMN Models, keeping in mind the Camunda Cloud BPMN coverage.
Application code: The application code needs to use a different client library and different APIs. This will lead to code changes you must implement.
Architecture: The different architecture of the core workflow engine might require changes in your architecture (e.g. if you used the embedded engine approach). Furthermore, certain concepts of Camunda Platform 7 are no longer possible (like hooking in Java code at various places, or control transactional behavior with asynchronous continuations) which might lead to changes in your model and code.
In general, workflow engine data is harder to migrate to Camunda Cloud:
Runtime data: Running process instances of Camunda Platform 7 are stored in the Camunda Platform 7 database. Like with a migration from third party workflow engines, you can read this data from Camunda 7 and use it to create the right process instances in Camunda Cloud in the right state. This way, you can migrate running process instances from Camunda 7 to Camunda Cloud, but some manual effort is required.
History data: Historic data from the workflow engine itself cannot be migrated. However, data in Optimize can be kept.
Migration tooling​
The Camunda Platform 7 to Camunda Cloud migration tooling, available as a community extension, contains two components that will help you with migration:
A Desktop Modeler plugin to convert BPMN models from Camunda Platform 7 to Camunda Cloud. This maps possible BPMN elements and technical attributes into the Camunda Cloud format and gives you warnings where this is not possible. This plugin might not fully migrate your model, but should give you a jump-start. It can be extended to add your own custom migration rules. Note that the model conversion requires manual supervision.
The Camunda Platform 7 to Camunda Cloud Adapter. This is a library providing a worker to hook in Camunda Platform-based glue code. For example, it can invoke existing JavaDelegate classes.
In essence, this tooling implements details described in the next sections.
Adjusting your source code​
Camunda Cloud has a different API than Camunda Platform 7. As a result, you have to migrate some of your code, especially code that does the following:
- Uses the Client API (e.g. to start process instances)
- Implements service tasks, which can be:
- Java code attached to a service task and called by the engine directly (in-VM).
- External tasks, where workers subscribe to the engine.
For example, to migrate an existing Spring Boot application, take the following steps:
- Adjust Maven dependencies
- Remove Camunda Platform 7 Spring Boot Starter and all other Camunda dependencies.
- Add Spring Zeebe Starter.
- Adjust config
- Make sure to set Camunda Cloud credentials (for example, in
src/main/resources/application.properties
) and point it to an existing Zeebe cluster. - Remove existing Camunda Platform 7 settings.
- Replace
@EnableProcessApplication
with@EnableZeebeClient
in your main Spring Boot application class. - Add
@ZeebeDeployment(resources = "classpath*:**/*.bpmn")
to automatically deploy all BPMN models.
Finally, adjust your source code and process model as described in the sections below.
Client API​
All Camunda Cloud APIs (e.g. to start process instances, subscribe to tasks, or complete them) have been completely redesigned are not compatible with Camunda Platform 7. While conceptually similar, the APIs use different method names, data structures, and protocols.
If this affects large parts of your code base, you could write a small abstraction layer implementing the Camunda Platform 7 API delegating to Camunda Cloud, probably marking unavailable methods as deprecated. We welcome community extensions that facilitate this.
Service tasks with attached Java code (Java Delegates, Expressions)​
In Camunda Platform 7, there are three ways to attach Java code to service tasks in the BPMN model using different attributes in the BPMN XML:
- Specify a class that implements a JavaDelegate or ActivityBehavior:
camunda:class
. - Evaluate an expression that resolves to a delegation object:
camunda:delegateExpression
. - Invoke a method or value expression:
camunda:expression
.
Camunda Cloud cannot directly execute custom Java code. Instead, there must be a job worker executing code.
The Camunda Platform 7 to Camunda Cloud Adapter implements such a job worker using Spring Zeebe. It subscribes to the task type camunda-platform-to-cloud-migration
. Task headers are used to configure a delegation class or expression for this worker.
You can use this worker directly, but more often it might serve as a starting point or simply be used for inspiration.
The Camunda Platform 7 to Camunda Cloud Converter Modeler plugin will adjust the service tasks in your BPMN model automatically for this adapter.
The topic camunda-platform-to-cloud-migration
is set and the following attributes/elements are migrated and put into a task header:
camunda:class
camunda:delegateExpression
camunda:expression
andcamunda:resultVariable
Service tasks as external tasks​
External task workers in Camunda Platform 7 are conceptually comparable to job workers in Camunda Cloud. This means they are generally easier to migrate.
The "external task topic" from Camunda Platform 7 is directly translated in a "task type name" in Camunda Cloud, therefore camunda:topic
gets zeebe:taskDefinition type
in your BPMN model.
Now, you must adjust your external task worker to become a job worker.
Adjusting Your BPMN models​
To migrate BPMN process models from Camunda Platform 7 to Camunda Cloud, you must adjust them:
- The namespace of extensions has changed (from
http://camunda.org/schema/1.0/bpmn
tohttp://camunda.org/schema/zeebe/1.0
) - Different configuration attributes are used
- Camunda Cloud has a different coverage of BPMN elements (see Camunda Cloud BPMN coverage vs Camunda Platform 7 BPMN coverage), which might require some model changes. Note that the coverage of Camunda Cloud will increase over time.
The following sections describe what the existing Camunda Platform 7 to Camunda Cloud migration tooling does by BPMN symbol and explain unsupported attributes.
Service tasks​
Migrating a service task is described in detail in the section about adjusting your source code above.
A service task might have attached Java code. In this case, the following attributes/elements are migrated and put into a task header:
camunda:class
camunda:delegateExpression
camunda:expression
andcamunda:resultVariable
The topic camunda-platform-to-cloud-migration
is set.
The following attributes/elements cannot be migrated:
camunda:asyncBefore
: Every task in Zeebe is always asyncBefore and asyncAfter.camunda:asyncAfter
: Every task in Zeebe is always asyncBefore and asyncAfter.camunda:exclusive
: Jobs are always exclusive in Zeebe.camunda:jobPriority
: There is no way to prioritize jobs in Zeebe (yet).camunda:failedJobRetryTimeCycle
: You cannot yet configure the retry time cycle.
A service task might leverage external tasks instead. In this case, the following attributes/elements are migrated:
camunda:topic
getszeebe:taskDefinition type
.
The following attributes/elements cannot be migrated:
camunda:taskPriority
Service tasks using camunda:type
cannot be migrated.
Service tasks using camunda:connector
cannot be migrated.
Send tasks​
In both engines, a send task has the same behavior as a service task. A send task is migrated exactly like a service task.
Gateways​
Gateways rarely need migration. The relevant configuration is mostly in the expressions on outgoing sequence flows.
Expressions​
Expressions need to be in FEEL (friendly-enough expression language) instead of JUEL (Java unified expression language).
Migrating simple expressions is doable (as you can see in these test cases), but not all expressions can be automatically converted.
The following is not possible:
- Calling out to functional Java code using beans in expressions
- Registering custom function definitions within the expression engine
Human tasks​
Human task management is also available in Camunda Cloud, but uses a different tasklist user interface and API.
In Camunda Platform 7, you have different ways to provide forms for user tasks:
- Embedded Task Forms (embedded custom HTML and JavaScript)
- Camunda Forms (simple forms defined via Desktop Modeler properties)
- External Task Forms (link to custom applications)
- Camunda Forms
Only Camunda Forms are currently supported in Camunda Cloud and can be migrated.
The following attributes/elements can be migrated:
- Task assignment (to users or groups):
bpmn:humanPerformer
bpmn:potentialOwner
camunda:assignee
camunda:candidateGroups
camunda:formKey
, but Camunda Cloud requires you to embedd the form definition itself into the root element of your BPMN XML models, see this guide.
The following attributes/elements cannot (yet) be migrated:
camunda:candidateUsers
(only candidate groups are supported)- Form handling:
camunda:formHandlerClass
camunda:formData
camunda:formProperty
camunda:taskListener
camunda:dueDate
camunda:followUpDate
camunda:priority
Business rule tasks​
For some time, the DMN engine was not yet directly integrated into Camunda Cloud, which is why the Zeebe DMN Worker, provided as as a community extension, was used to execute your existing DMN models. This is subject to change soon, as out-of-the-box support for DMN is added to Camunda Cloud at the moment.
The migration tool currently sets the task definition type to DMN
and the camunda:decisionRef
is moved to a task header attribute for this worker.
The following attributes/elements can be migrated:
camunda:decisionRef
The following attributes are not yet supported:
camunda:decisionRefBinding
,camunda:decisionRefVersion
, andcamunda:decisionRefVersionTag
(always use the latest version)camunda:mapDecisionResult
(no mapping happens)camunda:resultVariable
(result is always mapped to variable 'result' and can be copied or unwrapped using ioMapping).camunda:decisionRefTenantId
A business rule task can also behave like a service task to allow integration of third-party rule engines. In this case, the following attributes can also be migrated as described above for the service task migration: camunda:class
, camunda:delegateExpression
, camunda:expression
, or camunda:topic
.
The following attributes/elements cannot be migrated:
camunda:asyncBefore
,camunda:asyncBefore
,camunda:asyncAfter
,camunda:exclusive
,camunda:failedJobRetryTimeCycle
, andcamunda:jobPriority
camunda:type
andcamunda:taskPriority
camunda:connector
Call activities​
Call activities are generally supported in Zeebe. The following attributes/elements can be migrated:
camunda:calledElement
will be converted intozeebe:calledElement
- Data Mapping
camunda:in
camunda:out
The following attributes/elements cannot be migrated:
camunda:calledElementBinding
: Currently Zeebe always assumes 'late' binding.camunda:calledElementVersionTag
: Zeebe does not know a version tag.camunda:variableMappingClass
: You cannot execute code to do variable mapping in Zeebe.camunda:variableMappingDelegateExpression
: You cannot execute code to do variable mapping in Zeebe.
Script task​
Script tasks cannot natively be executed by the Zeebe engine. They behave like normal service tasks instead, which means you must run a job worker that can execute scripts. One available option is to use the Zeebe Script Worker, provided as a community extension.
If you do this, the following attributes/elements are migrated:
camunda:scriptFormat
camunda:script
camunda:resultVariable
The task type is set to script
.
The following attributes/elements cannot be migrated:
camunda:asyncBefore
: Every task in Zeebe is always asyncBefore and asyncAfter.camunda:asyncAfter
: Every task in Zeebe is always asyncBefore and asyncAfter.camunda:exclusive
: Jobs are always exclusive in Zeebe.camunda:jobPriority
: There is no way to priotize jobs in Zeebe (yet).camunda:failedJobRetryTimeCycle
: You cannot yet configure the retry time cycle.
Message receive events and receive tasks​
Message correlation works slightly different between the two products:
Camunda Platform 7 simply waits for a message, and the code implementing that the message is received queries for a process instance the message will be correlated to. If no process instance is ready to receive that message, an exception is raised.
Camunda Cloud creates a message subscription for every waiting process instance. This subscription requires a value for a
correlationKey
to be generated when entering the receive task. The code receiving the external message correlates using the value of thecorrelationKey
.
This means you must inspect and adjust all message receive events or receive tasks in your model to define a reasonable correlationKey
. You also must adjust your client code accordingly.
The bpmn message name
is used in both products and doesn't need migration.
Adjusting your DMN models​
For Camunda Cloud, a former community extension, built by core Camunda developers, is productized. This engine has a higher coverage of DMN elements. This engine can execute DMN models designed for Camunda Platform 7, however, there are some small differences which can be assessed looking at this issue.
The DMN engine is being added to the Camunda Cloud stack at the moment and might not yet be available to you when you read this.
Prepare for smooth migrations​
Whenever you build a process solution using Camunda Platform 7, you can follow these recommendations to create a process solution that will be easier to migrate later on:
- Use Java, Maven, and Spring Boot.
- Separate your business logic from Camunda API.
- Use external tasks.
- Stick to basic usage of public API (no engine plugins or extensions).
- Don't expose Camunda APIs (REST or Java) to front-end applications.
- Use primitive variable types or JSON payloads only (no XML or serialized Java objects).
- Use JSONPath on JSON payloads (translates easier to FEEL).
- Stick to BPMN elements supported in Camunda Cloud.
- Use FEEL as script language in BPMN, e.g. on Gateways.
- Use Camunda Forms.
Open issues​
As described earlier in this guide, migration is an ongoing topic and this guide is far from complete. Open issues include the following:
- Describe implications on testing.
- Discuss adapters for Java or REST client.
- Discuss external task adapter for Java code and probably add it to the Camunda Platform 7 to Camunda Cloud Adapter.
- Discuss more concepts around BPMN
Field injection that is using
camunda:field
available on many BPMN elements. Multiple instance markers available on most BPMN elements.camunda:inputOutput
available on most BPMN elements.camunda:errorEventDefinition
available on several BPMN elements.
And even more.
Please reach out to us to discuss your specific migration use case.
Summary​
In this guide, you hopefully gained a better understanding of what migration from Camunda Platform 7 to Camunda Cloud means. Specifically, this guide outlined the following:
- Differences in application architecture
- How process models and code can generally be migrated, whereas runtime and history data cannot
- How migration can be very simple for some models, but also marked limitations, where migration might get very complicated
- You need to adjust code that uses the workflow engine API
- How you might be able to reuse glue code
- Community extensions that can help with migration
We are watching all customer migration projects closely and will update this guide in the future.