Flowable call activities versus embedded subprocesses

Call activities and embedded subprocesses both split a large Flowable model into parts, but they differ in deployment coupling, variable scope, versioning and transaction behavior. This page explains how to choose and build each.

On this page

Call activities vs embedded subprocesses in Flowable: when each fits

Use an embedded subprocess when the steps belong to one business case, need the parent process's variables and lifecycle, and make no sense outside that parent. Use a call activity when the called process is reusable, owned by another team, or needs its own deployment and versioning. The difference is runtime behavior. An embedded subprocess runs inside the parent's process instance, so its tokens, variables and boundary events sit in the same instance. A call activity starts a separate process instance of a referenced process definition, and the parent waits for that instance to end unless the model says otherwise. This page covers the Flowable engine's modeling choices, not a general BPMN primer.

A model usually outgrows its diagram before it outgrows the engine. Typical signs are one diagram with dozens of tasks, the same approval branch copied into several processes, and reviewers who cannot trace where a variable is set. Before you split anything, check four things: whether the block changes on a different release cycle from the parent, whether another process reuses it, whether it needs its own instance ID and history for audit, and whether a different team owns it. If none of these apply, an embedded subprocess is usually easier to review. For a call activity, confirm how your Flowable version resolves the calledElement reference and which definition version is bound when the parent starts the child, because that binding decides which logic runs.

The main risks are variable mapping, version drift and completion timing. A call activity hides the called process's internal variables unless you map them explicitly in and out, so define each mapping and test that the parent sees the values it expects. Version drift occurs when a child definition changes while parents still expect the old contract, so agree on the interface and the deployment order before you release. Decide whether the parent waits synchronously or continues asynchronously, and confirm how async completion behaves in your engine version using the Flowable advanced documentation. Test these paths with long-running children and failed jobs before production.

How each construct runs inside the Flowable engine

An embedded subprocess is part of the parent process definition. When the token reaches it, the engine creates a scope inside the parent instance, so the subprocess shares the parent's process instance, its variables and its transaction context. Work inside it is committed along with the parent unless you add asynchronous boundaries. The subprocess is drawn and deployed as one unit with the parent, so the parent and the subprocess always change together.

  • Shared variables: Subprocess activities read and write the parent's variables by default, and local variables stay visible only inside the subprocess scope.
  • Single deployment: The subprocess has no separate definition, so a change to it creates a new version of the whole parent model.
  • Parent waits implicitly: The parent token stays inside the subprocess until its end event is reached, with no separate instance to track.
  • Shared transaction context: Failures inside the subprocess roll back to the last committed point of the parent unless async continuations split the work.
  • Limited reuse: Another model can only reuse it by copying the diagram, which leaves copies to drift apart.

Before relying on this construct, confirm with your engineers which variables the subprocess needs and where asynchronous boundaries will sit.

Configuration options for calling and nesting processes

This table compares the ways a Flowable model can run work outside its main flow, from an embedded subprocess to a call activity that targets a process by ID or within the same deployment. Read each row for the situation it fits and the cost it carries, then confirm attribute names against the Flowable BPMN documentation before you standardize on a pattern.

OptionWhen it fitsMain trade-off
Embedded subprocessSteps that belong to one business transaction and should share the parent's lifecycle, timers and variable scopeDiagram grows large and cannot be reused by other processes without copying the logic
Call activity by process IDA separately owned process that several parents reuse, deployed as its own definitionParent depends on the called definition existing at runtime, so deployment order and ownership must be managed
Call activity in the same deploymentParent and child are versioned and released together as one set of process filesChanges to the child ship with every parent release, which can slow independent change
Variable mapping in and outPassing only the inputs the child needs and returning only its results to the parentUnmapped variables are not visible to the child, so missing mappings surface as runtime errors or empty values
Async continuation on the call activityLong-running children or steps that should commit in their own transaction and retry on failureAdds job execution and latency, and the parent waits in a state that operations teams must monitor
Called process version selectionParent should follow a fixed or latest version of the child when a new definition is deployedLatest-version binding can change behavior of running parents without a deliberate release, so confirm the default in your Flowable version

How to structure a large model with call activities

