Durable workflows (Restate)
When to use Restate on Komodo
Section titled “When to use Restate on Komodo”Restate is a durable execution runtime: workflow steps journaled on the server survive pod restarts, so side effects inside ctx.run are not replayed after a crash.
On Komodo, Restate runs as a per-app StatefulSet next to your workload. You opt in through the devfile; the data-apps Helm chart provisions Restate, network policies, Istio authorization, and automatic deployment registration so the runtime can call back into your app.
Two App Builder entry points:
restate=trueonscaffold_app(typically with thefastapitemplate): addsrestate-sdk,metadata.komodo.restate, an examplerestate_workflow.py, and patchesmain.pywith a combined ASGI router (FastAPI for normal HTTP, Restate for protocol paths).restate-agenttemplate: a standalone Restaterestate.app(...)served by Uvicorn on the container port (default 9080). The whole process is the Restate deployment endpoint; there is no FastAPI split.
Enable Restate in the devfile
Section titled “Enable Restate in the devfile”Add (or keep) a restate block under metadata.komodo. The scaffold defaults match what App Builder injects:
metadata: komodo: restate: enabled: true storage: "10Gi" version: "1.3" dashboard: enabled: trueenabled: turns on the per-app Restate StatefulSet and related chart resources.storage: PVC size for Restate’s embedded RocksDB.version: Restate server image tag (for example1.3, aligned withdocker.io/restatedev/restate).dashboard.enabled: when combined with app exposure, exposes the Restate admin UI on a dedicated hostname (see your environment’s routing).
Multi-container apps
Section titled “Multi-container apps”The platform deploys one Restate instance per app, colocated with the primary service (the primaryService in the devfile). Non-primary services do not get their own Restate StatefulSet; they receive RESTATE_INGRESS_URL and RESTATE_ADMIN_URL pointing at the primary’s Restate Service. If a sibling defines its own Restate handlers, it must register that service’s in-cluster URL with the shared Restate admin API (see Multi-container and registration).
Runtime environment variables
Section titled “Runtime environment variables”When Restate is enabled, the chart injects:
| Variable | Purpose |
|---|---|
RESTATE_INGRESS_URL | In-cluster base URL for invoking handlers (for example POST …/Workflow/{key}/start). |
RESTATE_ADMIN_URL | In-cluster base URL for the admin API (for example POST …/deployments for registration). |
RESTATE_DASHBOARD_URL | Present when dashboard and exposure are enabled: HTTPS URL for the admin UI in a browser. |
Restate is the supported exception to “browser and containers only use public HTTPS”: pod-to-Restate traffic uses these in-cluster URLs. When calling Restate from Python with httpx, use trust_env=False and http2=False so traffic does not go through an HTTP proxy sidecar and does not attempt HTTP/2 against servers that speak HTTP/1.1 only.
Paths your app must expose (Restate → app)
Section titled “Paths your app must expose (Restate → app)”After registration, the Restate runtime calls your app’s listen port (the same port as your HTTP server and Kubernetes Service) on paths expected by the Restate service protocol and the Python SDK. Your ASGI stack must forward these to restate.app(...), not to FastAPI, or Restate will never see discovery or invocations.
Required paths for the FastAPI + Restate scaffold (as implemented in komodo-internal-tools):
/discover— discovery during deployment registration. The scaffold matches this path exactly (path == "/discover"). Use this path literally (no extra path prefix on the app port unless your framework strips a global prefix before ASGI routing)./invoke/— any path starting with/invoke/is routed to the Restate handler (service invocation protocol)./{ServiceName}/— HTTP-style paths for each registered service or virtual object (for example/Workflow/...for the defaultVirtualObject("Workflow")). For each newrestate.VirtualObject("MySvc")or service, add that service to the scaffold’s_restate_serviceslist inmain.pyso the ASGI router includes the/MySvc/prefix. If you omit a service from that list, named paths fall through to FastAPI and return 404 or the wrong handler.
restate-agent template: Uvicorn serves restate.app(services=[...]) directly, so all protocol and service paths are handled by the SDK on the container port without a separate FastAPI router.
Health checks: keep /health (or your configured probe path) on your web framework for Kubernetes and for the chart’s postStart registration script, which polls local HTTP before calling Restate admin. Do not send liveness or readiness probes to Restate-only paths on the user container; the Restate pod has its own admin /health on port 9070.
NetworkPolicies allow Restate → app on the TCP app port as a whole; there is no separate Kubernetes route per path. Path handling is entirely application routing.
Platform registration (postStart)
Section titled “Platform registration (postStart)”The data-apps chart runs a postStart hook on the user container that:
-
Optionally waits for the Istio sidecar, then for your app to respond on
http://127.0.0.1:<port><health-path>. -
Waits for Restate admin
GET {RESTATE_ADMIN_URL}/health. -
POST {RESTATE_ADMIN_URL}/deploymentswith JSON body:{"uri":"http://<release-service>.<namespace>.svc.cluster.local:<app-port>","use_http_11":true,"force":true}The URI is the app’s Kubernetes ClusterIP Service DNS name, not the public apps hostname. Restate uses it for in-cluster callbacks to
/discoverand/invoke/....
Image requirements: the script tries wget first, then curl. Install at least one in the image or registration fails silently from kubelet’s perspective; diagnostics append to /tmp/restate-registration.log inside the container (kubectl exec and cat that file).
Helm values under restate.registration control wait attempts and delays (for example localHttpPath, waitForLocalHttp, restateAdminHealthWaitAttempts). See deploy/charts/data-apps/values.yaml in the data-apps Helm chart (compute-services) for defaults.
Multi-container and registration
Section titled “Multi-container and registration”- Sibling services automatically receive
RESTATE_INGRESS_URLandRESTATE_ADMIN_URL; you do not add them manually to the devfile for that. - A sibling that only invokes workflows via
RESTATE_INGRESS_URLneedshttpx(or similar), not necessarilyrestate-sdkor ASGI patching. - A sibling that defines Restate handlers must combine ASGI routing like the primary, install
restate-sdk, and register its own stable Service DNS and port withPOST {RESTATE_ADMIN_URL}/deploymentsfrom application startup (with retries), because only the primary’s postStart runs the chart registration. Use the same JSON shape as the chart (uri,use_http_11,force).
Further reading
Section titled “Further reading”- Restate documentation
- HTTP invocation
- Register deployment (admin API)
- Service invocation protocol (spec)
- restate-sdk on PyPI — App Builder scaffolds use
restate-sdk>=0.4.0.