Trigger.dev vs Inngest for Next.js Background Jobs

· Tutorials

Real Trigger.dev v3 setup walkthrough after testing Inngest, Temporal, and DBOS. Code snippets, pricing comparison, and when to pick which one.

Last updated: August 6, 2025 · 9-minute read

I spent two weeks testing every background job solution for Next.js before picking one. Trigger.dev won — not because it's the best at everything, but because it's the best at the specific thing I needed: running long AI tasks inside a Next.js app without spinning up a separate backend.

The r/ExperiencedDevs thread "Does anyone here use dbos.dev or trigger.dev?" had a response that captured the landscape well: "If you can leverage long-running tasks on Inngest or Trigger.dev, there's no need to move to a separate backend." That's the thesis. Here's the proof.

The Contenders

I tested four options for my use case (AI-powered background tasks in Next.js):

Trigger.dev v3 — Open-source, TypeScript-native, supports self-hosting or managed cloud. Long-running tasks with retries, queues, observability. Built specifically for Next.js/Remix/Astro. Free tier includes $5/month usage credit and 20 concurrent runs.

Inngest — Event-driven durable execution platform. Great DX for event-driven architectures. Not open-source — you're locked into their cloud. Free tier is generous but pricing scales linearly with volume.

Temporal — The enterprise heavyweight. Battle-tested at scale (used by Stripe, Netflix). But it requires running your own worker fleet, starts at $100/month for Temporal Cloud, and the learning curve is steep. Overkill for anything under 100K workflow runs/month.

DBOS — Database-oriented orchestration. Interesting concept (workflows as database transactions) but small community and limited Next.js integration. I couldn't find enough documentation to get a production setup running in under a day.

Why Trigger.dev Won for My Use Case

Three reasons, all specific to what I'm building:

1. Long-running AI tasks. My NoteCanvas app runs AI summarization and transcription tasks that take 30 seconds to 5 minutes. Vercel's serverless functions timeout at 10-60 seconds. Trigger.dev handles tasks up to 5 hours on the $20 plan. Inngest caps at shorter durations on lower tiers.

2. Self-hosting option. I don't want to be locked into a pricing model I can't control. Trigger.dev is 100% open-source — I can run it on my own infrastructure if the cloud pricing stops making sense. Inngest is cloud-only.

3. Next.js integration. Trigger.dev was built for Next.js. The API routes, the dev server, the deployment — everything works without configuration gymnastics. Adding @trigger.dev/nextjs and wrapping my API routes is a 10-minute setup.

The r/node thread "Long running concurrent jobs" compared Inngest vs Trigger.dev pricing directly. The consensus: "Inngest and Trigger.dev grow linearly with volume. BullMQ stays cheap because there is no per-run pricing." Fair point — if you're doing millions of simple jobs, BullMQ on Redis is cheaper. But for complex, long-running AI workflows with retries and observability, the managed platforms save more in development time than they cost in runtime.

The Real Setup

Here's the actual code I'm running in production. This handles AI-powered transcription in my TalkDrive pipeline.

Step 1: Install

Step 2: Create a Trigger Project

This creates a trigger.config.ts file and registers your project with the Trigger.dev cloud (or points to your self-hosted instance).

Step 3: Define a Job

Create a file at src/jobs/transcribe.ts:

export const transcribeAudio = task({ id: "transcribe-audio", retry: { maxAttempts: 3, minTimeoutInMs: 1000, maxTimeoutInMs: 30000, }, maxDuration: 300, // 5 minutes run: async (payload: { audioUrl: string; episodeId: string }) = { // Fetch audio from URL const response = await fetch(payload.audioUrl); const audioBuffer = await response.arrayBuffer();

// Process with your AI transcription service const transcription = await processWithWhisper(audioBuffer);

// Save results to your database await saveTranscription(payload.episodeId, transcription);

return { success: true, episodeId: payload.episodeId }; }, });

Step 4: Trigger from an API Route

export async function POST(request: Request) { const { audioUrl, episodeId } = await request.json();

// This fires the job and returns immediately const result = await transcribeAudio.trigger({ audioUrl, episodeId, });

return Response.json({ jobId: result.id, status: "queued" }); }

Step 5: Run the Dev Server

This starts a local dev server that processes jobs. In production, Trigger.dev's cloud handles the execution.

Pricing That Actually Matters