This sequence turns a monolithic Flowable model into a parent process that calls reusable child processes with clear variable contracts and a known versioning behavior. Each step ends with a check you can run before the next one starts.

  1. Set process boundaries by business ownership

    Before drawing anything, list the stages of the end-to-end process and assign each one to the team that owns its decisions and outcomes. Stages owned by one team with a stable interface are candidates for a child process, while steps that only exist to serve the parent flow usually stay as an embedded subprocess. Write down, for each candidate, its inputs, its outputs and the people who approve changes to it. You are done when every candidate has a named owner and the parent process reads as a short sequence of business stages.

  2. Model and deploy the child process

    Model the child process as its own BPMN file with a single, documented start point and clearly defined end states. Give it a process definition key that the parent will reference, and keep its variables limited to the contract you agreed with the owning team. Deploy it to the same engine or to a target environment you control, then confirm the deployment appears in the repository service with the expected key and version. If the child cannot be found after deployment, stop here, because every later step depends on that lookup.

  3. Reference the child from the parent call activity

    In the parent model, add a call activity and point it at the child by process definition key, or by ID if your team pins specific versions. Choose whether the call uses the latest deployed version or a fixed version, and record that choice in the model documentation. Confirm the parent deploys without a validation error and that starting an instance creates a child instance when execution reaches the call activity. Check the runtime service for the parent and child instance IDs to confirm the link.

  4. Map variables in and out explicitly

    Define the input mappings that copy parent variables into the child, and the output mappings that copy child results back to the parent. Keep mappings narrow so the child cannot read or overwrite unrelated parent data, and avoid relying on implicit variable sharing. Use names that match the contract from the first step. You are done when a test run shows the expected input variables present in the child and the agreed output variables visible to the parent after the child completes.

  5. Decide and test the versioning behavior

    Decide how the parent should behave when the child changes: whether running parent instances keep the child version they started with, and whether new instances pick up the latest deployment. Test both situations by deploying a second child version and starting new parent instances, then checking which child version each instance uses. Involve the team that owns the child process, because a silent version change can alter business results. Record the rule in the model documentation so operations knows what a redeployment will affect.

  6. Handle asynchronous completion where the child is long-running

    If the child waits on people, timers or external messages, decide whether the call activity should wait synchronously or whether the child's completion should be handled asynchronously. Confirm with the engine documentation how async continuations and the async executor behave in your version before relying on them, and test that the parent resumes after the child finishes, including after a restart. Check that no parent instance remains waiting after its child has ended.

  7. Test the parent with the child deployed

    Run end-to-end tests of the parent with the real child deployed, not a stub, covering the happy path, each child end state and at least one failure path. Verify that output variables reach the parent, that gateways downstream of the call make the right choices, and that the history shows both parent and child activities in order. Repeat the test after any redeployment of the child. The sequence is complete when these tests pass in an environment that matches production deployment practice.

  8. Document the contract and ownership for operations

    Write a short contract for each child process listing its key, its input and output variables, its end states, its versioning rule and its owning team. Store it alongside the BPMN files so that changes to either side go through the same review. Hand the contract to operations and the owning teams, and confirm they can find a child instance from a parent instance during an incident. The step closes when every call activity in the model has a matching contract entry.

Passing variables in and out and versioning called processes

Variable mapping between a parent and a called process is the first design decision to settle, because it determines what the child can see and what the parent gets back. In a call activity, input mappings copy values from the parent execution into the child process instance when it starts, and output mappings copy selected values back when the child completes. Keep the mapping list explicit and short: map only the identifiers the child needs, give each one a name that states its meaning, and avoid mapping everything by default. Confirm the exact mapping element names and whether a mapping can be expressed as an expression against your Flowable release in the Flowable BPMN docs, since mapping syntax has changed between major versions and must match the version you deploy.

Large or unstructured variables deserve special care. Every mapped value is serialized into the database and copied at each call boundary, so a parent that passes a full case document, a list of thousands of records or an opaque JSON blob multiplies storage and slows every instance that carries it. Pass a reference such as an identifier, and let the called process load detail through a service task when it needs it. Also check how your team stores object values in variables and which serializer the engine uses in your deployment, because a class change between releases can make stored values unreadable on resume. Ask whether your variable policy is written down before the first model is built, not after a support ticket.

