# Workflow

Generate a background [workflow](/workflows) in `src/lib/workflows`, with a server test next to it.

### Syntax

```
$ vela generate workflow <name> [--cron <schedule>]
```

```
$ vela generate workflow send-welcome-email
```

### Options

- `--cron <schedule>` - Run on a schedule, given as a five-field cron expression

### What it writes

```
src/lib/workflows/send-welcome-email.ts
src/lib/workflows/send-welcome-email.server.test.ts
```

The name can be written as `send-welcome-email`, `sendWelcomeEmail` or `send_welcome_email`; the file and the workflow's registered name use the kebab-case form, and the export is camelCase. The generated workflow takes an empty input schema and has one step to fill in:

```ts
import { z } from 'zod';
import { ow } from '$lib/server/workflows';

export const sendWelcomeEmail = ow.defineWorkflow(
	{
		name: 'send-welcome-email',
		// What `run()` takes, checked before the run is queued.
		schema: z.object({}),
		retryPolicy: { maximumAttempts: 3 }
	},
	async ({ input, step }) => {
		const result = await step.run({ name: 'first-step' }, async () => {
			return input;
		});
		return result;
	}
);
```

Start it from server code with `sendWelcomeEmail.run(input)`. The test starts a worker in the test process, runs the workflow and waits for its result, so [`vela test:server`](/test/server) exercises it end to end.

### Recurring

```
$ vela generate workflow sync-prices --cron '*/5 * * * *'
```

A recurring workflow takes no input and its file exports the schedule. Every workflow defined in that file runs on it, once per minute at most and once across all servers; `syncPrices.run()` starts an extra run at any time.

The project has to have the workflow runtime — every project created with Vela does, and [`vela enable workflows`](/enable/workflows) adds it to one created earlier.