Flowable compensation and transaction subprocesses

Flowable compensation and transaction subprocesses let a BPMN process undo completed steps across several systems when a later step fails or is cancelled. This page covers the design choices, setup and limits to confirm before you build.

On this page

When Flowable compensation and transaction subprocesses are the right tool

A compensation in Flowable is a handler that semantically undoes work a process step already completed, such as cancelling a reservation or refunding a charge, so a long-running business transaction can be unwound after a later step fails. A transaction subprocess is a BPMN subprocess that groups several steps into one business transaction, where a cancel event in the subprocess triggers compensation of the work already done inside it. Both come from the BPMN 2.0 model that the Flowable BPMN engine executes, and the exact element names and semantics should be checked against the Flowable BPMN documentation linked from this page before you model them. You need them when a business operation spans several systems that each commit independently, such as a payment provider, an inventory service and a shipping partner, and no single database transaction can cover all of them. In that situation, rolling back is not an option once a step has committed, so the process must know what each completed step is and how to reverse it.

A plain error path or a retry is usually enough when the failure happens before any external side effect is committed, or when the step is idempotent and can simply be attempted again. Retries handle transient faults such as a timeout, and an error boundary event routes a business failure to an alternative branch without undoing anything. Compensation adds design cost: every compensable activity needs a handler that is itself reliable, and handlers must cope with partial failure, duplicate calls and data that changed since the original step ran. Before you commit to this pattern, list each external step, decide whether it can be reversed by a real business action, and confirm with the owners of those systems what a reversal means in their terms. Steps that cannot be reversed are better handled by ordering them last or by a manual task, and the team should agree which outcome is acceptable when reversal fails.

Which compensation pattern fits which business transaction

A compensation boundary event attaches to an activity that has already completed. It does not fire when that activity itself fails. It fires when a compensation throwing event in the same scope requests compensation, and it points to the compensation handler that undoes the completed work. Use it when each completed step has one clear reversal.

  • Trigger: A compensation throwing event in the same scope activates it. The attached activity's own failure does not.
  • Attachment: It sits on the activity whose effects must be undone and references a compensation handler activity.
  • Fit: Single-step reversals, such as releasing a reservation placed by an earlier step once a later step fails.
  • Scope: Confirm in the Flowable BPMN docs which completed activities the engine compensates when the throw sits in a subprocess.
  • Ordering: Confirm how the engine orders multiple compensations before you depend on a specific reversal sequence.

Before building, list every completed step that has an external effect and confirm that each one has a boundary event and handler.

Configuration options and when each fits

This table compares the BPMN constructs used for compensation and transaction subprocesses in Flowable, with the trigger and trade-off of each. Read it as a decision aid: start with whether the work must be undone after it completed, then check whether a group of steps must succeed or roll back together.

OptionTriggerTrade-off
Compensation handler associationAttached to an activity that has completed work to undo laterKeeps undo logic next to the step, but the handler only runs when a compensation event reaches it
Compensation boundary eventAttached to an activity and fired by a throwing compensation event in the same scopeTargets the attached activity only, so the model must confirm every completed step has a handler
Intermediate throwing compensation eventReached in the flow when the process must undo completed workGives explicit control over when undo starts, but it does not roll back work that has not completed
Transaction subprocessEntered as a unit whose outcome is success, cancel or failureGroups related steps under one outcome, while each inner step still commits independently in the engine
Cancel boundary eventFired by a cancel end event inside a transaction subprocessTriggers compensation for completed inner work, so handlers must be idempotent and reachable
Hold eventUsed where the process must wait before undoing or confirming workGives a pause point for external confirmation, but waiting steps add runtime state and monitoring needs

How to set up compensation in a Flowable process

