DEV Community

Alex Spinov
Alex Spinov

Posted on

Trigger.dev Has a Free API: Background Jobs for JavaScript Without Infrastructure

What is Trigger.dev?

Trigger.dev is an open-source background job framework for JavaScript/TypeScript. It replaces complex queue setups (Redis + BullMQ + workers) with a simple SDK that runs long-running tasks reliably — retries, scheduling, and observability included.

Why Trigger.dev?

  • Free tier — 50,000 task runs/month
  • No infrastructure — no Redis, no workers, no queues to manage
  • Serverless-compatible — works with Vercel, Netlify, any platform
  • Built-in retries — automatic retry with exponential backoff
  • Real-time logs — see task execution in a dashboard
  • TypeScript-first — fully typed tasks with Zod schemas

Quick Start

npx trigger.dev@latest init
Enter fullscreen mode Exit fullscreen mode
// trigger/send-email.ts
import { task } from '@trigger.dev/sdk/v3';
import { Resend } from 'resend';

export const sendWelcomeEmail = task({
  id: 'send-welcome-email',
  retry: { maxAttempts: 3 },
  run: async (payload: { email: string; name: string }) => {
    const resend = new Resend(process.env.RESEND_API_KEY);

    await resend.emails.send({
      from: 'hello@myapp.com',
      to: payload.email,
      subject: `Welcome, ${payload.name}!`,
      html: `<h1>Welcome ${payload.name}!</h1>`
    });

    return { sent: true, email: payload.email };
  }
});
Enter fullscreen mode Exit fullscreen mode

Trigger from Your API

// app/api/signup/route.ts
import { sendWelcomeEmail } from '@/trigger/send-email';

export async function POST(req: Request) {
  const { email, name } = await req.json();

  // Create user...
  const user = await db.insert(users).values({ email, name });

  // Trigger background job — returns immediately
  await sendWelcomeEmail.trigger({ email, name });

  return Response.json(user); // User gets instant response
}
Enter fullscreen mode Exit fullscreen mode

Scheduled Tasks (Cron)

import { schedules } from '@trigger.dev/sdk/v3';

export const dailyReport = schedules.task({
  id: 'daily-report',
  cron: '0 9 * * *', // Every day at 9 AM
  run: async () => {
    const metrics = await db.query.metrics.findMany({
      where: gte(metrics.date, yesterday())
    });

    await sendSlackMessage({
      channel: '#reports',
      text: formatDailyReport(metrics)
    });
  }
});
Enter fullscreen mode Exit fullscreen mode

Multi-Step Tasks

export const processOrder = task({
  id: 'process-order',
  run: async (payload: { orderId: string }) => {
    // Step 1: Validate
    const order = await validateOrder(payload.orderId);

    // Step 2: Charge payment
    const payment = await chargePayment(order);

    // Step 3: Send confirmation email
    await sendWelcomeEmail.triggerAndWait({
      email: order.customerEmail,
      name: order.customerName
    });

    // Step 4: Notify warehouse
    await notifyWarehouse(order);

    return { success: true, paymentId: payment.id };
  }
});
Enter fullscreen mode Exit fullscreen mode

Trigger.dev vs Alternatives

Feature Trigger.dev BullMQ Inngest AWS SQS + Lambda
Setup npm install Redis + workers npm install IAM + queues
Free tier 50K runs/mo Self-host 25K runs/mo 1M requests
Dashboard Built-in Bull Board Built-in CloudWatch
Retries Automatic Manual config Automatic DLQ
TypeScript Native Types available Native Manual
Cron Built-in Repeatable jobs Built-in EventBridge

Real-World Impact

An e-commerce app processed orders synchronously: charge payment, send email, update inventory, notify shipping — all in one API call taking 8 seconds. Users waited and sometimes got timeouts. After moving to Trigger.dev: API responds in 200ms, background tasks handle the rest with automatic retries. Cart abandonment dropped 25% because checkout felt instant.


Building reliable background jobs? I help teams implement async task processing. Contact spinov001@gmail.com or explore my data tools on Apify.

Top comments (0)