Versioning is the risk that surfaces after go-live. When a called process is redeployed as a new version while parent instances are still waiting on it, the question is which definition a new call resolves to and what happens to instances already running on the old definition. Decide whether the call activity should reference a specific process definition ID, which keeps behavior fixed but requires a deliberate migration, or resolve the latest version by key, which picks up changes automatically but can change behavior mid-flight. Treat that choice as something to confirm against the Flowable docs for your release, then tie it to the migration guidance in the Flowable features group, and test a parent instance started before the redeployment as part of your release checklist.

Security and operational risks in multi-process models

Once a parent process calls another process, data, authorization and failure handling cross a boundary that a single diagram does not show. The cards below cover the risks that most often surface only after go-live, and the checks to run before a call activity reaches production.

Sensitive data passed between processes

Call activities copy variables into the child process and copy results back out, so a field that was harmless in the parent can end up in the child's runtime data and history. Map only the variables each called process needs, and review which of them are stored in the database and visible through the history and REST APIs. Confirm how your Flowable version handles variable scope and history retention for mapped variables before you choose which data may cross the boundary.

Authorization left to the application

Starting a called process by its ID does not by itself check whether the user or service initiating the call may run it. The Flowable engine leaves most authorization decisions to your application, so a parent process that can reach any deployed definition can also start definitions it was never meant to use. Decide which process IDs a given caller may invoke, enforce that check in your service layer or REST gateway, and test it with a user who lacks the right.

Failed child jobs stalling the parent

A called process runs its own jobs, and an asynchronous step that fails there leaves the parent waiting at the call activity until the job is retried or moved to the deadletter state. Operators who watch only the parent instance can miss a stalled child. Check how failed jobs in child instances surface in your monitoring, set retry behavior deliberately for jobs that call external systems, and document who acts on a deadletter job.

Actuator exposure for child instances

In Spring Boot deployments, the Flowable actuator endpoint at /actuator/flowable reports on running processes, which can include child instances started from call activities. Exposing that endpoint without authentication or network restrictions gives anyone with access a view of process state and volume. Confirm which actuator endpoints your deployment exposes, restrict them to your monitoring network, and verify that the output you alert on includes child instances.

Version drift between parent and child

A call activity can reference a called process by ID, and a later deployment of that process may change the behavior the parent expects. Running parent instances and new calls can then hit different versions of the same child process. Record which called version each parent instance used, and plan a deployment order that keeps variable contracts stable for instances already in flight.

Questions teams ask before modeling large Flowable processes

How much effort does it take to restructure an existing model into call activities?

The effort depends mostly on how many subprocesses the model already has, how many variables cross their boundaries, and how many other models depend on them. Restructuring is usually a refactoring exercise: each embedded subprocess becomes a separate deployed process with its own input and output mappings, and the parent model calls it by key or ID. Teams should inventory every subprocess, list the variables it reads and writes, and identify which ones are reused elsewhere. Ask any partner for a written estimate that breaks the work into inventory, model split, mapping, test and rollout, because each step has different drivers.

Can our team restructure the models without outside help?

A team with working knowledge of BPMN 2.0 and the Flowable engine can usually do the restructuring in-house, especially for a small number of processes. Outside help tends to add value where the model is large, where variable contracts are unclear, or where the team lacks time to test every path. Whichever route you choose, agree on the decomposition rules first, such as which subprocesses stay embedded because they share transaction scope or timers with the parent. Ask a partner to state in writing which parts of the work it will perform and which parts your staff will own.

What does the work need from process owners and developers?

Process owners need to confirm the business boundaries of each reusable step, approve the variable contract between parent and child, and agree on acceptance tests that reflect real cases. Developers need to define input and output mappings, handle service tasks and delegates inside the called process, and keep the deployment pipeline consistent across both definitions. Plan a short working session where process owners sign off on the decomposition before developers change any diagram. Without that sign-off, teams often split models along technical lines and then have to split them again.

How do version changes affect running instances of a called process?

A running parent instance keeps the called process definition it started with unless the call is resolved again, so version handling needs an explicit decision. Calls by ID pin a specific definition, while calls by key can resolve to the latest deployed version when a new call starts. Confirm the exact resolution behavior for your Flowable version in the configuration and process documentation, and test a version change against instances that are already waiting. Plan a rule for when old instances finish on old definitions and when a migration of running instances is needed.

Does the Flowable version we choose change the work?

