DEV Community

Alex Spinov
Alex Spinov

Posted on

Hatchet Has a Free API — Heres How to Run Distributed Background Jobs

Hatchet is an open-source distributed task queue — think Celery but with durable workflows, retries, rate limiting, and a beautiful dashboard.

Why Hatchet?

  • Durable workflows: Multi-step jobs that survive crashes
  • Rate limiting: Built-in concurrency and rate controls
  • Retries: Automatic retry with exponential backoff
  • Cron jobs: Schedule recurring tasks
  • Dashboard: Real-time monitoring UI
  • TypeScript-first: Full type safety

Quick Setup

npx create-hatchet@latest
# Or self-host:
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

Define a Worker

import Hatchet from '@hatchet-dev/typescript-sdk';

const hatchet = Hatchet.init();

const worker = await hatchet.worker('my-worker');

worker.registerWorkflow({
  id: 'send-email',
  description: 'Send welcome email to new user',
  on: { event: 'user:created' },
  steps: [
    {
      id: 'send',
      run: async (ctx) => {
        const { email, name } = ctx.workflowInput();
        await sendEmail(email, `Welcome, ${name}!`);
        return { sent: true };
      },
    },
  ],
});

await worker.start();
Enter fullscreen mode Exit fullscreen mode

Trigger a Workflow

await hatchet.event.push('user:created', {
  email: 'user@example.com',
  name: 'Alice',
});
Enter fullscreen mode Exit fullscreen mode

Multi-Step Workflows

worker.registerWorkflow({
  id: 'process-order',
  steps: [
    {
      id: 'validate',
      run: async (ctx) => {
        const order = ctx.workflowInput();
        if (!order.items.length) throw new Error('Empty order');
        return { valid: true };
      },
    },
    {
      id: 'charge',
      parents: ['validate'],
      run: async (ctx) => {
        const order = ctx.workflowInput();
        const charge = await stripe.charges.create({ amount: order.total });
        return { chargeId: charge.id };
      },
    },
    {
      id: 'fulfill',
      parents: ['charge'],
      run: async (ctx) => {
        const { chargeId } = ctx.stepOutput('charge');
        await fulfillOrder(ctx.workflowInput().id, chargeId);
        return { fulfilled: true };
      },
    },
  ],
});
Enter fullscreen mode Exit fullscreen mode

Rate Limiting

{
  id: 'call-api',
  rateLimits: [{ key: 'api-calls', units: 1 }],
  run: async (ctx) => {
    return await externalApi.call(ctx.workflowInput());
  },
}
Enter fullscreen mode Exit fullscreen mode

Cron Schedules

worker.registerWorkflow({
  id: 'daily-report',
  on: { cron: '0 9 * * *' },
  steps: [{
    id: 'generate',
    run: async () => {
      const report = await generateDailyReport();
      await sendSlack(report);
    },
  }],
});
Enter fullscreen mode Exit fullscreen mode

Real-World Use Case

An e-commerce startup replaced 500 lines of custom queue code with Hatchet. Order processing went from fragile cron jobs to durable workflows with automatic retries. Failed charges now retry 3 times before alerting support.


Need to automate data collection? Check out my Apify actors for ready-made scrapers, or email spinov001@gmail.com for custom solutions.

Top comments (0)