This sequence takes a long-running business transaction from an inventory of completed work to a tested Flowable process that can undo finished steps. Each step produces a reviewable artifact: a reversal inventory, a model, delegates, a deployed definition and test evidence.

  1. Inventory reversible steps and compensating actions

    Business analysts and domain owners list every step that changes state in an external system, such as a reservation, a payment capture or a record creation, and write the compensating action beside each one. They also list steps that cannot be reversed, such as a sent notice or a released shipment, and document how each is handled instead, for example through a later correction or a manual task. Check: the process owner signs off on the inventory, and every forward step has either a named compensating action or a documented reason it has none.

  2. Model activities with compensation handlers

    Solution architects attach a compensation handler to each reversible activity in the BPMN model. The handler is an activity linked to its source through a compensation association, and it stays outside the normal sequence flow so it runs only when compensation is triggered. Where the undo must happen on a specific activity, they place a compensation boundary event on it. Check: the model validates in your BPMN tooling, and a trace of the normal flow shows that no handler is reachable through ordinary transitions.

  3. Add compensation throw and cancel events

    Architects add a compensation throwing event at the point where the business transaction must be undone, such as after a failed later step or a customer cancellation. For a transaction subprocess, they add a cancel boundary event that fires when the transaction is cancelled, followed by a cancel end event that triggers compensation for the work completed inside it. They also decide whether compensation applies to the whole process or only to a subprocess. Check: walk each cancel and throw path on the diagram and confirm that it reaches the intended compensation handlers and no others.

  4. Implement reversal logic in Java delegates

    Developers write a JavaDelegate or a service task for each compensation handler that calls the external system's reversal API. The delegate reads the correlation identifiers recorded during forward execution, such as a reservation or transaction reference, from process variables. Reversals must be idempotent, so a retried call does not reverse the same work twice, and the delegate must handle the case where the external system has already reversed it. Check: unit tests run each delegate against a stub of the external system, and they assert that a reversal is sent and that a repeated call leaves the state unchanged.

  5. Deploy the definition and confirm it loads

    The delivery pipeline deploys the BPMN file and its delegates to a test engine, using the same packaging that production will use. Platform engineers then confirm that the deployment registers with the expected definition version and that the engine accepts the model without parse errors. They start one sample instance to confirm that the process begins and that no startup errors appear in the logs. Check: the deployment appears in the repository query for the test engine, and the sample instance starts and reaches its first wait state.

  6. Test forward and compensation paths

    QA engineers run the happy path to completion, then run failure scenarios that stop the process at chosen activities and trigger cancel and throw events. For each scenario, they assert on the recorded calls to the external system and the final state of the process instance. The test set should confirm that handlers run in reverse completion order and that no handler runs for an activity that never completed. Check: the test report shows the reversal order matches the completion order in every compensation scenario, and the instance ends in the expected state each time.

Designing compensating actions that are safe to run twice

Compensation is a business action, not a rollback. A compensation handler runs after the forward work has already been committed in other systems, so it can fail, arrive late, or run after only part of the original step took effect. Design every handler on the assumption that it will be retried and may execute more than once. Give each external call an idempotency key derived from the process instance ID and the activity ID, so the downstream system can recognize a repeat and ignore it. Ask each system owner whether their API accepts a caller-supplied key and how long it remembers one. If the answer is no, the handler needs a lookup step that checks the target state before it acts.

The handler can only undo what it knows was done. Record the result of each forward step in process variables at the point the step completes, including the external reference ID, the amount or quantity changed, and a status value. Use a dedicated variable naming convention so that the compensation logic reads a clear ledger instead of guessing from the model. Keep these values small and serializable, because they travel with the process instance and into history. Confirm with your team how the variable storage choices affect the history you will keep for audit.

Transaction timing matters as much as handler logic. Flowable's advanced documentation describes how the async executor runs asynchronous jobs from a thread pool and coordinates nodes through lock owners and lock expiration times in the database, so a job whose lock expires can be picked up by another node. A compensation handler that calls an external system and then fails before the database commit can therefore run again. Review the Flowable advanced documentation to confirm how the async executor and job retries apply to your version, and mark the handler steps that make external calls as candidates for asynchronous continuations, so each side effect has a clear commit boundary.

Security and operational risks of compensating across systems

Compensation runs after work has already happened in other systems, so its credentials, audit trail and failure handling carry the same weight as the forward path. The cards below cover the risks that tend to surface once a compensating action has to run in production, and the checks to make before go-live.

Credentials used by compensation calls

