---
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

<Steps>

<Step title="Create an organization on Trigger.dev">

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.

</Step>

<Step title="Create a v3 project">

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)

</Step>

<CliInitStep />
<CliDevStep />
<CliRunTestStep />
<CliViewRunStep />

</Steps>

### 2. Migrate your Defer functions to Trigger.dev tasks

#### Example 1: Simple function

In Defer you might have a function like this.

<CodeGroup>

```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();
}
```

</CodeGroup>

In Trigger.dev it looks like this:

<CodeGroup>

```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" });
}
```

</CodeGroup>

<Warning>
  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.
</Warning>

#### 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.

<Card title="Attaching schedules" icon="clock" href="/tasks/scheduled">
  How to attach a schedule to a task
</Card>
