---
title: "Send an email sequence"
description: "Send onboarding and drip email as a durable sequence of delayed steps, started on sign-up and cancellable at any point."
canonical_url: "https://nuxt-backend.dev/docs/email/engagement/sequences"
---
# Send an email sequence

> Send onboarding and drip email as a durable sequence of delayed steps, started on sign-up and cancellable at any point.

A sequence is a [workflow](https://nuxt-backend.dev/docs/data/jobs/workflows) whose steps send email: each one sleeps its delay durably, survives restarts and deploys, and sends through the backend component, so every message is delivery-tracked.

The scaffolded `backend/workflows.ts` — as generated, with its commented second step filled in — is an onboarding drip built with `defineEmailSequence(workflow, components, { args, steps })`:

```ts [backend/workflows.ts]
import { defineEmailSequence, setupWorkflows } from 'nuxt-backend/workflows'
import { v } from 'convex/values'
import { components } from './_generated/api'

export const workflow = setupWorkflows(components)

// Runs once on signup (started from auth.ts's onUserCreated).
export const onSignup = defineEmailSequence(workflow, components, {
  args: { userId: v.string(), email: v.string(), name: v.string() },
  steps: [
    // The packaged welcome email goes out at signup; the sequence follows up.
    {
      after: 3 * 24 * 60 * 60 * 1000, // three days later
      email: ({ email, name }) => ({
        to: email,
        subject: 'How is it going?',
        text: `Hi ${name}, you signed up three days ago. Reply to this email if anything is in your way.`,
      }),
    },
  ],
})
```

Each step is `{ after, email }`. `after` is the delay in milliseconds from the previous step, slept durably through the workflow component — it survives restarts and deploys. `email(data)` receives the workflow's args and returns `{ to, subject, html?, text? }`, or `null` to skip the step (the user already activated, the nudge is moot). Every message goes through the backend component's email module, so it is delivery-tracked like any other [send](https://nuxt-backend.dev/docs/email/sending). Cancel a running sequence with `workflow.cancel(ctx, id)`; `EmailSequenceStep<Data>` is exported for steps you build elsewhere.

## Start it on sign-up

The scaffolded `backend/auth.ts` starts the sequence from `setupAuth`'s `onUserCreated` hook. The packaged welcome email always goes out at signup, so the sequence starts with what comes after it:

```ts [backend/auth.ts]
import { workflow } from './workflows'

export const { authComponent, createAuth, getAuthUser /* … */ } = setupAuth(components, query, {
  email,
  rateLimiter,
  onUserCreated: async (ctx, user) => {
    await workflow.start(ctx, internal.workflows.onSignup, {
      userId: user.id, email: user.email, name: user.name,
    })
  },
})
```

<tip>

The `ctx` passed to `onUserCreated` is a full mutation/action ctx, so it can start a Workflow directly. See [cross-component wiring](https://nuxt-backend.dev/docs/auth/setup#cross-component-wiring).

</tip>


## Sitemap

See the full [sitemap](https://nuxt-backend.dev/sitemap.md) for all pages.
