Comparison
Orch8 vs BullMQ
BullMQ is an excellent job queue — fast, simple, and battle-tested for background task processing. Orch8 is a workflow orchestration engine for multi-step sequences that need crash recovery, branching, and time-aware scheduling. They solve fundamentally different problems.
Job queue vs workflow engine
A job queue processes individual tasks. A workflow engine orchestrates multi-step sequences with state, branching, and recovery. Many teams start with BullMQ and add Orch8 when their workflows grow beyond what a job queue was designed for.
BullMQ excels at
- ✓Fast background job processing with Redis
- ✓Simple one-off tasks: resize image, send email, process payment
- ✓Priority queues and FIFO ordering
- ✓Job scheduling with cron and repeat
- ✓Rate limiting per queue
- ✓Minimal setup — Redis + npm package
Orch8 adds on top
- ✓Multi-step sequences with state between steps
- ✓Crash recovery — resume from last completed step
- ✓Conditional branching, loops, and parallel execution
- ✓Output memoization — no duplicate side effects on retry
- ✓Delays from minutes to months with timezone + business-day support
- ✓Human-in-the-loop approval gates
Side-by-side comparison
| Dimension | Orch8 | BullMQ |
|---|---|---|
| Type | Workflow orchestration engine | Job queue |
| Language | Rust | TypeScript (Node.js only) |
| Storage | PostgreSQL or SQLite | Redis |
| Durable execution | Yes — snapshot-based crash recovery | No — jobs re-queue on failure |
| Multi-step sequences | Native (blocks: step, loop, router, parallel, race) | Manual — stitch jobs together with custom code |
| Branching logic | Router blocks with conditions | Custom code between jobs |
| Rate limiting | Per-resource with sliding window, defer-not-drop | Per-queue with token bucket |
| Timezone scheduling | Built-in, per-task IANA timezone | Not built-in |
| Business-day awareness | Built-in | Not built-in |
| Human-in-the-loop | Native — wait_for_signal | Not built-in |
| AI agent support | Loop + Router + LLM rate limiting | Not built-in |
| Worker model | REST long-poll (any language) | Node.js only |
| License | BUSL-1.1 | MIT |
Signs you've outgrown a job queue
BullMQ is the right tool for many workloads. These are the signals that your workload has evolved into something that needs orchestration.
You're chaining jobs with custom glue code
Job A finishes → you create Job B with Job A's output → Job B finishes → you create Job C. This is a workflow. BullMQ gives you the pieces. Orch8 gives you the glue.
You're building a state machine for sequence position
Tracking which step a user is on, what's been sent, what's pending — this is workflow state. If you're storing it in Redis or your database manually, you're building a workflow engine.
Crashes cause duplicate side effects
A job sent an email but crashed before marking itself complete. On retry, it sends the email again. Orch8's output memoization prevents this — completed steps return cached results.
You need conditional branching mid-sequence
"If the user opened the email, send follow-up A. Otherwise, send follow-up B in 48 hours." This is orchestration logic that BullMQ leaves entirely to you.
You need delays longer than a few minutes
BullMQ delays are Redis-based. Scheduling a job for 14 days from now works, but timezone awareness, business-day exclusion, and DST handling require custom code.
You need workers in multiple languages
BullMQ is Node.js only. If your team uses Python, Go, or other languages, you need a separate job queue per language or a language-agnostic worker model like Orch8's REST API.
Multi-step sequence: BullMQ vs Orch8
An onboarding drip: send welcome email → wait 3 days → check if user activated → branch based on result.
BullMQ — manual job chaining
// Job 1: Send welcome email
queue.add('send-welcome', { userId });
// In the processor:
worker.on('completed', async (job) => {
if (job.name === 'send-welcome') {
// Schedule next job with delay
await queue.add('check-activation',
{ userId: job.data.userId },
{ delay: 3 * 24 * 60 * 60 * 1000 } // 3 days in ms
);
}
if (job.name === 'check-activation') {
const activated = await checkActivation(
job.data.userId
);
if (activated) {
await queue.add('send-pro-tips', job.data);
} else {
await queue.add('send-nudge', job.data);
}
}
});
// + error handling, dedup, state tracking...Orch8 — declarative sequence
{
"id": "onboarding_drip",
"blocks": [
{
"type": "step",
"handler": "send_welcome"
},
{
"type": "step",
"handler": "check_activation",
"delay": { "days": 3 }
},
{
"type": "router",
"routes": [
{
"condition": "{{outputs.check_activation.activated}}",
"blocks": [
{ "type": "step", "handler": "send_pro_tips" }
]
},
{
"default": true,
"blocks": [
{ "type": "step", "handler": "send_nudge" }
]
}
]
}
]
}
// Crash recovery, dedup, state: handled.When to use which
One-off background tasks (resize image, send single email, process webhook)
BullMQBullMQ is fast, simple, and purpose-built for individual job processing. No need for a workflow engine when there's no sequence.
Multi-step sequences with delays and branching
Orch8Sequences are Orch8's core design. Delays, conditions, branching, loops, and crash recovery are built in — not bolted on.
Simple retry logic for failed operations
BullMQBullMQ has excellent built-in retry with backoff. If your jobs are independent and don't need cross-job state, BullMQ handles retries well.
Retries that must prevent duplicate side effects
Orch8Output memoization ensures that a completed step never re-executes — even after crashes. Critical when retries could cause duplicate payments, emails, or API calls.
High-throughput job processing (10K+ jobs/second)
BullMQRedis-backed with minimal overhead. BullMQ is optimized for throughput on independent jobs.
Long-running workflows (days to weeks)
Orch8Snapshot-based persistence. Workflows run for weeks without accumulating state overhead. Deploy without killing in-progress workflows.
Workers in Python, Go, or other languages
Orch8BullMQ is Node.js only. Orch8 workers are plain HTTP endpoints — any language that handles POST requests.
They work well together. Use BullMQ for high-throughput independent jobs (image processing, webhook delivery). Use Orch8 for multi-step sequences where state, branching, and crash recovery matter. Many teams run both.
Try it yourself
One command to install. Two minutes to your first workflow.