# CompileFlow: three surfaces bolted onto one in-memory process engine

> CompileFlow is Alibaba's embeddable Java process engine for TBBPM and a documented subset of BPMN 2.0, where the base ProcessEngine keeps state in memory and persistence, versioned rollout and visual editing each arrive through a separate module. The most important line in its README is also the most easily missed: adding Deploy or Workbench does not make execute calls durable.

**alibaba/compileflow** — 🎨 core business process engine of Alibaba Halo platform, best process engine for trade scenes. | 一个高性能流程编排引擎

- Repository: https://github.com/alibaba/compileflow
- Stars: 1,988 · Forks: 281
- Language: Java
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/alibaba-compileflow

## Stateless execution is the default, and persistence is opt-in

CompileFlow's core design decision is stated in its own summary: the process engine focuses on in-memory, stateless execution. That word stateless refers to the engine holding no per-process session state across calls, not to the flows themselves being trivially simple. Everything a flow needs must travel in with the request.

Persistence is a separate product surface. CompileFlow Durable persists long-running process state so that execution can resume after waits, after timers, after an external operation, or after an application restart. Deploy adds versioned rollout. Workbench adds browser modeling and execution inspection. The README states that these surfaces are independent and that adding Deploy, Durable or Workbench does not turn ProcessEngine.execute calls persistent. That sentence is the one to read twice, because the module names read as if they compose, and the natural assumption is that installing the platform makes the whole thing restart-safe. It does not.

The choice table makes the mapping explicit. For in-process, low-latency execution you use ProcessEngine with either compileflow-tbbpm or compileflow-bpmn. Immutable versions, aliases and canary routing come from CompileFlow Deploy. Persisted waits, timers, external operations and restart recovery come from CompileFlow Durable. Browser modeling, release management and execution inspection come from CompileFlow Workbench.

The engine is described as used by core systems across Alibaba business platforms, including Taobao, Alibaba Cloud and the international businesses, and the repository description calls it the core business process engine of the Alibaba Halo platform, positioned for trade scenarios.

## Four types, one long-lived engine

The core API is small enough to hold in your head, which is unusual for a process engine. ProcessEngine is the thread-safe entry point for execution. ProcessRef is a reference to a published version or an alias, which is the object the Deploy surface introduces. ProcessDefinition is a definition supplied inline or from the classpath. ProcessResult<T> is the typed result or failure carrying stable error information.

There is a lifecycle rule attached to those types, and it is phrased as a prohibition. Keep one long-lived ProcessEngine for each distinct configuration. A single engine discovers every installed frontend, so a TBBPM module and a BPMN module installed together are both visible to the same engine instance, and each definition carries its own model type rather than requiring a second engine. Close the engine with the application lifecycle. Do not create an engine per request. In a Spring Boot service that means one injected bean, which is what the quick start shows.

The declared variables, preflight validation, typed results and stable errors listed under Java and Spring Boot integration are what distinguish this from a bare interpreter. Because ProcessResult is typed and carries stable error information, callers can branch on failure without string matching, which matters more in Java than in most languages since there is no union return type.

## Building from source, because the documented coordinate is a snapshot

CompileFlow supports JDK 17, 21 and 25, and generated bytecode targets Java 17. The repository ships a Maven wrapper, so no separate Maven install is implied; the commands use ./mvnw.

The quick start builds and installs the required modules from source rather than pulling a published artifact, and the reason is visible in the dependency block it is paired with.

```bash
./mvnw install -pl compileflow-spring-boot-starter-tbbpm -am -DskipTests
```

The -am flag builds the dependencies of the named module as well, which is what makes a clean checkout work without a prior full build. Tests are skipped in this particular invocation because the goal is to get the artifact into your local repository, not to validate it.

The starter you then depend on is the TBBPM one:

```xml
<dependency>
    <groupId>com.alibaba.compileflow</groupId>
    <artifactId>compileflow-spring-boot-starter-tbbpm</artifactId>
    <version>2.0.0-SNAPSHOT</version>
</dependency>
```

