Flowable asynchronous continuations and transaction boundaries

Flowable asynchronous continuations decide where a process commits, which steps run in the caller's transaction and which run later as jobs. This page explains the trade-offs so teams can set them per step before the process goes live.

On this page

Flowable asynchronous continuations: where your process commits

Where a Flowable process commits its work is a design decision you make before the build starts, not a tuning detail you fix later. When a BPMN process has to answer a user quickly while a downstream system is slow or unavailable, each step you mark for asynchronous continuation becomes a transaction boundary. Work before the boundary commits together, and the engine then hands the next step to a job. Your team needs to decide which steps must commit with the user's request, which can wait, and what should happen when the waiting step fails.

The Flowable advanced documentation describes the async executor as the component that runs timers and asynchronous jobs from a thread pool. In a clustered deployment, it coordinates nodes through lock owners and lock expiration times stored in the database, so a job locked by a node that stops is recovered and picked up by another node once its lock expires. That database-backed design means async jobs survive restarts, but it also means job throughput, lock timing and database load are shared concerns. Confirm the executor settings, thread pool sizing and lock behavior for your Flowable version in the Flowable advanced documentation before you assume any default. Retry behavior and failed job handling are covered in the sibling topics on error handling and operations.

Plan continuations early for three reasons: they change what the user sees, they change how failures are recovered, and they change how the model is tested. A synchronous step returns its result within the same request, while an asynchronous step returns control and completes later, so screens, status messages and reporting must allow for work still in progress. Ask your process owners which steps the user waits on, and ask your integration owners how long each downstream call may take and how it reports failure. Record those answers in the process design, then confirm the Flowable behavior with a proof of concept in your own environment, because the exact effect depends on your database, Flowable version and deployment model.

How Flowable asynchronous continuations split a process into transactions

Each asynchronous continuation ends one database transaction and starts another, so the engine commits everything up to that point before the next step runs. When a step fails, the rollback only undoes the work done since the last commit point, not the whole process instance. That is the main lever you have over failure scope: place a flowable:async continuation before a step that talks to an external system, and a failure in that step cannot roll back the earlier steps that already committed. Map out where your service tasks fall relative to these commit points before you decide where the process is allowed to be partially complete.

Continuations are not run inline. The async executor picks up asynchronous jobs and timers and executes them from a thread pool, and it coordinates across nodes through the database. Each job carries a lock owner and a lock expiration time, both stored in the database. A node that claims a job sets its lock owner and an expiry, and if that node dies before finishing, the lock eventually expires and another node can pick the job up. Ask your team how the async executor is configured in your deployment, including the thread pool size and lock timing, and confirm the lock expiry values against the Flowable advanced documentation for the version you run. Those values determine how long a job can sit stranded after a node failure.

The engine only controls what happens inside its database transaction. A payment call, an email, a message published to a broker or a write to another system is not rolled back when a Flowable transaction fails, and a job that retries after a lock expires may run the external call again. Plan for this explicitly: make external calls idempotent with a stable business key, or place them where a retry is acceptable, and record which steps have already produced outside effects. Confirm with your application owners which external actions can be repeated safely before you set retry behavior, because the engine will not detect a duplicate side effect on your behalf.

Which continuation setting fits each step

This table compares the five continuation choices Flowable offers for a step: synchronous, asynchronous before, asynchronous after, exclusive job handling, and timer-driven continuation. Read each row for what the choice commits, how it affects what users see, and how retries and transaction size change. Confirm exact attribute names and placement in the Flowable docs for your version before you model.

