--- title: "Migrating from Defer.run" description: "A guide to migrating from Defer to Trigger.dev v3" --- import CliInitStep from '/snippets/step-cli-init.mdx'; import CliDevStep from '/snippets/step-cli-dev.mdx'; import CliRunTestStep from '/snippets/step-run-test.mdx'; import CliViewRunStep from '/snippets/step-view-run.mdx'; This guide highlights the differences between Defer and Trigger.dev and should help you migrate your project. ## Differences #### Local development In Defer you run your tasks locally using `npm run dev` (or other package manager). This is simple but it means dev behaved differently from production for your background tasks. With Trigger.dev you need to use our CLI to run a local server that behaves like the deployed production environment. It also means you will see your runs in the dashboard. #### Multiple tasks in a single file In Defer you needed to use a default export in a file inside your `/defer` directory. ```ts /defer/longRunningTask.ts import { defer } from "@defer/client"; async function longRunningTask() { // runs a fake task for 30s await performLongRunningTask(); } export default defer(longRunningTask); ``` In Trigger.dev **you use named exports** so you can have multiple tasks in a single file. ```ts /trigger/someTasks.ts export const longRunningTask = task({ id: "longRunningTask", run: async (payload: any) => { //...do stuff }, }); export const otherTask = task({ id: "otherTask", run: async (payload: any) => { //...do different stuff }, }); ``` #### Triggering your tasks In Defer, you wrapped your existing function in `defer()`. Then for simple cases you could just call the function. In other cases, like when you wanted to have a delay you needed to use `assignOptions` to create a new function. ```ts /app/actions/actions.ts "use server"; import longRunningTask from "@/defer/longRunningTask"; export async function runLongRunningTask() { return await longRunningTask(); } ``` In Trigger.dev your logic goes in the `run` function of a task. You can then `trigger` and `batchTrigger` that task, with a payload as the first argument. ```ts /app/actions/actions.ts "use server"; import { longRunningTask } from "@/trigger/someTasks"; export async function runLongRunningTask() { return await longRunningTask.trigger({ foo: "bar" }); } ``` #### `wait` In Trigger.dev you can use the [wait](/wait) functions to freeze execution of your code until a later date (it can be months later). You won't pay while it's frozen and the state is restored exactly when it wakes (using a technology called CRIU). ```ts //In Defer you could use "sleep" but that would keep your function running. await sleep(1000 * 60 * 5); // 5 minutes but you'd pay for it. //In Trigger.dev you can use wait. We freeze execution if it's more than 30s await wait.for({ seconds: 5 }); await wait.for({ minutes: 10 }); await wait.for({ hours: 1 }); await wait.for({ days: 1 }); await wait.for({ weeks: 1 }); await wait.for({ months: 1 }); await wait.for({ years: 1 }); //you can wait for a date too await wait.until({ date: aFutureDate }); ``` #### delay the start of a run In Defer you can do this: ```ts const delayedRun = assignOptions(someTask, { delay: "10s" }); await delayedRun(); ``` There will be a nice way to do this soon when you call `trigger()` but for now you can use `wait` to get the same behavior: ```ts export const helloWorld = task({ id: "hello-world", run: async (payload: { delayUntil?: string; delayForSeconds?: number }) => { if (payload.delayUntil) { await wait.until({ date: new Date(payload.delayUntil) }); } if (payload.delayForSeconds) { await wait.for({ seconds: payload.delayForSeconds }); } //do stuff }, }); ``` ## How to migrate ### 1. Get Trigger.dev working in your project 1. Go to the [Trigger.dev Cloud](https://cloud.trigger.dev) 2. Create an account 3. Create an organization with a project (this will be a version 2 project) 4. [DM us on Discord](https://trigger.dev/discord) or [fill in this form](https://trigger.dev/v3-early-access) and mention Defer in the company name. We will grant you v3 access. 1. Go to the Projects page ![Click the Projects page](/images/sidemenu-projects.png) 2. Click "Create a new project" ![Click "Create a new project"](/images/projects-new-button.png) 3. If the "Project version" dropdown is visible, make sure you select "Version 3"! ![Select "Version 3"](/images/projects-new-v3.png) ### 2. Migrate your Defer functions to Trigger.dev tasks #### Example 1: Simple function In Defer you might have a function like this. ```ts /defer/longRunningTask.ts import { performLongRunningTask } from "@/utils/performLongRunningTask"; import { defer } from "@defer/client"; async function longRunningTask() { // runs a fake task for 30s await performLongRunningTask(); } export default defer(longRunningTask, { concurrency: 2, // want maximum 2 executions of this function in parallel retry: 5, // adding retry to recover from potential network issues or rate limiting }); ``` ```ts /app/actions/actions.ts "use server"; import longRunningTask from "@/defer/longRunningTask"; export async function runLongRunningTask() { return await longRunningTask(); } ``` In Trigger.dev it looks like this: ```ts /trigger/someTasks.ts import { performLongRunningTask } from "@/utils/performLongRunningTask"; import { task } from "@trigger.dev/sdk"; //named export export const longRunningTask = task({ //a unique and stable ID so you can refactor the function name id: "long-running-task", queue: { concurrencyLimit: 2, // want maximum 2 executions of this function in parallel }, retry: { maxAttempts: 5, // adding retry to recover from potential network issues or rate limiting }, run: async (payload: any) => { // runs a fake task for 30s await performLongRunningTask(); }, }); ``` ```ts /app/actions/actions.ts "use server"; import { longRunningTask } from "@/trigger/longRunningTask"; export async function runLongRunningTask() { return await longRunningTask.trigger({ foo: "bar" }); } ``` You need to set your `TRIGGER_SECRET_KEY` environment variable in your `.env` or `.env.local` file to trigger tasks from your code. See the [API keys page](/apikeys) for more information. #### Example 2: A cron task We call these [scheduled tasks](/tasks/scheduled) in Trigger.dev. In Defer you might have a function like this: ```ts import { defer } from "@defer/client"; async function sendMondayNewletter() { // business logic here } export default defer.cron(sendMondayNewletter, "0 0 * * 1"); ``` In Trigger.dev the task looks like this: ```ts import { schedules } from "@trigger.dev/sdk"; //this task will run when any of the attached schedules trigger export const sendMondayNewletter = schedules.task({ id: "send-monday-newsletter", run: async (payload) => { // business logic here }, }); ``` Then you need to attach a schedule to the task, either using the dashboard or in your code. You can attach unlimited schedules to a task. How to attach a schedule to a task