That version string is worth noticing. The newest GitHub release listed for the repository is v1.2.0, dated 2022-07-15, preceded by v1.1.0 from 2021-09-01 and a v1.1.0-Beta2. A 2.0.0-SNAPSHOT coordinate does not correspond to any of those tags, so anyone pinning a version for production has to decide for themselves whether to consume a snapshot they build themselves or to resolve an older released line. The README does not explain the relationship between the two, and it does not document a migration path from 1.x.

If you want BPMN rather than TBBPM, the sibling artifact is compileflow-spring-boot-starter-bpmn, which the choice table names as the other frontend for ProcessEngine.

## Injecting the engine and naming a definition explicitly

The quick start service takes the engine through constructor injection and executes a definition it names at the call site rather than relying on a lookup by name. The definition is built with a classpath reference, passing the model type first, then the process name, then the resource path.

```java
@Service
public class OrderService {

    private final ProcessEngine processEngine;

    public OrderService(ProcessEngine processEngine) {
        this.processEngine = processEngine;
    }

    public OrderResult execute(OrderRequest request) {
        ProcessDefinition definition = ProcessDefinition.classpath(
                ProcessModelType.TBBPM, "order.process",
                "flows/order-process.bpm");

        return processEngine.execute(
                        definition,
                        request,
                        OrderResult.class,
                        ProcessExecutionOptions.defaults())
                .orElseThrow();
    }
}
```

Four things are visible in those ten lines. The engine is a constructor dependency, which enforces the single long-lived instance. The model type is passed explicitly, so the same service works whether the flow is TBBPM or BPMN. The resource lives on the classpath, so it is packaged and versioned with the application rather than fetched from a repository at runtime. And the call passes an input object, an output class and ProcessExecutionOptions.defaults(), returning an optional that the caller unwraps with orElseThrow, meaning a failed flow surfaces as an exception rather than a silent empty result.

For a first real run the repository points at examples/spring-boot-basic, which is the smallest complete project. The quick start guide at docs/en/quick-start.md covers the standalone composition path as well as preflight, warm-up and shutdown. If you want to see what a non-trivial flow looks like, the fuller example is examples/spring-boot-order-fulfillment, and it exercises gateways, a process call, parallel work, iteration, retries and controlled errors, which is the honest way to learn what the engine does with branching and failure.

## Compiled and interpreted are a real choice with a real cost

The performance claim in the README is framed as a choice rather than a promise: you choose compiled or interpreted execution, and compiled mode generates and reuses Java runtimes. That is the whole mechanism. Rather than walking a process definition as data on every call, the engine can generate Java source for the flow, compile it, and reuse that runtime for subsequent executions of the same definition.

The trade-off follows directly from that mechanism. Generating a runtime is not free, so a flow executed rarely is paying generation cost for very little reuse. That is why warm-up appears in the quick start guide alongside preflight and shutdown. A high-volume order path and a rarely taken exception-handling path are not the same case, and one engine configuration covers both only if you accept the cost profile of one of them.

The repository also ships a compileflow-benchmarks module, which tells you the project has a place to measure this, but the README makes no performance claim with numbers attached and neither does any other part of what is available here. Treat the high-performance framing as a design goal with a documented mechanism behind it, not as a measured result you can quote.

BPMN support is described as a documented subset of 2.0, not full coverage. If your diagram uses an element outside that subset, the failure mode is not a runtime error you can catch but a definition that does not load, so checking the subset boundaries against your own diagrams is a prerequisite rather than a debugging step.

## Workbench, Deploy and the parts of the module map

The repository root shows how much ships alongside the engine. There are separate modules for the API, core, TBBPM and BPMN frontends, a BOM for dependency management, two Spring Boot starters plus an autoconfigure module, and standalone directories for compileflow-deploy, compileflow-durable, compileflow-workbench and compileflow-workbench-server. There is a benchmarks module, an integration test module, examples, and a docs directory with an English compatibility policy and quick start.