OptionWhat it commitsWhen it fits
Synchronous stepThe step and the following logic run in the same transaction as the request that reached themFast, side-effect-free steps where the user needs an immediate result and a failure should roll back the whole request
Asynchronous before a stepA transaction commits before the step runs, and the step runs later as a job on the async executorSteps that call external systems or heavy logic, where the user should not wait and a retry should not repeat earlier work
Asynchronous after a stepThe step completes and commits, then the next node is queued as a separate jobSplitting a long path into smaller transactions, or placing a commit point after a step whose output must be durable before continuing
Exclusive job handlingJobs for the same process instance run one at a time, so parallel branches do not write to the same instance concurrentlyParallel gateways or multi-instance paths where several async jobs touch the same variables or execution tree
Timer-driven continuationThe continuation waits for a due time, then the executor fires it in a new transactionReminders, SLA deadlines and waits where the delay is intended and user-facing latency is acceptable
Retry behaviorA failed async job is retried according to configured retry settings, and the work before the commit point is not repeatedCalls to unreliable services; confirm retry configuration and deadletter behavior for your version
Transaction sizeEach commit point shortens the transaction but adds job rows and executor workLarge models with many steps; add commit points deliberately rather than after every task

Synchronous or asynchronous by situation

When a person submits a form and waits for the next screen, the default goal is a fast, predictable response. Keep the steps between the user's submit and the next user task synchronous where they are short and deterministic, such as validating input, setting variables and evaluating a gateway. The engine then commits the whole path in one transaction, so a failure rolls back to the state the user saw before submitting. Mark an async boundary only where a step is slow enough to affect the response or where a separate transaction is needed.

  • Commit point: the transaction ends at the next user task, so the user sees one consistent state.
  • Effect on the wait: every synchronous delegate adds to the response time, and a slow call blocks the screen.
  • Effect on retries: a failure rolls back and returns an error to the user, so no hidden retry runs.
  • Watch for: a flowable:async flag added to a step the user is waiting on, which moves work to the job executor and returns the screen before the step finishes.
  • Test before go-live: response time under realistic load, error messages on rollback, and that the user never sees a half-completed step.

Confirm the exact behavior of your engine version in the Flowable documentation before fixing the commit points in your model.

Failure modes that follow from where a process commits

Every asynchronous continuation is a commit point, and each one decides what survives a failure and what runs again. The cards below cover the failure modes that follow from those choices in Flowable, along with the design responses that keep retries, locks and user feedback under control.

Duplicated side effects on retry

A service task that calls an external system and then fails before its transaction commits will be retried by the job executor, so the external call can run twice. This happens when the side effect and the engine state do not share one transaction. Check every delegate that sends money, email, tickets or messages, and confirm which call sits before the next asynchronous boundary. Put the external call behind its own asynchronous step or make the target system aware of the retry.

Retries piling up on a failing dependency

When a downstream service is unavailable, every job that reaches it fails and schedules another attempt, so the async executor keeps hitting the same dependency. The load can outlast the outage and slow recovery. Review the retry count and wait interval for each job type, and decide which failures should stop retrying and move to a deadletter state for a person to review. Cap retries per dependency rather than per job alone.

Lock expiry delaying work on busy clusters

The async executor coordinates nodes through lock owners and lock expiration times stored in the database. If a node holds a job past its lock window, another node can pick it up, and recovery waits for the lock to expire. On a loaded cluster, long delegates and slow commits make this more likely. Measure how long your longest asynchronous steps take, keep delegates short, and size lock settings with your database and node count in view.

Ordering changes from exclusive jobs

Exclusive jobs prevent two jobs for the same process instance from running at once, which protects data but serializes work that a modeler may have assumed was parallel. Parallel branches that each carry an asynchronous step can run in a different order than the diagram suggests. Trace the expected order of each branch, and confirm with a test that results do not depend on which branch finishes first.

Unclear user feedback after a commit

A user who submits a form may see a success page while the rest of the process is still waiting in a queue, or may see nothing change at all when a job fails. Where a step is asynchronous, the screen can show a state the process has not reached yet. Decide which steps are synchronous for the user, show a pending state for the asynchronous ones, and define what the user sees if the job later fails.

Missing idempotency keys

Retries and manual reruns are only safe when the receiving system can tell a repeated request from a new one. Without an idempotency key passed from the process to the external system, a retried job creates a second record that looks valid. Assign a stable key from a process variable or business identifier before the external call, store it with the result, and check for it on the receiving side.

Setting up the async executor and checking continuations

