Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Rust BPM Engine
A native Rust BPM runtime engine for long-running, stateful workflows.
Rust BPM Engine is a lightweight, embeddable Business Process Management (BPM) runtime, designed for executing long-running workflows with parallelism, timers, retries, human tasks, and Saga compensation β without relying on BPMN XML or heavyweight platforms.
This project focuses on the execution engine, not visual modeling or low-code tooling.
Why This Project
The Rust ecosystem lacks a production-grade BPM runtime that:
- Works natively in Rust
- Supports long-running business processes
- Handles failures, retries, and compensation correctly
- Does not depend on JVM, BPMN XML, or external workflow servers
This project fills that gap.
What This Is (and Is Not)
β This is
- A BPM runtime engine
- Token-based execution model
- Event-driven core
- Crash-safe and resumable
- Designed for backend systems and orchestration
β This is NOT
- A BPMN modeler
- A low-code platform
- A workflow UI tool
- A distributed workflow SaaS (yet)
Core Concepts
Token-based Execution
- Token is the unit of execution
- Parallelism is achieved by multiple tokens, not threads
- Each token advances independently through the process graph
Event-driven Engine
- All state transitions are triggered by events
- Event handlers are deterministic and transactional
- Engine progression is observable and replayable
Saga Compensation
- Long-running transactions are handled via Saga
- Only successfully completed steps are compensated
- Compensation executes in reverse order using dedicated tokens
Crash Recovery
- Engine state is fully persisted
- Tokens can be safely resumed after crashes
- No in-memory assumptions
Key Features
- π§ Token-based workflow execution
- π Parallel fork / join support
- β± Timers, delays, and timeouts
- π Retry with backoff
- π€ Human task integration
- π Saga compensation (long transactions)
- πΎ Persistent state & crash recovery
- βοΈ Native Rust, async-friendly design
High-level Architecture
API / Adapter
β
Application Services
β
BPM Engine Core
* Event Dispatcher
* Token Scheduler
* Node Executor
* Saga Coordinator
β
Persistence Layer
β
Infrastructure (DB / Clock / Logger)
For detailed design, see the architecture documentation.
Getting Started
Prerequisites: Rust 1.70+ (rustup).
Usage
Default demo (approval process)
Running the default binary starts the approval demo: Start β validate (ServiceTask) β gateway (ExclusiveGateway) β approve (UserTask) or reject (End) β end. State is stored in bpm.db; on boot, recovery runs and re-dispatches any Ready/Executing tokens.
You will see the process start, pause at the UserTask approve, then complete after the engine receives UserTaskCompleted.
Examples
Runnable examples live in examples/. Run any of them with:
| Example | Command | Description |
|---|---|---|
| minimal | cargo run --example minimal |
Start β End. In-memory SQLite; process completes in one run. |
| approval | cargo run --example approval |
Same flow as the default demo (validate β gateway β approve/reject β end). |
| exclusive_gateway | cargo run --example exclusive_gateway |
Start β ServiceTask β ExclusiveGateway (EL + VariableEq) β end_a or end_b. |
| el_gateway | cargo run --example el_gateway |
Gateway with EL expressions only: choice == "a", amount > 50, Default. |
| service_task_chain | cargo run --example service_task_chain |
Start β step1 β step2 β step3 β End (linear ServiceTask chain). |
| reject_path | cargo run --example reject_path |
Approval topology but variable set to reject; process ends without UserTask. |
| parallel_fork_join | cargo run --example parallel_fork_join |
Start β Fork β (branch_a, branch_b) β Join β End (ParallelFork/Join). |
- minimal: Two-node process (start, end); template for the smallest run.
- approval: Full approval flow with ServiceTask, ExclusiveGateway, and UserTask; simulates βcomplete user taskβ so you see the same behavior as
cargo runwithoutbpm.db. - exclusive_gateway: Branching with EL expression (
choice == "a") and VariableEq; first matching edge wins. - el_gateway: Gateway conditions using EL only: string equality (
choice == "a"), numeric comparison (amount > 50), and Default. - service_task_chain: Three ServiceTasks in sequence; shows linear automation.
- reject_path: Same graph as approval; ServiceTask sets
valid = "false"so the gateway takes Default β reject (no UserTask). - parallel_fork_join: ParallelFork creates two tokens; both run branch_a/branch_b; ParallelJoin waits for both, then one token continues to End (uses in-memory join state).
Using the engine as a library
From crates.io (recommended):
Add to your projectβs Cargo.toml:
[]
= "0.1"
From a local path (e.g. for development or forking):
[]
= { = "../bpm-engine" }
Then define a ProcessDefinition, build an EngineContext with repos (e.g. InstanceRepo), and run BpmEngine::run with events such as ProcessStarted and UserTaskCompleted. Gateway conditions support EL expressions (engine/el): use EdgeCondition::Expression("key == \"value\"") or "key > 100" for numeric comparison. See the examples/ directory in this repo for full code (minimal, approval, exclusive_gateway, el_gateway, service_task_chain, reject_path, parallel_fork_join).
Documentation
- π Architecture Overview
- βοΈ Execution Model (Token & Concurrency)
- π Saga & Compensation
- β»οΈ Crash Recovery & Rehydration
- ποΈ Database Schema
- π§ͺ Testing Strategy
Status
π§ Early development / Architecture-first phase
- Core design is stable
- Implementation is in progress
- APIs may change
Design Philosophy
Token is the unit of execution.
Event is the unit of progress.
Saga is the unit of resilience.
Roadmap
v1
- Single-node engine
- Code-defined workflows
- Core runtime features
v2
- BPMN adapter layer
- Improved timer scheduling
- Execution visualization
v3
- Multi-engine coordination
- Horizontal scalability
- Advanced observability
License
MIT