---
title: Scheduled jobs
description: Code that runs on a schedule, from an app's jobs/ folder.
section: Server
order: 6
---

# Scheduled jobs

<p class="lead">A job runs on a schedule, such as every night at two or every Monday, with the same server API as the rest of your code. There is no cron, queue or worker to set up.</p>

```js title="jobs/tidy-drafts.js"
export const schedule = "0 6 * * 1-5";   // weekdays at 06:00 UTC

export default async function (ctx) {
  const stale = await ctx.collection("drafts").list({ filter: "updated < @days_ago.30" });
  // tidy up, send the digest, close the day
}
```

- One file per job in `jobs/`, beside `functions/`.
- Nothing in `jobs/` is served over HTTP. A job runs when the clock says, never when somebody calls it.
- A job runs as the system, with the same `ctx` a [server function](/docs/server-functions) gets, and `CRON` as its method.

## The schedule

Five fields of standard cron, in UTC: minute, hour, day of month, month, day of week (`0` is Sunday).

| | |
|---|---|
| `0 2 * * *` | Every night at two |
| `*/15 * * * *` | Every quarter of an hour |
| `0 8 * * 1` | Mondays at eight |
| `0 9 1 * *` | The first of each month |
| `@hourly`, `@daily`, `@weekly`, `@monthly` | As they say |

`*`, `*/n`, `a-b`, `a-b/n` and lists all work. The schedule is read from the file's text, so listing jobs never runs an app's code.

## How they run

- Every minute, whatever matches it runs.
- One run of a job at a time: if the last one is still going, the next is skipped.
- A server that was down doesn't catch up on the minutes it missed, as with cron.

The admin UI's **Jobs** lists every job, when it last ran and how that went, and runs one now for trying it out. Backups are a job there too: off until given a schedule and how many to keep.
