Trigger.dev is a background job framework for TypeScript. Long-running tasks, scheduled jobs, webhooks, and event-driven workflows — with full observability and zero infrastructure.
Why Trigger.dev?
- TypeScript-native — write jobs in TypeScript with full type safety
- Serverless — runs on their infra or self-hosted
- Durable execution — jobs survive crashes and restarts
- Dashboard — real-time monitoring, logs, retries
Quick Start
npx trigger.dev@latest init
// src/trigger/example.ts
import { task } from '@trigger.dev/sdk/v3';
export const helloWorld = task({
id: 'hello-world',
run: async (payload: { name: string }) => {
console.log(`Hello, ${payload.name}!`);
return { message: `Processed ${payload.name}` };
},
});
Trigger from Your App
import { tasks } from '@trigger.dev/sdk/v3';
// Trigger and forget
await tasks.trigger('hello-world', { name: 'Alice' });
// Trigger and wait for result
const result = await tasks.triggerAndPoll('hello-world', { name: 'Bob' });
console.log(result.output); // { message: 'Processed Bob' }
// Batch trigger
await tasks.batchTrigger('hello-world', [
{ payload: { name: 'Alice' } },
{ payload: { name: 'Bob' } },
{ payload: { name: 'Charlie' } },
]);
Scheduled Jobs (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 fetchDailyMetrics();
await sendSlackMessage(formatReport(metrics));
return { sent: true };
},
});
Long-Running Tasks with Steps
import { task, wait } from '@trigger.dev/sdk/v3';
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: Wait for fulfillment
await wait.for({ minutes: 5 });
// Step 4: Send confirmation
await sendConfirmation(order, payment);
return { status: 'completed' };
},
});
Retry Configuration
export const unreliableTask = task({
id: 'unreliable-api-call',
retry: {
maxAttempts: 5,
factor: 2,
minTimeoutInMs: 1000,
maxTimeoutInMs: 30000,
},
run: async (payload) => {
const response = await fetch('https://unreliable-api.com/data');
if (!response.ok) throw new Error('API failed');
return response.json();
},
});
Need background scraping jobs? Check out my Apify actors for scheduled web scraping, or email spinov001@gmail.com for custom job pipelines.
Trigger.dev, Inngest, or BullMQ — how do you handle background jobs? Share below!
Top comments (0)