A compensation handler often calls an external API with a service account that can reverse a payment, release a reservation or cancel an order. That account usually has write rights the process itself never needs to hold. Check which identity the handler runs under, whether it is scoped to the reversal operations only, and how its secret is stored and rotated. Confirm that Flowable's delegate code reads credentials from your secrets store rather than from process variables or model files.

Auditability of compensating actions in history

A compensating action is a business event, and auditors will ask who triggered it, why, and what it reversed. Flowable's history records the compensation activities that ran, but it does not know whether the external reversal succeeded. Decide what your handlers write to an audit log in the target system, which correlation key links it to the process instance, and how long history is retained for those records.

Duplicate or missing compensation after restarts

If a node stops after an external call succeeds but before the engine records the step as complete, the job runs again on restart. A compensation that is not idempotent can reverse the same payment twice, while a job that never retries can leave a failed reversal silent. Make each external call idempotent with a stable key derived from the process instance and activity, and test restarts at each commit point of the transaction subprocess.

Exposure of sensitive process variables

Compensation handlers read the variables captured when the forward work ran, and those variables often hold account numbers, personal data or approval details. Process variables are stored in the engine database and can be visible through the REST API and history. Limit what is stored as a variable to identifiers needed for the reversal, keep sensitive values in the target system, and review which roles can query historic variables.

Multi-node execution through the async executor

In a clustered deployment, the async executor on any node can pick up a compensation job. Flowable coordinates nodes with lock owners and lock expiration times in the database, so expired locks are recovered by another node. That protects against lost work but also means a slow external call can outlive its lock and run on a second node. Confirm the lock duration and the job retry settings against the longest reversal call you expect, and verify behavior with your load balancer and node count.

Monitoring stuck or failed jobs

A compensation that fails repeatedly moves to a deadletter state and can sit unnoticed while the business case stays half reversed. The Spring Boot starter exposes an actuator endpoint at /actuator/flowable for monitoring running processes, which is the place to start. Define alerts for jobs that exhaust retries and for process instances that remain in a compensating state beyond a time limit you set, and assign an owner who can resolve them.

Questions teams ask before building compensation in Flowable

What drives the cost of building compensation in Flowable?

The biggest cost driver is how many systems a business transaction touches and how hard each one is to reverse. Each completed step that needs an undo action requires a compensation handler, and each handler must be designed, coded against the target system's API, and tested. Other drivers include whether the target systems offer reversal endpoints at all, how much state must be kept to undo work correctly, and how many failure paths the business has agreed to handle. Fixed-scope work is quoted from a written scope, so ask for the list of steps, systems and compensation actions to be itemized. Expect the quote to separate design, build, testing and handover, and to show which items recur, such as support retainers after go-live.

How long does designing and building compensation usually take?

Duration depends mainly on the number of systems, the number of steps that need an undo action, and the state of the target APIs. Each additional system adds integration design, credential handling, error mapping and test environments to the plan. No duration figure has been published here, so ask for a timeline in the written scope that lists the process steps, the systems behind each one and the test environments available to the project. A good scope also states which compensation paths are in and out of the first release.

What does the work need from our team?

Expect to supply business owners who can define what a correct undo looks like for each step, API owners for every connected system, and an environment where compensation can be exercised without touching production money, records or messages. You will also need a decision on who approves manual intervention when an undo fails. Your identity and secrets team should provide service credentials for each target system, and your platform team should confirm where the Flowable engine and its database will run. Agree these owners in the written scope so that delays do not come from missing access.

Can our internal team build compensation without outside help?

Yes, if your engineers already work with Flowable, understand BPMN transaction subprocesses and have experience with the target systems' APIs. The harder part is usually the business design: deciding which work can be undone, which cannot, and what the customer sees while a reversal is pending. Many teams build the first version internally and bring in a partner for design review, hardening or the audit trail. Ask yourself whether you have engineers who can test failure paths systematically, because compensation bugs often appear only when a later step fails after several earlier steps have already completed.

When is a retry or an error boundary enough instead of compensation?