Yes. Flowable 8.0.0 was released on February 27, 2026, following 7.2.0 on August 21, 2025 and 7.1.0 on October 7, 2024. The 8.0.0 release notes describe an upgrade to Spring Framework 7 and Spring Boot 4 with no backward compatibility for Spring Boot 3, so a team on Spring Boot 3 will need a platform upgrade before or alongside the model work. Confirm the target version and its baseline before estimating restructuring effort, because the two changes compound.

What drives the cost of this work up or down?

Cost rises with the number of subprocesses to split, the number of variables crossing each boundary, the number of parallel versions in production, and the depth of testing needed for long-running paths such as timers and boundary events. Cost falls when the model is already modular, when the variable contracts are documented, and when the team reuses a test harness. Recurring costs include maintaining called-process contracts and retesting when a dependent process changes. Ask any quote to separate one-time refactoring from ongoing support, and to state what is included for a platform upgrade.

When should a subprocess stay embedded instead of becoming a call activity?

Keep a subprocess embedded when it needs to share the parent's transaction scope, its timers, boundary events, or its variables without a formal contract. Move it to a call activity when several models reuse the same logic, when it has its own lifecycle and ownership, or when it needs independent versioning. The Flowable advanced documentation explains how the async executor handles timers and asynchronous jobs across nodes, which matters when a long-running child waits on a timer. Document the rule you apply so reviewers can check each split the same way.

How DeployOpen scopes Flowable modeling work

DeployOpen plans and implements Flowable models inside your own infrastructure, whether that is your cloud accounts, your data centers or an air-gapped network. For a call activity versus embedded subprocess question, that means the work covers the process definitions themselves, the decision on how each subprocess boundary is drawn, the variable contracts that cross it, and the deployment pipeline that ships called and calling definitions together. Engagements are typically fixed-scope, so the models in scope, the number of process and subprocess definitions, the called processes that must be reused across applications, and the integrations each one touches are agreed in writing before build work starts.

Before you sign, ask for the written scope to name the specific deliverables: the decomposition diagram, the input and output variable map for every call activity, the chosen referencing method (same deployment or by process ID), the versioning rule for called processes, and the test cases that prove async completion behaves as designed. Also confirm which items are your responsibility, such as access to your Git repository, deployment environments and database instances, because delays on those inputs are the most common reason a fixed scope moves. Any timeline should come from that written scope, not from an estimate offered in a sales conversation. After go-live, ongoing support, Flowable version upgrades and continuous testing can be covered by a retainer. Ask whether a retainer would include review of new or changed called processes, since a version change to a shared subprocess affects every parent that calls it. The retainer terms, response expectations and what is excluded should be written down the same way as the original scope, so you can judge the recurring cost against the work your own team would otherwise absorb.

How DeployOpen delivers Flowable process architecture

DeployOpen plans, implements, documents and supports Flowable engines inside your own infrastructure, including the decision between embedded subprocesses and call activities. We agree the process boundaries, variable contracts and deployment approach in writing before build work starts, so the structure of your models is settled before the first large diagram is drawn.

How we scope

  • Map which process fragments stay embedded and which become reusable called processes, with the reason for each boundary
  • Define the variable contract for every call activity, listing inputs, outputs and types agreed with the process owners
  • Agree in writing how called processes are referenced, either from the same deployment or by process definition ID, and how versions are pinned
  • Confirm the async completion points and the transaction boundaries your operations team needs to monitor

How we build

  • Model parent and child processes in BPMN 2.0 with the Flowable Designer or your preferred modeling tool, keeping diagrams readable at review
  • Implement input and output mappings so called processes receive only the variables they need and return results in a defined shape
  • Write tests that start parent processes, complete called processes and check variable propagation, including the asynchronous completion path
  • Configure the deployment pipeline so called process definitions are deployed in a known order and tagged with version identifiers

How we hand over

  • Deliver a written architecture record covering process boundaries, variable contracts, versioning rules and the reasons behind them
  • Document how to add a new called process, retire an old version and check which parent processes depend on it
  • Walk your engineers through the test suite, the deployment order and the monitoring points for running instances
  • Provide runbooks for stuck call activities, failed child jobs and reruns of asynchronous completion steps

How we support

  • Review new models for process depth, variable sprawl and reuse before they reach production
  • Support upgrades of the Flowable engine and changes to shared called processes through a planned release process
  • Ongoing support, upgrades and continuous testing are available as a retainer, scoped in writing with your team
  • Quotes follow from the written scope, so ask for the effort drivers, the test coverage and the handover items to be listed separately

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.