Durable Workflows
By default, LogicFlowRuntime pods are stateless. Workflow instances exist only in memory and are
lost if a pod restarts. Durable mode adds a PostgreSQL persistence layer and uses Kubernetes Leases
to give each pod a stable identity across restarts, so in-flight workflow instances survive pod
failures.
Enabling Durable Mode
Set spec.persistence on the LogicFlowRuntime to switch the runtime to durable mode:
apiVersion: logic.kubesmarts.org/v1
kind: LogicFlowRuntime
metadata:
name: order-processing
namespace: my-namespace
spec:
replicas: 2
image: quay.io/quarkiverse/quarkus-flow-runner:1.0.0-standard (1)
persistence:
postgresql:
secretRef:
name: order-processing-db-secret (2)
serviceRef: (3)
name: postgresql
port: 5432
databaseName: workflows
| 1 | Use the standard image — the minimal image does not include the PostgreSQL driver. |
| 2 | A Secret containing POSTGRESQL_USER and POSTGRESQL_PASSWORD keys (the operator defaults).
Override with secretRef.userKey / secretRef.passwordKey if your Secret uses different key names. |
| 3 | The operator builds the JDBC URL from serviceRef. Alternatively supply an explicit
jdbcUrl instead of serviceRef. |
|
The |
Kubernetes Leases for Stable Pod Identity
Quarkus Flow Runner uses a lease-per-pod model to distribute durable workflow instances across the pool. Each pod must hold a uniquely numbered lease so it can claim ownership of a specific partition of workflow data in the database.
When durable mode is enabled, the operator creates one Kubernetes Lease for each replica:
| Replica index | Lease name |
|---|---|
0 |
|
1 |
|
N |
|
For the order-processing runtime with replicas: 2, the leases are:
-
flow-pool-member-order-processing-00 -
flow-pool-member-order-processing-01
Each pod acquires exactly one of these leases at startup. If the pod restarts, it reacquires the same lease — giving it the same stable identity in the pool. The operator sets up the RBAC (Role + RoleBinding) required for the runtime’s ServiceAccount to get and update these Leases.
Environment Variables Injected by the Operator
The operator injects the following environment variables into the runtime pods when persistence is configured:
| Environment variable | Value / source |
|---|---|
|
|
|
Set to the |
|
Injected via Kubernetes downward API field reference ( |
|
Injected via Kubernetes downward API field reference ( |
|
|
|
From the Secret specified in |
|
From the Secret specified in |
|
Built from |
Deployment Strategy in Durable Mode
Stateless runtimes use the default RollingUpdate strategy. Durable runtimes require a stricter
strategy to ensure that a pod releases its Lease before a replacement pod tries to acquire it.
| Replica count | Deployment strategy |
|---|---|
1 |
|
2 or more |
|
|
Do not override the Deployment strategy on a durable runtime. The |
PostgreSQL Connection: serviceRef vs jdbcUrl
The operator supports two ways to specify the database connection:
Option 1 — serviceRef (recommended): The operator constructs the JDBC URL from the service name, port, and database name.
persistence:
postgresql:
secretRef:
name: order-processing-db-secret
serviceRef:
name: postgresql
port: 5432
databaseName: workflows
# Produces: jdbc:postgresql://postgresql:5432/workflows
Option 2 — explicit jdbcUrl: Provide the full JDBC URL directly. Use this when the database is not exposed as a Kubernetes Service, or when you need non-standard connection parameters.
persistence:
postgresql:
secretRef:
name: order-processing-db-secret
jdbcUrl: "jdbc:postgresql://db.example.com:5432/workflows?sslmode=require"
Scaling a Durable Runtime
When you change spec.replicas, the operator reconciles the Lease set to match:
-
Scale up — new Leases are created for the added replicas before the Deployment is updated.
-
Scale down — the Deployment is updated first; after the pods terminate and release their Leases, the operator deletes the orphaned Lease resources.
|
Scaling a durable runtime causes a rolling restart due to the |