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
// 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 };
}
});
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
}
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)
});
}
});
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 };
}
});
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)