DEV Community

Alex Spinov
Alex Spinov

Posted on

Trigger.dev Has a Free API — Background Jobs for TypeScript Developers

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
Enter fullscreen mode Exit fullscreen mode
// 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}` };
  },
});
Enter fullscreen mode Exit fullscreen mode

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' } },
]);
Enter fullscreen mode Exit fullscreen mode

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 };
  },
});
Enter fullscreen mode Exit fullscreen mode

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' };
  },
});
Enter fullscreen mode Exit fullscreen mode

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();
  },
});
Enter fullscreen mode Exit fullscreen mode

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)