Use a retry or a BPMN error boundary when the failed step can be repeated safely, or when the failure should be handled locally without undoing earlier work. Compensation is needed when earlier steps have already changed state in other systems and the whole business transaction must be reversed. Retries are configured on asynchronous jobs, so a transient network failure in one call may not require any undo. A rule of thumb is to ask whether the completed steps must be reversed for the business to be correct. If they do not, a simpler error path is usually easier to operate and test.

How do we test compensation paths before go-live?

Test each compensation handler on its own, then test the full transaction with a failure injected at every step, so each combination of completed work and failed step is exercised. Verify that the reversal calls reach the target systems, that they run once and that they behave correctly when the target is slow or returns an error. Check the audit trail for each path, since the history is the evidence that the reversal happened. Use a sandbox or private test environment for every connected system. Ask your partner or internal team to show a test matrix that lists each path and its expected outcome before sign-off.

What recurs after go-live?

After go-live, costs recur for monitoring failed compensations, updating handlers when target system APIs change, upgrading Flowable, and keeping test environments current. Flowable's upgrade work follows the major release line, so plan for the Java, Spring and Jakarta requirements of the version you run. Ask for a support scope that names who responds to a failed reversal, how quickly, and which runbooks exist. Ongoing support and upgrades can be arranged as retainers after the fixed-scope build.

How DeployOpen scopes compensation work on your infrastructure

DeployOpen starts compensation work by mapping which business transactions span several systems and which of their steps can be undone after they have committed. For each transaction we record the forward steps, the systems that own them, and the point at which a step is irreversible, such as a payment settled to an external party or a notice already sent to a customer. That map decides where a compensation handler is needed at all, and where a transaction subprocess with cancel events is the better structure. The output is a written inventory that your system owners review before any model is drawn.

Compensating actions are defined with the people who own each system, not inferred from the BPMN. For every forward step, the owner confirms the reverse operation, whether it is idempotent, how long it remains valid, and what the business accepts when the reverse is partial. Compensation handlers in Flowable are ordinary service logic running against your APIs, so the reverse call, its retry behavior and its failure path belong in the scope document with named owners. Confirm with each owner whether their API supports the reverse call at all, since many do not and the handler then becomes a manual task with a ticket.

Models and handlers are built and tested inside your cloud accounts, data centers or air-gapped network, against your staging copies of the systems they call. Testing covers the forward path, a cancel at every transaction boundary, a failure inside each compensation handler, and a redelivery of the same compensation to confirm it does not double-reverse. DeployOpen then writes runbooks for operators: how to read a partially compensated instance, when to retry a failed handler, and who approves a manual reversal. Engagements are fixed-scope, with the mapping, handler list, test cases, runbooks and handover listed as written deliverables with agreed timelines before work starts. Ongoing support, handler changes after system upgrades and periodic re-testing are available as a retainer.

How DeployOpen delivers Flowable process work

DeployOpen plans, implements, customizes, tests, documents and supports self-hosted open-source platforms inside your own infrastructure, including the Flowable engines. For compensation and transaction subprocesses, the work starts with the business transactions that need undo logic and ends with a model, handlers and runbooks your team can operate.

How we scope

  • Map each business transaction that spans several systems and decide which completed steps need a compensation handler.
  • Agree in writing which compensation, cancel and failure paths are in scope, along with the systems each handler must call.
  • Engagements are fixed-scope, with deliverables and timelines agreed before work starts; ongoing support is available as a retainer.

How we build

  • Model transaction subprocesses with compensation boundary and throwing events, and cancel events, in the Flowable BPMN engine.
  • Write compensation handlers as Java delegates that are idempotent and safe to retry against the external systems they call.
  • Test success, cancel and partial-failure paths, including compensation of work that was already committed in other systems.

How we hand over

  • Document each transaction boundary, compensation handler, and the state a process leaves behind when compensation fails.
  • Deliver the process models, delegate source and deployment steps into your repository and your pipeline.
  • Walk your engineers and operators through failed compensation jobs and the manual steps your team owns.

How we support

  • Review compensation behavior after upgrades of the Flowable engine and the Java and Spring baseline it runs on.
  • Provide retainer support for changes to handlers when the external systems they call change their APIs.
  • Run repeat testing of cancel and compensation paths as part of continuous security and quality checks, where your retainer includes it.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.