Three GitHub Actions workflows are advertised as status badges: a Workbench Server CI, a Java Core CI and a Workbench CI. Splitting the suites this way means the core engine can be validated independently of the browser-facing Workbench, which is the part most likely to break on a front-end dependency bump.

CompileFlow Deploy is the module worth understanding if you run this in production. It publishes immutable versions, updates aliases with revision checks, and routes deterministic canary traffic. That means a flow definition can be released under a name that never changes content, and traffic can be shifted between two versions in a controlled way rather than by editing a definition in place. It also means ProcessRef has a purpose that the base engine does not need.

The Workbench is the browser side: model and validate processes, then publish, monitor and inspect execution through the Workbench Server. Note that the same README also mentions Agent workflow orchestration, composing Agent calls with service actions and business rules through Java Actions. That is a composition pattern over the existing Java Action mechanism rather than a separate runtime, and nothing in the available documentation describes scheduling, retries or failure handling for Agent calls specifically.

## What the repository does not tell you

Several things an adopter would reasonably want are absent from the documentation. There is no statement about which BPMN 2.0 elements are in the supported subset; the README says a documented subset and points elsewhere, but the list itself is not given. There is no migration guide between the 1.x released line and the 2.0.0-SNAPSHOT coordinates the quick start asks you to depend on.

There is also no rollback procedure described, no guidance on sizing or on how many concurrent executions a single engine instance is expected to handle beyond the statement that it is thread-safe, and no statement about what happens to an in-flight execution if the application is shut down. That last gap follows from the architecture rather than from an omission in the writing: with in-memory execution and no Durable API, a process mid-flight has nowhere to be written down.

The repository does carry the ordinary governance files, including CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, SUPPORT.md, MAINTAINERS.md, a NOTICE file alongside the LICENSE, a CHANGELOG.md and an OpenSSF Scorecard badge. The licence is Apache-2.0. The NOTICE file matters more than it looks: Apache 2.0 requires you to preserve notices and licence headers when redistributing, and the repository ships checkstyle-license-header.txt and checkstyle.xml, so header checks are part of the build rather than optional courtesy.

The last push was on 2026-10-02 and the repository is not archived, so the code is moving even though the release tags are old.

## Conclusion

Adopt CompileFlow if you want process orchestration embedded in a Spring Boot service, on a supported JDK version, and you are willing to choose between the compiled and interpreted execution modes deliberately. Do not adopt it expecting a drop-in durable engine, because the README is explicit that Deploy, Durable and Workbench are independent surfaces and that ProcessEngine.execute calls stay in memory unless you move to the Durable API. Before starting, check the version you are pinning against the release list, since the newest tagged release is 1.2.0 from 2022-07-15 while the documented starter coordinates in the quick start are 2.0.0-SNAPSHOT, and confirm that compileflow-bpmn covers the BPMN elements your diagrams actually use.

## FAQ

### How do I install CompileFlow in a Spring Boot project?

Build the starter from source with ./mvnw install -pl compileflow-spring-boot-starter-tbbpm -am -DskipTests, then add the com.alibaba.compileflow:compileflow-spring-boot-starter-tbbpm dependency at version 2.0.0-SNAPSHOT and inject ProcessEngine through the constructor.

### Is CompileFlow execution persistent by default?

No. The README states the surfaces are independent and that adding Deploy, Durable or Workbench does not make ProcessEngine.execute calls persistent. Persisted waits, timers and restart recovery come from the CompileFlow Durable API.

### Which Java versions does CompileFlow support?

JDK 17, 21 and 25 are supported, and generated bytecode targets Java 17. The repository links a compatibility policy at docs/en/compatibility-policy.md for details.

## Sources

- [alibaba/compileflow on GitHub](https://github.com/alibaba/compileflow)
- [Issues](https://github.com/alibaba/compileflow/issues)
- [License: Apache-2.0](https://github.com/alibaba/compileflow/blob/master/LICENSE)
- [README](https://github.com/alibaba/compileflow/blob/master/README.md)
- [Releases](https://github.com/alibaba/compileflow/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/alibaba-compileflow