This sequence turns the async decisions for a Flowable process into a tested configuration, confirming the database, enabling the async executor on every node, and proving that retries and lock recovery behave as designed before production.

  1. Confirm database type and timestamp precision

    The platform engineer checks which database the Flowable engine will use and compares it with the supported types listed in the configuration docs. For MySQL, confirm the server version is at or above 5.6.4, because older versions lack millisecond precision, which affects timer and lock expiration timing that the async executor relies on. Record the database type, version and precision in the design document. Done means the team can point to the configuration page entry and the server version output that match.

  2. Enable the async executor on each node

    The platform engineer sets the async executor configuration on every Flowable node, using the same database and the same engine configuration so that all nodes share one job table. Each node should start with a distinct, identifiable configuration, and the team should confirm that the executor is active in startup logs. Done means every node reports the async executor as started and all nodes point at the same schema.

  3. Mark the async steps in the model

    The process modeler reviews the BPMN diagram and sets flowable:async on the chosen service tasks, script tasks or events that must commit before continuing, and removes it from steps that must stay in the same transaction. Each marked step should have a written reason tied to a boundary, such as an external call or a user-facing response. Done means the model review record lists every marked element with its reason, and a peer has signed off the list.

  4. Deploy the model to a two-node test environment

    The developer deploys the process definition to a test environment with two Flowable nodes sharing one database, then starts a test instance and follows it through the marked steps. The team checks that a job is created in the job table for each async step and that the instance advances once the executor picks it up. Done means the test log shows each async job created, executed and completed, with the node that executed it recorded.

  5. Trigger a failing delegate and observe retries

    The developer adds a temporary failure to one Java delegate, such as a thrown exception on a designated input, and starts an instance that reaches it. The team watches the job table and logs as the executor retries the job according to the configured retry settings, then confirms the job lands in the expected state after retries are exhausted. Done means the team has recorded the retry count, the interval behavior and the final job state, and has removed the temporary failure.

  6. Simulate a stopped node and confirm lock recovery

    With an instance waiting on an async job, the operator stops the node that holds the job lock before the lock expires, then waits for the lock expiration time stored in the database to pass. The team then checks that the second node picks up the job and completes it, which confirms that expired locks are recovered across nodes. Done means the job history shows the lock owner change from the stopped node to the surviving node, and the instance completes.

  7. Record the continuation map for operations

    The engineer documents the final configuration, the list of async steps with their transaction boundaries, the retry settings and the observed lock recovery behavior, and hands it to operations. The document should state which steps will show a delay to users and which run in the background. Done means the operations team can reproduce the checks and the map is stored with the process model in version control.

Questions buyers ask about async continuations

How much effort does it take to map async continuations across a process model?

The effort grows with the number of service tasks, external calls, gateways and boundary events that must be classified as synchronous or asynchronous, and with how many of those steps touch shared data. A review of the model usually comes first: each step is marked by what it writes, what it calls outside the database, and whether a failure there should roll back the steps before it. Flowable's flowable:async attribute is set per activity, so the mapping is a design exercise before it is a configuration exercise. Ask for the review to be included in the written scope, with the model, the list of external systems and the expected failure behavior as inputs.

What drives the cost of an async continuation project up or down?

Four factors move the cost most:

  • The number of steps that need a transaction boundary decision and the number of external dependencies each one calls.
  • The idempotency work: every step that may run twice after a retry needs a safe way to repeat or skip its side effects.
  • Test coverage for retries, failed jobs and concurrent execution across nodes.
  • Whether the processes already run in production, which adds migration of running instances to the review.

Fixed-scope quotes are built from these inputs, so ask the provider to list each one as a separate line item.

How long does it take to scope this work?

Scoping depends on how many process definitions are in play and how well the current behavior is documented. A small set of models with known external calls can be reviewed quickly, while a large estate with undocumented side effects needs time to trace what each step writes. Flowable does not publish a fixed timeline for this work, so the duration should come from the written scope rather than from a general figure. Ask for the scoping phase to produce a list of boundary decisions, open questions and the test cases that will prove each decision holds.

What does our team need to provide before an engagement starts?

The team should provide the BPMN models under version control, the Flowable engine version and deployment setup, the database type, and a list of external systems each process calls. It should also provide the current failure handling, the expected behavior when a step fails halfway, and any service-level expectations for how long a user waits on a step. Access to a non-production environment that mirrors the database and job executor configuration is needed for testing. Confirm the exact database and engine versions with your own environment before the scope is signed.

