Guides
Move your background jobs from BullMQ to Strait with minimal changes.
Migrating from BullMQ
This guide helps you migrate from BullMQ (Redis-backed Node.js queue) to Strait. The core concepts map closely, but Strait replaces Redis queuing with PostgreSQL-backed orchestration.
Concept Mapping
| BullMQ | Strait | Notes |
|---|---|---|
| Queue | Job | A job definition with endpoint, schedule, and retry config |
| Job | Run | A single execution of a job |
| Worker | Worker mode | strait server --mode worker |
| Processor function | HTTP endpoint | Your job logic lives behind an HTTP endpoint |
| Repeatable jobs | Cron schedule | schedule: "*/5 * * * *" |
| Job attempts | max_retries | Same concept, configured per job |
| Backoff strategies | retry_strategy | exponential, linear, fixed, or custom |
| Flow (parent/child) | Workflow DAG | More powerful: fan-in/fan-out, conditions, approvals |
| Rate limiter | Per-key rate limiting | Built into job definitions |
| Delayed jobs | delayed_secs | Schedule runs for the future |
Step-by-Step Migration
1. Replace queue definitions with job definitions
BullMQ:
const emailQueue = new Queue("send-email", { connection: redis });Strait:
strait jobs create --name "send-email" \
--endpoint "https://your-app.com/api/jobs/send-email" \
--timeout 60 \
--max-retries 3 \
--retry-strategy exponential2. Convert processors to HTTP endpoints
BullMQ:
const worker = new Worker("send-email", async (job) => {
await sendEmail(job.data.to, job.data.subject, job.data.body);
}, { connection: redis });Strait:
export async function POST(req: Request) {
const { payload } = await req.json();
await sendEmail(payload.to, payload.subject, payload.body);
return Response.json({ status: "sent" });
}3. Replace queue.add() with API triggers
BullMQ:
await emailQueue.add("welcome", { to: "user@example.com", subject: "Welcome" });Strait:
const client = createClient({ baseUrl: "http://localhost:8080", apiKey: "..." });
await client.jobs.trigger("send-email", {
payload: { to: "user@example.com", subject: "Welcome" },
});4. Convert repeatable jobs to cron schedules
BullMQ:
await queue.add("cleanup", {}, { repeat: { cron: "0 0 * * *" } });Strait:
strait jobs create --name "cleanup" \
--endpoint "https://your-app.com/api/jobs/cleanup" \
--schedule "0 0 * * *"5. Replace Flows with Workflow DAGs
BullMQ:
const flow = new FlowProducer({ connection: redis });
await flow.add({ name: "parent", queueName: "pipeline", children: [...] });Strait:
{
"name": "pipeline",
"steps": [
{ "name": "step-1", "job": "extract" },
{ "name": "step-2", "job": "transform", "depends_on": ["step-1"] },
{ "name": "step-3", "job": "load", "depends_on": ["step-2"] }
]
}What You Gain
- No Redis dependency -- PostgreSQL handles queuing with SKIP LOCKED
- Built-in observability -- Logs, metrics, and traces without extra infrastructure
- Workflow orchestration -- DAGs with conditions, approvals, and event waits
- Multi-language SDKs -- Your job endpoints can be in any language
- Cost budgets -- Track and limit AI/API spending per run
Was this page helpful?