devtoolreviews
Backend2026-09-29

Temporal vs Inngest vs Trigger.dev vs BullMQ (2026)

Background job and workflow tools compared: Temporal, Inngest, Trigger.dev, and BullMQ on durable execution, retries, long jobs, self-hosting, and pricing.

#Ratings

avg8.4
Temporal
8.8
Inngest
8.6
Trigger.dev
8.4
BullMQ
7.9

Every backend eventually grows a job that cannot run inside a request. A user uploads a forty-minute video. A Stripe webhook arrives, and the account it describes has to be provisioned now and reminded about its trial fourteen days from now. Somebody writes setTimeout inside a serverless function, ships it on a Friday, and learns what an execution limit is. Then the shopping starts. Inngest is the best default for TypeScript teams on serverless platforms in 2026, Temporal is the one to adopt when a workflow failing halfway costs real money, Trigger.dev wins for long compute-heavy jobs like AI pipelines and media processing, and BullMQ remains the right answer if you already run Redis and your jobs are one step long.

Background work sits downstream of two other choices. Where your workers live depends on your hosting, which our Fly.io vs Railway vs Render vs Coolify review covers. How you find out a job has been failing silently for six hours depends on the monitoring covered in the Datadog vs New Relic vs Sentry comparison.

Queues and durable execution

These four tools look similar on a landing page. They split into two camps once you read the docs.

A job queue stores a message, hands it to a worker, and retries the whole job if the worker throws. BullMQ is a queue. That model is simple and fast, and it breaks down the moment a job has several side effects in a row, because a retry after step three re-runs steps one and two. You end up writing your own checkpoint table in Postgres, with a status column that slowly grows eleven possible values.

Durable execution tools persist the result of each step. When something fails, the retry skips the steps that already succeeded and resumes where it stopped, with local variables intact. A workflow can sleep for a month without holding a process open. Temporal, Inngest, and Trigger.dev all sell this idea, and they implement it in very different ways, which matters more than any feature grid.

Temporal

Temporal is the heavyweight, descended from Uber's Cadence project and MIT licensed. You write workflows as ordinary code in Go, Java, TypeScript, Python, .NET, PHP, or Ruby. Workers you run yourself poll task queues on the Temporal server. The server records every event in a workflow's history, and when a worker crashes, another worker replays that history to rebuild state exactly where the first one died. It is the most battle-tested design here by a wide margin, running payment flows and order pipelines at companies where a stuck workflow ends up on an incident review.

Replay has a price. Workflow code must be deterministic, which means no reading the clock or calling the network inside a workflow. Those go into activities. Changing a workflow while old executions are still running requires versioning with the SDK's patching APIs, and getting it wrong produces nondeterminism errors on executions that started last week. Histories also have hard limits (50,000 events or 50 MB per execution), so a long-running loop needs Continue-As-New to start a fresh history. New engineers need a real week to get fluent. Budget for that week.

Self-hosting means operating the Temporal server plus a persistence store (Postgres or MySQL for most teams, Cassandra at very large scale), and an Elasticsearch-compatible store if you want advanced search over executions. Plenty of teams do it. More of them end up on Temporal Cloud, which bills per action with storage on top and removes the part of the job nobody wants on call for.

Inngest

Inngest turns the architecture inside out. You never run workers. You expose your functions through an HTTP handler inside your existing app (a Next.js route or an Express endpoint works fine), and Inngest calls that endpoint when an event arrives. Each step.run() executes as its own invocation, and its return value gets memoized, so a retry at step four sends back the saved results of steps one through three without running them. step.sleep() and step.waitForEvent() let a function pause for days while consuming zero compute.

For a team deploying to Vercel or Netlify this is close to magic. There is no new infrastructure to run, and every step fits comfortably inside a serverless timeout because no single step has to do everything. Flow control is where Inngest quietly pulls ahead of the others: per-key concurrency limits, throttling, debouncing, rate limits, and priority are each one line of config, which is how you stop a single enterprise customer's bulk import from starving everyone else's jobs. The local dev server shows every run and step in a browser UI, and it is the best debugging experience in this group.

The tradeoffs follow from the design. Every step is an HTTP round trip, so a function with two hundred tiny steps is slower and pricier than it would be on Temporal, and you should batch work inside steps. Pricing counts executions and steps, which rewards coarse steps. SDKs cover TypeScript and Python, plus Go, with TypeScript clearly getting new features first. The self-hosted server exists and works for smaller deployments, but most teams run on the cloud product, and your security review should know that event payloads pass through Inngest.

Trigger.dev

Trigger.dev started out looking a lot like Inngest and diverged with version 3. Your tasks are TypeScript files in your repo, deployed with the Trigger.dev CLI, and they run on Trigger.dev's own managed compute, outside your app. That one choice removes timeouts entirely. A task can transcode video for an hour, or chain eight LLM calls with retries on each, and it simply runs. You pick a machine size per task, which matters when one job needs 8 GB of memory and the rest need almost nothing.

