What are you looking for?

From Monolith to Microservices Using Camunda

Overcome many of the challenges of a monolith-to-microservices migration with process orchestration.
By
  • Blog
  • >
  • From Monolith to Microservices Using Camunda

As I was writing my previous blog post, “A Developer’s Guide to Migrating an Existing Workflow to Camunda,” one question kept running through my mind: How can Camunda help development teams migrate away from legacy architectures?

Of course, migrating away from legacy systems is something Camunda and its customers have spoken about at length. At CamundaCon 2024 in Berlin, First American spoke about how they’re leveraging Camunda to modernize their business operations and how Camunda helped them migrate away from several legacy systems.

I was thinking about something closer to development teams, not broader business initiatives. For instance, how can development teams leverage Camunda to help manage tasks such as migrating from one cloud to another? Or, how can development teams use Camunda to migrate from a monolith to microservices?

Migrating legacy architectures before Camunda

One of the primary challenges faced by developers when migrating from an existing monolith to microservices—or any other architecture pattern—is business continuity. Dependencies between different services inside your monolith are more easily managed than dependencies between independently deployed services.

Changing from a monolith to microservices changes how those services communicate: while they used to communicate directly within your application, now they need to communicate using event buses or message queues. This means that, when migrating one service to its own deployment, all other services that previously called it also need to have changes deployed.

Other challenges include:

  • Domain complexity: The lines between each service is much less clear than in a microservices architecture, and migration requires deep knowledge of the application’s domains.
  • Data consistency: Ensuring consistency across all the newly developed services can be complex, especially when dealing with distributed transactions across multiple systems.
  • Distributed transactions: In a microservices architecture, transactions are spread across multiple services, requiring more complex rollback processes and the implementation of entirely new patterns, such as the saga pattern.

It’s unlikely that any product would be migrated entirely from a monolith to microservices in a single release. Not only would doing so introduce far too many risks, but the development process would take a very long time, putting new feature development on hold until the migration was complete. Instead, development teams often migrate an application incrementally, extracting individual services until the entire monolith has been migrated.

Let’s start another thought experiment using the loan application demo from the previous blog post, before implementing Camunda.

Consider the very first step that an application takes: validating the loan application form. After a user submits the application form, it needs to be validated to ensure that all the required data has been provided. Form validation is something every development team has experience with. Creating a standalone service that validates the user input is a simple and logical first step in migrating away from a monolith.

Once that service is complete, is it enough to deploy it and move onto the next task? Unfortunately no.

That service needs to do more than just validate the form. It also needs to tell the main application the result of the validation. For this thought experiment, let’s assume the team is using an event bus. That service needs to write an event to the bus, and the main application needs to listen to that bus.

It isn’t as simple as making changes to a single service; parts of the main application need to change also, resulting in two or more deployments for each feature. Is there a better way?

Migrating with a process engine

Continuing the same thought experiment with the loan application demo, what would the migration process look like after Camunda has been implemented?

Camunda is now managing the state of the application, moving each loan through the process from start to finish. No longer does the validate application service need to send an event back to the main application; Camunda handles the transition to the next task.

Of course, integrating with event and message queues may be needed for other applications; for instance, you may need to integrate Kafka into your Camunda process!

Phrased another way, the validate application service now has no dependencies on other parts of the application and can function atomically. Camunda sends the data to the service where it’s validated, and the result is returned to Camunda. There is no need, in this example, to write to an event bus or to configure other services to listen for that event.

Looking at it this way, the BPMN diagram becomes something of a migration planning roadmap.

Individual services can be developed, tested, and deployed independently of the rest. The only change needed for the application to continue functioning is to change the REST endpoint in the BPMN model and redeploy it.

All new processes going forward will call the newly deployed service instead of the monolith, and processing will continue as usual regardless of which services have been extracted.

The power of process orchestration

This is the power of process orchestration with Camunda. Where your services are deployed doesn’t matter; what framework or language your services are written in doesn’t matter; whether they used to be part of a monolith doesn’t matter. Camunda allows you to seamlessly integrate all services into a single, well-defined process.

By starting with process orchestration, many of the challenges faced during a monolith to microservices migration can be easily overcome:

  • Business continuity: The process is already running end to end in Camunda, with your application handling the data and the logic. As each service is migrated away from the monolith, the process continues to function as originally designed.
  • Service decomposition: The BPMN diagram can act as a roadmap of sorts, helping teams identify individual services to migrate
  • Domain complexity: One key benefit of BPMN is the visual documentation it provides. By having your process already modeled and defined, much of the domain complexity is already well understood and documented.
  • Data consistency: Camunda continues to run the process as designed, and ensures that the process reaches the end. In this model, Camunda is responsible for managing the eventual consistency of the data in your process by moving the data through the individual tasks.
  • Distributed transactions: Camunda supports distributed transactions and rollbacks out of the box. For instance, teams can implement the saga pattern using compensation events. With compensation events, your individual services don’t need to track each transaction individually; instead, Camunda executes the rollbacks as defined in the BPMN model, easing the complexity of rollbacks.

If you’re new to Camunda and process orchestration, I recommend heading to Camunda Academy to learn more about BPMN, DMN, process orchestration, and using Camunda.

If you’re ready to experiment with your own processes and applications, sign up for a free account or log in at https://camunda.io/. I also recommend you join our community forum and join other developers as they explore Camunda and its ecosystem.

Happy coding!

Start the discussion at forum.camunda.io

Try All Features of Camunda

Related Content

Learn the individual strengths of genAI and ML and then learn how they can complement each other in your business.
Learn about the best programming languages for microservices, plus how to compose and orchestrate microservices for your project.
What Intelligent Process Automation (IPA)? Learn the definition and benefits of IPA, plus use cases, workflows, and technologies needed to get started.