Application (Worker and Client)
View as MarkdownYour Dex application is the code you deploy. It has two parts:
- A Worker hosts Flow definitions. It runs WaitFor, Execute, and RPC handlers when Dex hands it work.
- A Client starts Flows, calls RPCs, reads Attributes, and searches Flows. See Client.
A process can run a Worker, a Client, or both.
How it fits with the other components
Workers and Clients connect to the Dex Server (server-zd). Every Worker is a pull Worker. It opens outbound task streams to the server and never listens for calls. So a Worker needs no inbound port and can run behind NAT or a firewall.
Dex sends every Flow, SubFlow, Step, and RPC call to your Workers. There is no Worker address to configure. A Flow that Dex Web or dexcli starts also runs on your Workers.
A Worker can publish the Flow Definition Graphs of its Flows to the server when it starts. Dex Web reads them there to draw each Flow.
Start a Worker
Configure the Worker with the server address. A Client needs only the server address too. You can also set pull options to tune task capacity, registration, and shutdown.
Each SDK reference has a runnable startup example: Go, Python, Java, TypeScript, and Rust.
Capacity and shutdown
A Worker opens one stream for each task slot. Dex sends a task only to a free slot, so a Worker never has to decline work for lack of capacity. A Step that no Worker takes waits in a durable task queue. An RPC fails when no Worker takes it in time. Stop Workers gracefully during a deployment, so running tasks can finish.
Workers and the task queue describes readiness, routing, capacity, shutdown, and network settings.
Operate it in production
When a Flow does not advance or fails, follow Troubleshoot a Flow run.
Versioning Flow code
Dex does not re-run your earlier Step code to decide what a Flow does next. So deploying changed code never causes a replay error. You still have to keep open Flows working across a deployment. They can meet changed business rules, missing Step implementations, renamed RPCs, or incompatible data.
Lock business behavior at Flow start
Persist a business version value when a Flow starts, such as an Attribute or a field in the start state. Branch on that stored value, not on the Worker build currently serving the call. Existing Flows keep their old behavior; new Flows can use the new behavior after deployment.
Use this when a change alters a decision, payment rule, retry policy, deadline, or other customer-visible meaning. Deploying new code alone is not enough, because a long-running Flow can call a newly deployed Worker later.
Evolve data and contracts additively
Add optional fields. Code that reads a payload must handle fields that older runs did not set, and ignore unknown fields that newer components send. Supply a safe default for an absent field, and keep the previous meaning of existing field values. For an incompatible payload or output contract, introduce a new Step type or RPC name instead of silently changing the old one.
Keep old definitions until old Flows finish
Do not delete or rename a Flow type, Step type, or RPC implementation while an open Flow can still call it. Deploy the new definition alongside the old one, route only new-version Flows to it, and keep the old implementation available through retries and any approved Time Travel recovery.
During a rolling deployment, a Worker that lacks a requested Step or RPC can hand the call to another Worker that has it. This does not use up a Step attempt. See Routing and availability.
Before removing the old definition, search for the legacy Flow type and confirm that no running, waiting, retrying, or recoverable terminal Flow needs it. Keep the search result with the change record. The exact query depends on your search fields. Start with a search by Flow type:
dexcli flow search --query 'FlowType = "OldFlowType"'
Only remove the old code after the result is empty or every remaining Flow has an explicitly approved retirement plan.