Configure state persistence
|
Stable — Production-ready with stable APIs and full test coverage. |
By default, Quarkus Flow executes workflows entirely in memory. While this is incredibly fast, it means that if your application crashes, restarts, or is scaled down, any currently running workflow instances are lost.
State Persistence solves this by writing the workflow’s state to a durable datastore every time a task completes or pauses.
Enabling persistence allows your workflows to survive:
-
Asynchronous Callbacks: Pausing a workflow for days or weeks while waiting for a human approval (HITL) or an external webhook.
-
Failures & Restarts: Recovering automatically from unexpected JVM crashes.
-
Kubernetes Node Drains: Safely migrating running workflows across pods during rolling updates, deployments, or cluster scaling events.
(For a deeper conceptual dive into how this enables cluster-wide orchestration, see Durable Workflows in Kubernetes).
|
The Quarkus Flow team is currently actively testing and benchmarking these persistence providers for high-throughput production scenarios. Expect deeper performance tuning guides in the future. |
1. Automatic Restoration
When a persistence provider is active, Quarkus Flow will automatically attempt to resume interrupted workflows upon application startup.
When the server boots, any workflow instance that was running when the JVM previously shut down (as identified by its application ID) will resume execution from its last recorded checkpoint.
If you need to disable this auto-resume behavior, add this to your application.properties:
quarkus.flow.persistence.auto-restore=false
2. Excluding Workflows from Persistence
In some scenarios, you may want to exclude specific workflows from persistence while keeping persistence enabled for others.
To exclude workflows from persistence, add their IDs in namespace:name:version format to the exclusion list in your application.properties:
quarkus.flow.persistence.exclude-workflows=com.example:temporary-workflow:1.0.0,com.example:test-workflow:0.1.0
|
Excluded workflows will:
|
3. Periodic Re-scan (Self-Healing Recovery)
Automatic restoration (see above) only runs once, at application startup. In rare cases, a workflow instance can end up persisted to the datastore under this runner’s application ID without being tracked in memory — for example, if the JVM is interrupted between writing the instance to the datastore and registering it in memory. Such an instance would otherwise stay stuck until the next restart.
To cover this, Quarkus Flow can periodically re-scan the datastore for instances that belong to this runner’s application ID but aren’t currently active in memory, and resume them automatically. This also lays the groundwork for a future external rebalancer that reassigns workflow instances across runners: a runner newly assigned an instance picks it up on its next scan cycle, without needing a restart.
Periodic re-scanning is disabled by default — enable it by setting a scan interval in your application.properties:
quarkus.flow.persistence.scan-interval=30s
|
The periodic scan respects |
4. Choose a Persistence Provider
Quarkus Flow provides three drop-in persistence implementations. You should only include one of these dependencies in your project at a time.
Option A: Redis (Recommended for distributed workloads)
Redis is an in-memory data structure store that provides excellent performance for high-throughput workflow checkpoints.
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-redis</artifactId>
</dependency>
Configure the Redis connection in your application.properties:
quarkus.redis.hosts=redis://localhost:6379
| Our integration tests use Valkey image instead. |
Using Infinispan Server RESP
Quarkus Flow can use Infinispan Server as a Redis-compatible persistence backend through the Infinispan RESP endpoint.
This mode still uses the quarkus-flow-redis persistence implementation and the Quarkus Redis client. No Quarkus Flow Infinispan-specific runtime dependency is required.
Infinispan Server exposes RESP on the default single-port endpoint. Redis clients connect to the same server port, 11222, and Infinispan routes RESP traffic to the RESP connector.
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-redis</artifactId>
</dependency>
Configure the Quarkus Redis client to point to the Infinispan Server RESP endpoint:
quarkus.redis.hosts=redis://admin:password@infinispan-server:11222
For local development with Docker:
docker run --rm \
--name infinispan \
-p 11222:11222 \
-e USER=admin \
-e PASS=password \
quay.io/infinispan/server:15.0
Then configure your application:
quarkus.redis.hosts=redis://admin:password@localhost:11222
For Kubernetes deployments managed by the Infinispan Operator, point quarkus.redis.hosts to the internal Infinispan service name:
quarkus.redis.hosts=redis://admin:password@infinispan:11222
A minimal Infinispan cluster managed by the Operator can be created with:
apiVersion: infinispan.org/v1
kind: Infinispan
metadata:
name: infinispan
spec:
replicas: 2
Use Kubernetes Secret or your platform secret-management mechanism to provide the username and password to the Quarkus application instead of hardcoding credentials in application.properties.
For example:
quarkus.redis.hosts=redis://${INFINISPAN_USER}:${INFINISPAN_PASSWORD}@infinispan:11222
Option B: JPA (Relational Databases)
JPA allows you to store workflow state in a standard relational database (e.g., PostgreSQL, MySQL). This is ideal if your enterprise architecture already relies heavily on a relational database.
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-jpa</artifactId>
</dependency>
You must also configure a Quarkus JDBC driver and datasource. See the Quarkus Datasources Guide for full instructions.
Database Schema Migration
Quarkus Flow can create the persistence tables automatically through the Quarkus Hibernate ORM schema management configuration:
quarkus.hibernate-orm.schema-management.strategy=update
This is convenient for development and testing. For production, prefer managing the schema explicitly with a migration tool such as Flyway.
The recommended way to do that is the quarkus-flow-db-migration extension, which ships versioned Flyway scripts for this schema for you; see Database Schema Migration for the full setup. If you’d rather manage the migration yourself, see the Manual migration section of that guide.
Option C: MVStore (Local file system)
MVStore writes workflow state to a local file system file. This is an excellent, zero-infrastructure option for local development, testing, or single-node edge deployments.
<dependency>
<groupId>io.quarkiverse.flow</groupId>
<artifactId>quarkus-flow-mvstore</artifactId>
</dependency>
Configure the local file path in your application.properties:
quarkus.flow.persistence.mvstore.db-path=${user.home}/testFlowMVStore.db
See also
-
Durable Workflows in Kubernetes — architecture and concepts for distributed execution.
-
Using the Quarkus Redis Client — advanced Redis configuration.
-
MVStore homepage — deeper dive into the MVStore engine.
-
Open Workflow Java SDK Persistence — upstream SDK reference.