This library provides durable, fault-tolerant workflow orchestration for Ballerina applications. It lets you define long-running business processes — spanning minutes, hours, or days — that automatically recover from crashes and process restarts without losing progress.
Workflows and activities are ordinary Ballerina functions:
@workflow:Workflow— A durable function that orchestrates a business process. The runtime checkpoints every step and replays recorded history to recover from failures.@workflow:Activity— A function that performs a single non-deterministic operation (API call, database query, email send). Once an activity completes, its result is recorded and never re-executed during replay.
import ballerina/workflow;
@workflow:Activity
function checkInventory(string item) returns boolean|error {
// Call external inventory API
return true;
}
@workflow:Workflow
function processOrder(workflow:Context ctx, OrderRequest request) returns OrderResult|error {
boolean inStock = check ctx->callActivity(checkInventory, {"item": request.item});
if !inStock {
return {orderId: request.orderId, status: "OUT_OF_STOCK"};
}
return {orderId: request.orderId, status: "COMPLETED"};
}Use workflow:run() to start a workflow instance from any entry point — HTTP service, scheduled job, message consumer, or main:
string workflowId = check workflow:run(processOrder, {orderId: "ORD-001", item: "laptop"});A workflow can pause and wait for external input — approvals, payment confirmations, user decisions — using future-based event records. Send data to a running workflow with workflow:sendData():
// In the workflow — wait for a human decision
ApprovalDecision decision = check wait events.approval;
// From outside — deliver the decision
check workflow:sendData(processOrder, workflowId, "approval", {approverId: "mgr-1", approved: true});Use ctx->await to wait for multiple futures at once, with optional quorum and timeout:
| Pattern | Example |
|---|---|
| Wait for all | ctx->await([f1, f2]) |
| Wait for any (first wins) | ctx->await([f1, f2], 1) |
| Quorum (N of M) | ctx->await([f1, f2, f3], 2) |
| With deadline | ctx->await([f1, f2], timeout = {hours: 48}) |
Activity errors are returned as plain Ballerina values. The workflow decides what happens next:
string|error result = ctx->callActivity(chargeCard, {"amount": input.amount});
if result is error {
// retry with a different card, fall back, or compensate
}Enable automatic retries for transient failures:
string result = check ctx->callActivity(chargeCard, {"amount": input.amount},
retryOnError = true, maxRetries = 3);Add a Config.toml to your project. For local development with no server:
[ballerina.workflow]
mode = "IN_MEMORY"For production, connect to a Temporal server:
[ballerina.workflow]
mode = "TEMPORAL"
temporalHost = "localhost"
temporalPort = 7233
namespace = "default"
taskQueue = "my-task-queue"| Guide | Description |
|---|---|
| Get Started | Write and run your first workflow |
| Key Concepts | Workflows, activities, external data, and timers |
| Write Workflow Functions | Signatures, determinism rules, and durable sleep |
| Write Activity Functions | Activity patterns and retry options |
| Handle Data | Waiting for external input and sending data |
| Handle Errors | Propagation, retry, fallback, and compensation |
| Configure the Module | Connection settings, TLS, and namespaces |
| Example | Description |
|---|---|
| Get Started | First workflow |
| Order Processing | HTTP-triggered workflow with result polling |
| Human in the Loop | Pause for a human approval |
| Wait for All | Dual authorization — both teams must approve |
| Alternative Wait | First responder wins (approval ladder) |
| Forward Recovery | Pause for corrected data and retry |
| Error Propagation | Fail the workflow on a critical error |
| Error Fallback | Fall back to a secondary activity |
| Error Compensation | Saga: undo committed steps on failure |
Issues and Projects tabs are disabled for this repository as this is part of the Ballerina Standard Library. To report bugs, request new features, start new discussions, view project boards, etc., please visit Ballerina Standard Library parent repository.
This repository only contains the source code for the package.
-
Download and install Java SE Development Kit (JDK) version 21 (from one of the following locations).
Note: Set the
JAVA_HOMEenvironment variable to the path name of the directory into which you installed JDK. -
Export GitHub Personal Access Token with read package permissions as follows:
export packageUser=<Username> export packagePAT=<Personal access token>
-
Download and install Docker and Docker Compose (required for integration tests).
Execute the commands below to build from source.
-
To build the library:
./gradlew clean build
-
To run the integration tests:
./gradlew clean test -
To run a group of tests:
./gradlew clean test -Pgroups=<test_group_names>
-
To build the package without the tests:
./gradlew clean build -x test -
To debug the tests:
./gradlew clean test -Pdebug=<port>
-
To debug with Ballerina language:
./gradlew clean build -PbalJavaDebug=<port>
-
Publish the generated artifacts to the local Ballerina central repository:
./gradlew clean build -PpublishToLocalCentral=true
-
Publish the generated artifacts to the Ballerina central repository:
./gradlew clean build -PpublishToCentral=true
As an open source project, Ballerina welcomes contributions from the community.
For more information, go to the contribution guidelines.
All contributors are encouraged to read the Ballerina Code of Conduct.
- For more information go to the Workflow library.
- For example demonstrations of the usage, go to Ballerina By Examples.
- Chat live with us via our Discord server.
- Post all technical questions on Stack Overflow with the #ballerina tag.