Aviary
Transports

BullMQ / Redis

The queue-backed transport for cross-process and cross-language steps. Each step name gets its own tasks queue; results return on a shared results queue. Run one instance engine-side, one per worker.

@dudousxd/nestjs-durable-transport-bullmq carries steps over BullMQ/Redis — the path for steps that run in another process or another language (e.g. a Python worker).

pnpm add @dudousxd/nestjs-durable-transport-bullmq bullmq

How it works

  • ctx.remote dispatches a task to a per-name queue: <prefix>-tasks-<name>[@<partition>].
  • A worker registered for that step name consumes it, runs the handler, and adds the result to the shared <prefix>-results queue.
  • The engine-side instance consumes results and checkpoints them.

Run one instance engine-side (consumes results) and one per worker process (registers its handlers, and dispatches on the transport):

engine side (your NestJS app)
const transport = new BullMQTransport({ connection: { host: 'localhost', port: 6379 } });

DurableModule.forRoot({ store, transport });
worker side (a separate process)
const transport = new BullMQTransport({
  connection: { host: 'localhost', port: 6379 },
  partition: 'payments', // optional isolation suffix — omit for a single-tenant deployment
});
transport.handle('payments.charge-card', async (input) => ({ chargeId: await charge(input) }));

Options

OptionDescription
connectionioredis connection options (or an IORedis instance).
partitionOptional isolation suffix appended to every one of this instance's per-name queues (<name>@<partition>). Omit for a single-tenant deployment.
prefixNamespaces the queues. Defaults to durable.

The payload is the documented RemoteTask / StepResult JSON, so a non-Node worker on the same queues interoperates — that's exactly how the Python worker plugs in.

On this page