You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Task queue admission keeps one queue, tenant, or downstream dependency from consuming the whole worker fleet. Durable Workflow exposes admission in three layers:
9076
+
9077
+
- worker registrations advertise local workflow and activity slots
9078
+
- the server can cap active workflow and activity leases per namespace and queue
9079
+
- query tasks have a bounded pending queue so synchronous reads fail fast instead of growing without limit
9080
+
9081
+
Use admission controls when a queue is tied to a rate-limited dependency, tenants share the same server, or operators need to prove why a workflow is waiting.
9082
+
9083
+
## How The Budget Is Applied
9084
+
9085
+
Workflow and activity polling starts with the workers that are currently registered for a namespace and task queue. Each worker advertises `max_concurrent_workflow_tasks` and `max_concurrent_activity_tasks`; the server sums active, non-stale workers to calculate the queue's registered slot capacity.
9086
+
9087
+
Server-side active lease caps are optional. When configured, the server checks a short-lived cache lock before leasing the next workflow or activity task. If the cap is full, polling returns no task for that poll instead of exceeding the budget.
9088
+
9089
+
Query tasks are different: the control plane enqueues an ephemeral query task and waits for a worker response. `DW_QUERY_TASK_MAX_PENDING_PER_QUEUE` caps how many pending query tasks can exist for each namespace and task queue. When the queue is full, new queries return `query_task_queue_full` with HTTP `429`. If the cache store cannot provide the lock needed to mutate the query-task queue, queries return `query_task_queue_unavailable` with HTTP `503`.
9090
+
9091
+
## Server Configuration
9092
+
9093
+
Set global caps when every queue should share the same ceiling:
9094
+
9095
+
```bash
9096
+
DW_WORKFLOW_TASK_MAX_ACTIVE_LEASES_PER_QUEUE=25
9097
+
DW_ACTIVITY_TASK_MAX_ACTIVE_LEASES_PER_QUEUE=100
9098
+
DW_QUERY_TASK_MAX_PENDING_PER_QUEUE=1024
9099
+
```
9100
+
9101
+
Use `DW_TASK_QUEUE_ADMISSION_OVERRIDES` when specific queues need different budgets. Keys are checked in this order: `namespace:task_queue`, `task_queue`, then `*`.
The override value also accepts `max_active_leases` as an alias for `max_active_leases_per_queue`.
9119
+
9120
+
Cache must support atomic locks for server-side active lease caps and query-task admission. Redis is the recommended cache store for multi-node deployments.
9121
+
9122
+
## Worker Slot Registration
9123
+
9124
+
Python workers expose local semaphores through `Worker(...)` and send the same values during registration:
9125
+
9126
+
```python
9127
+
worker = Worker(
9128
+
client,
9129
+
task_queue="payments",
9130
+
workflows=[PaymentWorkflow],
9131
+
activities=[charge_card, send_receipt],
9132
+
max_concurrent_workflow_tasks=8,
9133
+
max_concurrent_activity_tasks=12,
9134
+
)
9135
+
```
9136
+
9137
+
For custom HTTP workers, send the slot fields to `POST /api/worker/register`:
Worker slots are not a hard tenant budget by themselves. They describe what active workers can currently process. Add server caps when you need a queue-wide ceiling that still holds if more workers are deployed.
| Query | `unavailable` | The query-task queue cannot acquire its cache lock; new queries return HTTP `503`. |
9217
+
9218
+
## Tuning Pattern
9219
+
9220
+
1. Start with worker slots sized to the process: CPU-bound workflow tasks are usually lower than I/O-heavy activity tasks.
9221
+
2. Add server caps for queues that protect a tenant, external API, database pool, or legacy service.
9222
+
3. Inspect `dw task-queue:describe <queue>` during load. `saturated` means add worker capacity or lower workflow fan-out. `throttled` means the server cap is doing its job. `no_active_workers` means the queue has no healthy poller.
9223
+
4. Keep query-task capacity large enough for normal operator reads, but low enough to fail fast during incidents. Query-task overflow is backpressure, not data loss.
This page documents version compatibility across Durable Workflow components. All components validate version compatibility at runtime and provide clear error messages when incompatible versions are detected.
0 commit comments