Waits are handled with checkpointing: when a task calls wait.for() or waits on a child task, the runtime snapshots the process and restores it later, and you are not billed for the idle time. The Realtime API streams run status and metadata straight to a React frontend, which has turned into a quiet killer feature for AI products that need a progress bar during a three-minute generation. Build extensions handle awkward dependencies like FFmpeg, Puppeteer, Prisma, and bundled Python scripts without a custom Dockerfile.

It is TypeScript only. Pricing combines compute time with a small per-run charge, so a task that mostly waits on an external API is cheap, and a task that burns CPU for an hour costs what an hour of CPU costs. The project is Apache 2.0 and self-hostable with Docker or Kubernetes, which puts it ahead of Inngest for teams with hard data residency rules. Flow control is thinner than Inngest's, though queues with concurrency limits cover most real cases.

BullMQ

BullMQ is a Node.js library, MIT licensed, built on Redis. No vendor and no new service for security to approve. Delayed jobs, retries with exponential backoff, rate limiting, priorities, cron-style schedulers, and parent-child flows are all mature, and throughput is limited mostly by your Redis instance. For sending emails and nightly CRM syncs it does the job with almost no ceremony, and it has for years.

The gaps are the durable execution features. Multi-step state is yours to model. Observability is whatever you bolt on, usually Bull Board for free or Taskforce.sh if you pay. Redis has to be configured for persistence and with a noeviction memory policy, and that setting has been missed often enough to become folklore; an evicting Redis loses jobs silently.

Head-to-head

DimensionTemporalInngestTrigger.devBullMQ
ModelDurable execution via history replayDurable steps over HTTPDurable tasks with checkpointingJob queue
Where code runsYour workersYour app, invoked by InngestTrigger.dev compute or self-hostedYour workers
LanguagesSeven official SDKsTypeScript, Python, GoTypeScriptNode.js (Python port exists)
Long-running jobsYes, with Continue-As-New for huge historiesYes, split into stepsYes, no timeoutsYes, if the worker stays up
Flow controlBuild it in workflow codeBest in classQueues and concurrency limitsRate limits and priorities
Self-hostingYes, operationally heavyPossible, less commonYes, Docker or KubernetesIt is only a library
Learning curveSteepGentleGentleFlat
Best forPayments and order pipelinesServerless TypeScript appsAI pipelines and media jobsSimple jobs on existing Redis

Honorable mentions

Hatchet is an MIT-licensed durable task queue built on Postgres, a good fit if you want Inngest-style steps without adding Redis or a vendor. Restate takes a lighter approach to durable execution and is worth a look if Temporal's determinism rules scare your team. AWS Step Functions is fine when everything already lives in AWS and you enjoy JSON state machines. On a smaller scale, pg-boss gives you a respectable queue inside the Postgres you already run, which pairs well with a managed database from our Neon vs Supabase review.

Idempotency

Every one of these tools will, on some bad night, run your side effect twice, so send the idempotency key to Stripe.

The recommendation

If you deploy a TypeScript app to a serverless platform, start with Inngest. You get retries, sleeps, fan-out, and serious flow control without running a single new process, and you can be in production the same afternoon. Pick Trigger.dev instead when individual jobs run for minutes or hours, or when you want the job's progress streamed to your UI; AI features are the obvious case. Choose Temporal when workflows touch money or have to survive every failure mode you can name, and accept the learning curve as the cost of that guarantee. Stay on BullMQ if Redis is already in your stack and your jobs really are single steps. Most are, until the day one of them grows a second step and a retry charges a customer twice.

Winner

Inngest (best default) / Temporal (mission-critical workflows)

Independent testing. No affiliate bias.


Frequently asked questions

?Which tool wins in Temporal vs Inngest vs Trigger.dev vs BullMQ (2026)?

Inngest (best default) / Temporal (mission-critical workflows). The full review above explains the scoring behind that verdict.

?How is Temporal vs Inngest vs Trigger.dev vs BullMQ (2026) scored?

This review scores 4 dimensions: Temporal 8.8/10, Inngest 8.6/10, Trigger.dev 8.4/10, BullMQ 7.9/10. Temporal scores highest at 8.8/10.

?When was Temporal vs Inngest vs Trigger.dev vs BullMQ (2026) last updated?

This review was last updated on September 29, 2026. Reviews are re-checked when a material change occurs — a pricing revision, a significant feature change, or a new competitor entering the space.

?What does Temporal vs Inngest vs Trigger.dev vs BullMQ (2026) cover?

Four ways to run background jobs and durable workflows. Covers queues versus durable execution, Temporal's replay model and its costs, Inngest's HTTP steps for serverless apps, Trigger.dev for long AI and media jobs, and when BullMQ on Redis is enough. Filed under Backend on Dev Tool Reviews — see the reviews index for more Backend coverage.

⚡ Proven System Architecture

Scale 1,000+ Developer Benchmark Pages on Autopilot

We run devtoolreviews.com using the SEO Content OS—the battle-tested Python automation engine that turns technical keywords into structured benchmark tables, FAQ schemas, and de-slopped engineering guides.

Get the SEO Content OS ($19)→

Instant .zip download · Complete Python scripts + Next.js MDX pipelines