DEV Community

Alex Spinov
Alex Spinov

Posted on

Inngest Has a Free API: Serverless Functions With Built-In Queuing and Orchestration

You need a background job. So you set up Redis, Bull, a worker process, retry logic, monitoring... Inngest replaces all of that.

What Is Inngest?

Inngest is a serverless queue and workflow engine. Send events, Inngest runs functions — with retries, scheduling, concurrency control, and step functions built in.

import { Inngest } from "inngest"

const inngest = new Inngest({ id: "my-app" })

// Define a function triggered by an event
export const sendWelcomeEmail = inngest.createFunction(
  { id: "send-welcome-email", retries: 3 },
  { event: "user/signup" },
  async ({ event, step }) => {
    // Step 1: Get user details
    const user = await step.run("get-user", async () => {
      return await db.user.findUnique({ where: { id: event.data.userId } })
    })

    // Step 2: Wait 1 hour (Inngest handles the timer)
    await step.sleep("wait-before-email", "1h")

    // Step 3: Send email
    await step.run("send-email", async () => {
      await emailService.send({
        to: user.email,
        template: "welcome",
        data: { name: user.name }
      })
    })

    // Step 4: Update database
    await step.run("mark-sent", async () => {
      await db.user.update({
        where: { id: user.id },
        data: { welcomeEmailSent: true }
      })
    })
  }
)
Enter fullscreen mode Exit fullscreen mode

Trigger It

// From your API route
await inngest.send({
  name: "user/signup",
  data: { userId: "user_123", plan: "pro" }
})
// Returns immediately — function runs in background
Enter fullscreen mode Exit fullscreen mode

Key Features

1. Step functions — each step.run() is checkpointed. If step 3 fails, it retries from step 3, not step 1.

2. Sleep/waitstep.sleep("1h") actually pauses for 1 hour without consuming resources.

3. Concurrency control:

inngest.createFunction(
  { id: "process-upload", concurrency: { limit: 5 } },  // Max 5 concurrent
  { event: "file/uploaded" },
  handler
)
Enter fullscreen mode Exit fullscreen mode

4. Fan-out:

const results = await step.invoke("process-batch", {
  function: processItem,
  data: items.map(item => ({ item }))
})
Enter fullscreen mode Exit fullscreen mode

5. Cron:

inngest.createFunction(
  { id: "daily-report" },
  { cron: "0 9 * * *" },  // Every day at 9 AM
  handler
)
Enter fullscreen mode Exit fullscreen mode

Free Tier

  • 25K function runs/month
  • Unlimited functions
  • 7-day event history

Building background jobs? Check out my developer tools or email spinov001@gmail.com.

Top comments (0)