---
title: "Application (Worker and Client)"
description: "Your Dex application is the code you deploy. It has two parts:"
canonical_url: "https://docs.superdurable.io/components/application/"
source: "docs/content/components/application.mdx"
locale: "en"
---

# Application (Worker and Client)

Your 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](https://docs.superdurable.io/concepts/client.md).

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](https://docs.superdurable.io/components/web.md)
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.

<a id="enable-pull-mode"></a>

## 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](https://docs.superdurable.io/reference/go/workers.md), [Python](https://docs.superdurable.io/reference/python/workers.md),
[Java](https://docs.superdurable.io/reference/java/workers.md), [TypeScript](https://docs.superdurable.io/reference/typescript/workers.md),
and [Rust](https://docs.superdurable.io/reference/rust/workers.md).

## 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](https://docs.superdurable.io/reference/server/workers.md) 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](https://docs.superdurable.io/reference/web/debugging.md).

## 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](https://docs.superdurable.io/reference/server/workers.md#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:

```bash
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.
