Every registered backend needs the worker bus and a
shared hooks registry:
TAI_BUS_REDIS_URL
and HOOKS_REDIS_URL must be set (each falls back to TAI_DEFAULT_REDIS_URL), or
boot is refused. The backend process matches the events it raises against its own
hooks registry, and an in-memory one holds none of the hooks registered through
the server. Stacks sharing one Redis must also diverge on TAI_BUS_NAMESPACE
(default tai). On arq and RQ they must also set distinct ARQ_QUEUE_NAME / RQ_QUEUE_NAME values, and no
stack’s value may be another stack’s value followed by .<label>; otherwise one stack’s workers run the other
stack’s jobs.Install and run one
Each backend’s package, itsbackend_module manifest key, its <PREFIX>_*
settings, the worker/beat/dashboard commands it accepts, and its
contract-coverage quirks live on the plugin page:
backend-arq
ARQ_* settings and the single worker process.backend-celery
CELERY_* settings, beat and flower, and the prefork concurrency caveat.backend-rq
RQ_* settings, worker, beat, and the dashboard.Send a task to a chosen worker
Thesync_task and async_task branches take an optional queue argument on
all three backends; it sends the job to the workers that serve that queue.
- On arq and RQ the value is a label of letters, digits,
_and-. The plugin derives the queue<ARQ_QUEUE_NAME>.<label>/<RQ_QUEUE_NAME>.<label>from it, and any other value is refused before the job is sent. - With distinct settings queues, as the note above requires, a label cannot reach
another stack’s worker: every derived queue starts with this stack’s own
ARQ_QUEUE_NAME/RQ_QUEUE_NAME. - Celery takes its own queue name; Celery stacks are kept apart by their broker vhost.
- Start a worker on the label: arq and RQ take
--queue <label>(the flag is on each plugin page); a Celery worker takes Celery’s own-Q <queue>(and a distinct-n <name>@%hfor a second worker), passed throughtai backend worker. See the backend-arq and backend-rq plugin pages. - A preset over a
sync_taskorasync_taskbranch can fixqueuein its arguments, so every call through the preset runs on that queue. - Schedules carry no queue: they run on the settings queue and need a worker that serves it.
- A job on a queue no worker serves waits: a
sync_taskcall times out after the task timeout, and anasync_taskjob stays queued.
See also
- Backends — the contract all three implement.
- Manage a fleet — read the live worker census.
- Schedule a tool — put work on a schedule.