Can our internal team handle async continuations on its own?

Yes, if the team already runs Flowable and has engineers who understand transactions, the async executor and idempotent service design. The work is mostly careful modeling and testing rather than new code. Teams new to the async executor usually benefit from a review of their first few models, because the mistakes are subtle: a step that looks safe can duplicate a payment when a job retries. An internal team can own the work from start to finish if it has time for a full test pass and a written record of each transaction decision.

When does outside help make sense for this work?

Outside help is most useful when the process estate is large, when processes move money or regulated records, or when the team has no one who has run the Flowable async executor under load. It also helps when the work must be finished alongside a version upgrade or a migration, because transaction behavior changes are easy to miss in that setting. DeployOpen plans, implements, tests and documents Flowable work inside the client's own infrastructure, under a fixed-scope written agreement, and can support the team after go-live through a retainer if needed.

Operational and security considerations for the job queue

Async continuations move work into the job queue, so the queue inherits the access, data and recovery questions of the process itself. The four cards below cover who can act on jobs, what data those jobs hold, how running and failed jobs are watched, and how the database protects work in flight.

Who can view and act on jobs

Job management is a privileged operation: anyone who can reach the management API or the engine's management services can inspect, retry or delete jobs. Confirm which roles your deployment grants access to job management, whether your REST application or embedded services expose these operations, and how your application layer enforces authorization, since the engine does not decide which user may act on which instance. Review this before enabling any management endpoint in production.

Job and variable data at rest

Jobs are rows in database tables, and each job references its process instance and execution. Process variables attached to those executions are stored in the same database, so a job can carry business data even when the job itself looks technical. Ask which tables hold job payloads and variables in your deployment, who can query them directly, and whether your logging configuration writes variable values or exception messages to application logs that run through a broader set of systems.

Monitoring running and failed jobs

Operators need to see jobs waiting in the queue, jobs that have failed and jobs that have exhausted their retries. The Spring Boot starters expose an actuator endpoint at /actuator/flowable for monitoring running processes, which is useful when Spring Boot is your runtime. Confirm which actuator endpoints are exposed on your network, whether that endpoint reveals job or variable details, and how alerts on failed job counts reach the people who can act on them.

Database access and backups

Async work is only as durable as the database that holds it. A restore from a backup taken at a different moment than the process state can leave jobs pointing at executions that no longer match, or lose jobs that were already acknowledged to a user. Confirm your backup schedule and whether application data and engine tables are captured in the same consistent snapshot, who holds database credentials, and how you will test a restore of in-flight instances before a production incident depends on it.

How DeployOpen scopes and delivers async continuation design

DeployOpen treats async continuation design as part of the process model, not a tuning step after go-live. We scope where Flowable should commit, build and test those boundaries in your infrastructure, and hand over the decisions and runbooks your team needs to operate them.

How we scope

  • Inventory which service tasks call external systems and which must complete in the same transaction as the user action.
  • Agree in writing which boundaries, retry behavior and user-facing waits are in scope before work starts.
  • Document the expected job volume, lock settings and database platform so the design matches your environment.

How we build

  • Place flowable:async markers at the chosen commit points and confirm the resulting transaction and job sequence in test runs.
  • Configure exclusive jobs, retry counts and failed job handling for each asynchronous step, with the settings recorded in code.
  • Test duplicate-execution, rollback and node-restart scenarios against a multi-node setup before the design is accepted.

How we hand over

  • Deliver a transaction map showing each commit point, its job type and what the user sees while it runs.
  • Provide a written record of the decisions, trade-offs and any agreed exceptions to the default async behavior.
  • Walk your engineers and operations staff through the job queue, failed job handling and recovery steps.

How we support

  • Engagements are fixed-scope, and ongoing support, upgrades and continuous testing are available as a retainer.
  • Review new or changed process models against the agreed transaction map before they reach production.
  • Revisit async settings when Flowable versions change or when job volume and integration behavior shift.

Sources and further reading

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.