Affiliate Reviews Developer Tools

Trigger.dev vs Inngest for Background Jobs: Real Pricing and DX Test

July 08, 2026 11 min read 3 views

Background jobs are one of those things that feel simple until you're three hours into debugging a silent failure at 2 AM. In a serverless environment, the problem gets worse β€” functions time out, retries aren't guaranteed, and you have no visibility into what actually ran.

Trigger.dev and Inngest both promise to fix this. They both let you write background jobs as regular code, handle retries, and give you an observable dashboard. But they make very different bets on how you should structure that code and what you pay when you grow.

What you'll learn

  • How Trigger.dev and Inngest model jobs differently and what that means in practice
  • Step-by-step setup for a realistic background job on each platform
  • A clear breakdown of free-tier limits and where pricing gets expensive
  • Honest developer experience notes β€” things the docs don't tell you
  • Which tool fits which team, with concrete recommendations

The problem with background jobs in serverless apps

Serverless functions max out somewhere between 15 seconds and a few minutes depending on your provider. Any job that needs longer β€” sending bulk emails, processing uploads, syncing data with a third-party API β€” has to be broken up or moved somewhere else. That "somewhere else" used to mean running your own queue with BullMQ or SQS. Both work fine, but you're now managing infrastructure alongside your application code.

The newer generation of tools, including Trigger.dev and Inngest, lets you write long-running jobs as plain TypeScript functions and offloads the queue, retry logic, and scheduling to a managed platform. The pitch is good. But the execution β€” and the pricing β€” varies enough that the choice matters.

How both tools work under the hood

Understanding the mental model for each tool will save you a lot of confusion later.

Inngest

Inngest works by sending events into its cloud. You define functions that react to those events, and Inngest orchestrates the execution β€” including steps, retries, and waits. Your function code runs inside your own infrastructure (a serverless function, a server, a container), but Inngest controls when and how it's called. Each step.run() call inside your function is checkpointed; if something fails, only that step reruns.

Trigger.dev

Trigger.dev v3 (the current version) runs your jobs inside its own managed infrastructure using a worker pool. You write jobs with the Trigger SDK, and Trigger.dev handles spinning up workers, persisting state, and retrying tasks. You don't need a running server of your own β€” Trigger deploys your job code into its cloud. It also supports self-hosting if you want to keep everything on your infrastructure.

The key difference: Inngest runs your code where you host it, while Trigger.dev runs your code in its own managed workers. This changes the cold-start story and the pricing model significantly.

Setting up your first job: Trigger.dev

Start by installing the SDK and initializing a project. You'll need a Trigger.dev account and your project's API key.

npm install @trigger.dev/sdk
npx trigger.dev@latest init

The init command scaffolds a trigger/ directory and adds configuration to your project. Define a job inside that folder:

import { task } from "@trigger.dev/sdk/v3";

export const processUpload = task({
  id: "process-upload",
  retry: {
    maxAttempts: 3,
    minTimeoutInMs: 1000,
    maxTimeoutInMs: 30000,
    factor: 2,
  },
  run: async (payload: { fileUrl: string; userId: string }) => {
    // Download file
    const file = await downloadFile(payload.fileUrl);

    // Heavy processing β€” no timeout anxiety
    const result = await runAnalysis(file);

    // Notify user
    await notifyUser(payload.userId, result);

    return { processed: true, resultId: result.id };
  },
});

Trigger the job from anywhere in your application by importing and calling it:

import { processUpload } from "../trigger/processUpload";

// Inside an API route or server action
await processUpload.trigger({
  fileUrl: uploadedUrl,
  userId: currentUser.id,
});

Deploy your tasks with npx trigger.dev@latest deploy. Trigger handles building and uploading your code to its worker infrastructure. The dashboard gives you a real-time log of every run, step output, and retry attempt. This part of the DX is genuinely excellent.

Setting up your first job: Inngest

Inngest requires an HTTP endpoint in your app that it can POST events to. Install the SDK, then create a serving endpoint β€” Next.js is the most common setup, but it works with any Node.js framework.

npm install inngest
// inngest/client.ts
import { Inngest } from "inngest";

export const inngest = new Inngest({ id: "my-app" });

Define a function that reacts to a named event:

// inngest/processUpload.ts
import { inngest } from "./client";

export const processUpload = inngest.createFunction(
  {
    id: "process-upload",
    retries: 3,
  },
  { event: "upload/file.uploaded" },
  async ({ event, step }) => {
    const file = await step.run("download-file", () =>
      downloadFile(event.data.fileUrl)
    );

    const result = await step.run("run-analysis", () =>
      runAnalysis(file)
    );

    await step.run("notify-user", () =>
      notifyUser(event.data.userId, result)
    );

    return { processed: true, resultId: result.id };
  }
);

