Announcing Trigger.dev v2: the self-hostable background jobs framework for Next.js

Eric AllamEric Allam

Announcing Trigger.dev v2: the self-hostable background jobs framework for Next.js

TL;DR: Trigger.dev v2 is launching soon and you can sign up to get early access here!

In February 2023, our Hacker News post hit the No.1 spot. Since then, we've been gathering feedback from our customers to improve the app and build the best background jobs framework for developers. We're excited to announce Trigger.dev v2, a ground-up rewrite of the platform to be serverless-first, a much simplified architecture that dramatically decreases the complexity of self-hosting, and a more streamlined approach to delivering integrations quickly. We’ve also added some much requested features, like Teams support (to borrow a line from Craig Federighi – We truly live in an age of wonders.)

First-class support for Next.js and serverless

Many of you expressed interest in using Trigger.dev in your Next.js applications, particularly those deployed on serverless platforms like Vercel. Unfortunately, our initial version wasn't configured to support serverless. This time around, we've revamped our architecture to not only support serverless but also optimize it specifically for Next.js developers, enabling them to manage long-running jobs without concern for timeouts in their short-lived functions. Naturally, we're also broadening our support for more platforms, such as Express, in the near future.

So writing a Job in your Next.js app will be as simple as this:


_19
// pages/api/jobs.ts
_19
import { Job, TriggerClient, eventTrigger } from "@trigger.dev/sdk";
_19
import { createHandler } from "@trigger.dev/nextjs";
_19
_19
const client = new TriggerClient({
_19
apiKey: process.env.TRIGGER_API_KEY,
_19
});
_19
_19
client.defineJob({
_19
id: "new-user-created",
_19
name: "New User Created",
_19
version: "1.0.1",
_19
trigger: eventTrigger({ name: "user.created" }),
_19
run: async (payload, io, ctx) => {
_19
// Perform your tasks here
_19
},
_19
});
_19
_19
export default createHandler(client, { path: "/api/jobs" });

Making it easier to host

While we'll be offering a cloud version from day one, we've focused on making it considerably easier to run Trigger.dev locally and self-host it. In response to this, we've reconstructed Trigger.dev, significantly reducing its dependencies. This revision has streamlined deployment into a more straightforward process, thanks to a single service built on top of PostgreSQL. To understand how we've achieved this, check out this Queues in PostgreSQL talk, which illustrates the design changes we've implemented to make self-hosting more accessible.

Making it easier to contribute to

We also made it a lot easier to add new API integrations for any service we don’t already support, as well as for your own APIs. We did this by moving our integration logic almost completely client-side, instead of a mix between client and server side. This will make it much easier to ship more integrations faster.

Here’s a simple diagram of posting a message to a Slack channel using the old system:

trigger v1

Because we moved all integration specific code into the clients, we now expose a general purpose "Task API" that clients can use to provide their executions with idempotency, resumability, and retries. The updated posting a message to a Slack channel would look like this:

trigger v2

A full app refresh

We’ve completely redesigned the app so you have much better visibility into every run. Here’s a little preview of the Run dashboard which displays the full details of a Run, broken up into Tasks, all updating in realtime.

web-app

Team Collaboration made easy

You asked for better collaboration. So, we've added the ability for you to invite your entire team to an organization. Each team member now gets their own local development API key, letting everyone work independently but together.

One more thing

Another common request is that you want to easily add integrations for your users. We agree, so we’re working on "Trigger.dev Connect” which we’ll be releasing during our v2 beta period.

  1. You’ll be able to add our OAuth React button to your app.
  2. Write a Job that will have access to your user’s connected accounts.
  3. Your jobs will get run as your users. You can do webhooks, scheduled jobs or custom events.

For example: add our “Connect to Slack” button to your web app and start sending notifications to your customers when important things happen. Or sync data with their Airtable. Or… you can easily add any integrations to your product.

Lastly, some new vocabulary

We're taking this opportunity to cleanup some of the names for things in Trigger.dev to try and clear up confusion.

  • Workflows become Jobs
  • Jobs have a Trigger
  • Workflow Runs become Job Runs
  • Workflow Steps become Tasks
  • Events stay Events

So this code from our Hello World example:


_15
import { Trigger, customEvent } from "@trigger.dev/sdk";
_15
_15
new Trigger({
_15
// Give your Trigger a stable ID
_15
id: "hello-world",
_15
name: "Template: Hello World",
_15
// Trigger on the custom event named "your.event", see https://docs.trigger.dev/triggers/custom-events
_15
on: customEvent({
_15
name: "your.event",
_15
}),
_15
// The run functions gets called once per "your.event" event
_15
async run(event, ctx) {
_15
await ctx.logger.info("Hello world from inside trigger.dev 10");
_15
},
_15
});

Becomes:


_15
import { Job, customEvent } from "@trigger.dev/sdk";
_15
_15
new Job({
_15
// Give your Job a stable ID
_15
id: "hello-world",
_15
name: "Template: Hello World",
_15
// Trigger on the custom event named "your.event", see https://docs.trigger.dev/triggers/custom-events
_15
trigger: customEvent({
_15
name: "your.event",
_15
}),
_15
// The run functions gets called once per "your.event" event
_15
run: async (event, ctx) => {
_15
await ctx.logger.info("Hello world from inside trigger.dev 10");
_15
},
_15
});

Trigger.dev v2 is launching soon!

These last few months have seen huge progress for our upcoming v2 release, and we're stoked to make Trigger.dev a more developer-friendly platform. By streamlining deployment, hosting, and contributions, we're not just making our lives easier, but also empowering the community to build even cooler stuff. So, let's roll up our sleeves, embrace these changes, and see what awesome things we can create together on Trigger.dev! Visit trigger.dev to get early access to v2 when it’s available.

FAQs

Will I be forced to upgrade?

In short, yes. But migrating will be very straightforward as the syntax is similar to the existing SDK. The current version will also continue to work after we've launched v2. They will run alongside each other and we will provide help for you to migrate if you'd like. We will sunset the existing cloud platform later this year but will give plenty of notice.

Are you only supporting serverless now?

No, you'll be able to use Trigger.dev with a variety of other frameworks, serverless or otherwise, such as Node.js, Remix, and Express, in addition to Next.js.

What are the reliability of requests?

Currently, because of the way requests are performed on the platform-side and not the client side, requests are guaranteed to be attempted exactly once (or retried more than once if they are retried).

Moving requests (now called tasks) fully over to the clients, that guarantee becomes at least once, since there is always a chance the client performs the request but then fails to update the platform, marking the task as complete. We'll be providing tools to clients to prevent duplicate tasks, such as idempotency keys. There's also an idea for how to easily prevent duplicate tasks on the client side through database integrations, but it's an area still being explored.