Expose a serving route. In Next.js App Router this looks like:

// app/api/inngest/route.ts
import { serve } from "inngest/next";
import { inngest } from "../../../inngest/client";
import { processUpload } from "../../../inngest/processUpload";

export const { GET, POST, PUT } = serve({
  client: inngest,
  functions: [processUpload],
});

Send an event from your application code:

await inngest.send({
  name: "upload/file.uploaded",
  data: { fileUrl: uploadedUrl, userId: currentUser.id },
});

Inngest's local dev server is worth calling out: run npx inngest-cli@latest dev and you get a local UI that mirrors the cloud dashboard. Events you send locally are captured and replayed in real time. It's the best part of the Inngest DX, hands down.

Developer experience compared

Both tools have good documentation and TypeScript support, but the day-to-day feel is different.

Local development

Inngest wins this category. The local dev server is fast to start and gives you event replay, which means you can trigger your function with the same payload multiple times without touching real infrastructure. Trigger.dev's local development mode (trigger.dev dev) works, but it requires a tunnel to connect your machine to Trigger's cloud, which adds latency and occasionally drops connections on spotty networks.

Debugging

Trigger.dev's cloud dashboard shows every task run with a step-by-step trace, payload, output, and duration. It's detailed enough that you rarely need to add extra logging to understand what went wrong. Inngest's dashboard is comparable β€” function runs show each step's output and error β€” but the UI felt slightly slower to load in testing.

Long-running jobs

This is where Trigger.dev's architecture pays off. Because your code runs in its managed workers, there's no function timeout from your hosting provider. You can run a job for hours if needed. Inngest gets around serverless timeouts by breaking work into steps β€” each step.run() is a separate invocation β€” but this means your total execution time is still bounded by how quickly Inngest re-invokes your function. For most workloads this is fine, but truly long sequential processing is simpler with Trigger.

If you're interested in how this compares to managing notification workflows, the Courier vs Knock comparison on notification infrastructure covers similar architectural trade-offs in a related domain.

Framework compatibility

Inngest has official adapters for Next.js, Remix, SvelteKit, Express, Hono, and several others. Trigger.dev v3 is framework-agnostic at the job level β€” you deploy job code independently from your app, so there's no adapter needed. This is cleaner if your app isn't a standard Node.js web framework.

Free tier and real pricing breakdown

This is where you need to read carefully, because the marketing pages for both tools require some mental translation.

Inngest free tier

Inngest's free plan gives you a generous number of function runs per month (the exact number changes, so check their current pricing page), one concurrent worker, and a limited retention window for run history. The meaningful constraints are concurrency and the number of steps per run counted against your quota. Each step.run() call counts as a step, so a function with five steps uses five times your step quota compared to a single-step function. Plan your step usage carefully before assuming you're within the free tier.

Trigger.dev free tier

Trigger.dev's free plan is usage-based on compute seconds β€” the actual CPU time your jobs consume in their worker infrastructure. A quick job that runs in a second costs very little. A job that runs for ten minutes consumes your compute budget faster. The free allowance covers a reasonable amount of experimentation, but data-heavy processing tasks will eat through it quickly. The dashboard shows your usage in real time, which helps.

Paid plan comparison

Feature Inngest (Hobby/Pro) Trigger.dev (Pro)
Pricing model Step-count based Compute seconds based
Concurrency Tiered by plan Configurable on paid plans
Log retention 7 days (free), longer on paid 30 days on paid plans
Self-hosting Not available (cloud only) Supported (open-source)
Team features Available on Team plan Available on Pro plan

The self-hosting difference is significant for teams with data residency requirements. Trigger.dev is open-source and can run entirely on your own infrastructure. Inngest has no self-hosted option β€” everything runs through their cloud. If you're already managing costs carefully across your stack, the Upstash vs Redis Cloud breakdown shows a similar pattern of serverless pricing surprises worth keeping in mind.

The cost cliff to watch for

With Inngest, the cliff arrives when you start running high-frequency jobs with many steps. A job that runs 10,000 times per day with 8 steps each generates 80,000 steps per day. That adds up fast. With Trigger.dev, the cliff comes from long-running compute β€” if you're running jobs that each take several minutes, your compute seconds burn quickly on the free tier but the cost per second on paid plans is predictable.

Neither platform is dramatically expensive at moderate scale, but the pricing structure rewards different job shapes. Match the tool to your job profile before committing.

Where each tool breaks down

No tool is perfect. Here's what you'll run into with each one.

Inngest limitations

  • No self-hosting means vendor lock-in from day one. If Inngest changes pricing or terms, you're migrating your entire job infrastructure.
  • Step function mental model takes time to internalize. Junior developers sometimes flatten everything into one step, losing the retry granularity that makes the platform useful.
  • Your infrastructure still runs the code, so cold starts from your serverless functions still apply to each step invocation. Long chains of steps on Vercel or Lambda can accumulate cold-start latency.

Trigger.dev limitations

  • The tunnel-based local dev experience is the weakest part of the DX. Network-dependent development is frustrating.
  • v3 is a significant rewrite from v2, and older tutorials still rank highly in search results. Make sure any example code you find online is using the v3 SDK.
  • Self-hosting is powerful but non-trivial. Running the Trigger.dev platform yourself requires Docker and a reasonable amount of configuration; it's not a five-minute job.

For teams choosing their full infrastructure stack, it's worth reading the Render vs Railway comparison on pricing traps β€” the pattern of free-tier generosity followed by steep paid tiers shows up repeatedly across developer tooling.

Which use case fits which tool

These aren't hard rules, but they cover the majority of real scenarios.

Pick Inngest if:

  • You're building on Next.js or another framework with an official Inngest adapter
  • Your jobs are event-driven and composed of discrete steps that each complete in under a minute
  • You want the best local development experience with event replay
  • You don't have data residency requirements that rule out a US-hosted SaaS

Pick Trigger.dev if:

  • You need genuinely long-running jobs (multi-minute or longer) without timeout gymnastics
  • Self-hosting is a requirement now or likely to be one soon
  • Your job code runs independently from your web application (background workers, not in-app functions)
  • You want compute-second pricing rather than per-step pricing

The event notification side of your stack has similar trade-offs worth evaluating β€” the Resend vs Loops email comparison walks through how per-event pricing interacts with real sending volume in production.

Wrapping up: which one should you pick

Both tools are production-ready and well-maintained. The decision comes down to three things: your job shape, your hosting situation, and how much you care about local dev experience.

Here are your concrete next steps:

  1. Profile your jobs before choosing. Count the average number of steps per job and the average duration. Run those numbers through each tool's pricing calculator β€” the tool that looks cheaper in marketing often isn't for your specific workload.
  2. Test local dev on a real project. Spin up each tool's local environment with an actual job from your codebase, not the hello-world example. The DX differences become obvious within an hour.
  3. Check your hosting provider's timeout limits. If you're on Vercel or another platform with short function timeouts, Inngest's step model or Trigger.dev's managed workers both solve the problem β€” but the Inngest solution requires you to chunk your work, while Trigger.dev handles it transparently.
  4. Evaluate self-hosting requirements early. If your company is likely to need on-premise or private cloud deployment in the next year, Trigger.dev's open-source option gives you a real path. Inngest doesn't.
  5. Start on the free tier with a real workload, not a toy project. Both free tiers are generous enough to run a meaningful pilot β€” use that to validate cost assumptions before upgrading.

Frequently Asked Questions

Can Trigger.dev and Inngest both handle jobs that run longer than the Vercel function timeout?

Yes, but in different ways. Trigger.dev runs your job code in its own managed workers, so Vercel's timeout doesn't apply at all. Inngest breaks work into steps where each step is a separate invocation, which lets you exceed the timeout limit as long as individual steps finish within it.

Is Trigger.dev free to self-host in production?

Trigger.dev is open-source and you can self-host it at no licensing cost, but you're responsible for the infrastructure β€” Docker, a database, and worker nodes. The managed cloud version has a paid free tier with compute-second billing.

How does Inngest's step-based pricing affect high-frequency background jobs?

Every step.run() call inside an Inngest function counts against your step quota. A job with eight steps that runs thousands of times per day can exhaust a free or low-tier plan quickly. Map out your expected step count per job and multiply by daily volume before assuming you're within the free tier.

Which tool is easier to set up for a Next.js project specifically?

Inngest has a purpose-built adapter for Next.js App Router and Pages Router, making setup a matter of adding one API route and registering your functions. Trigger.dev works with Next.js but requires deploying your job code separately, which adds a step to your deployment pipeline.

What happens if a background job fails on both platforms?

Both platforms retry failed jobs automatically with configurable backoff policies. Trigger.dev retries the entire task from the beginning unless you've defined sub-tasks. Inngest retries only the failed step, which means earlier steps in the function don't re-run on retry β€” a meaningful advantage for expensive or side-effect-heavy operations.

πŸ“€ Share this article

Sign in to save

Comments (0)

No comments yet. Be the first!

Leave a Comment

Sign in to comment with your profile.

πŸ“¬ Weekly Newsletter

Stay ahead of the curve

Get the best programming tutorials, data analytics tips, and tool reviews delivered to your inbox every week.

No spam. Unsubscribe anytime.