---
title: "Jobs Queue — Overview"
aliases: [payload-jobs-queue, jobs-queue-overview, payload-background-jobs]
tags: [payloadcms, jobs-queue, background-tasks, scheduling, workers]
sources: [raw/jobs-queue__overview.md]
created: 2026-05-15
updated: 2026-05-15
---

## What It Is

Payload's Jobs Queue offloads long-running, expensive, or future-scheduled work from your main API server to separate compute resources.

## Core Concepts

| Concept | Description |
|---------|-------------|
| **Task** | A specific function with business logic (`handler: async () => {}`) |
| **Workflow** | Ordered grouping of tasks; retryable from the exact failure point |
| **Job** | A single instance of a task or workflow queued for execution |
| **Queue** | Named segment that groups jobs (e.g. `emails`, `nightly`) |

## Use Cases

**Non-blocking hooks**
- Vector embeddings on document change
- Sending data to third-party APIs
- Triggering emails from customer actions

**Scheduled actions** (via `waitUntil`)
- Publish/unpublish posts at a future time
- Trial reminder emails after X days

**Periodic sync** (via cron)
- Nightly rebuild of frontend
- Off-peak third-party API sync

**Offloading heavy compute**
- Open-source embedding models (keep out of Next.js bundle via dynamic import)
- PDF generation, headless browser tasks
- Durable multi-step pipelines

## How Jobs Flow

```
Define Task → Queue Job → Stored in DB → Run Job → Task executes → Complete/Retry
```

Scheduling is **two-part**: defining a `schedule` in config is passive; you must also actively execute `handleSchedules` to queue jobs.

## Running Jobs — 4 Options

| Option | When to Use |
|--------|-------------|
| `pnpm payload jobs:run --cron "* * * * *"` | Dedicated server (recommended — separate process) |
| `autoRun: [{ cron, queue }]` | Dedicated server (runs within Next.js, handles both scheduling + running) |
| `GET /api/payload-jobs/run?queue=emails` | Serverless (triggered by Vercel Cron, GitHub Actions) |
| `payload.jobs.run({ queue })` | Manual / programmatic |

## Scheduling Jobs — 3 Options

| Option | When to Use |
|--------|-------------|
| `pnpm payload jobs:handle-schedules --cron "* * * * *"` | Dedicated server bin script |
| `GET /api/payload-jobs/handle-schedules?queue=emails` | Serverless |
| `autoRun` (default — also calls `handleSchedules`) | Dedicated server only |

## Key Takeaways

- **Scheduling ≠ Running** — two separate independent steps; the `queue` name must match between them
- **Jobs persist in DB** between queuing and execution — track status, retries, errors there
- **`autoRun` is dual-purpose** by default: it both queues scheduled jobs AND runs queued jobs; set `disableScheduling: true` to run only
- **Never use `autoRun` on serverless** (Vercel, Lambda) — use API endpoints + external cron instead
- **Avoid duplicate scheduling**: don't use `handle-schedules` bin script AND `autoRun` for the same queue simultaneously
- **Dynamic imports** in Task handlers keep large dependencies out of the main Next.js bundle
- **Admin UI visibility**: `payload-jobs` collection is hidden by default — use `jobsCollectionOverrides` to expose for debugging

## Common Pitfalls

```ts
// WRONG: schedule defined but never executed
export const EmailTask: TaskConfig = {
  slug: 'sendEmail',
  schedule: [{ cron: '0 8 * * *', queue: 'emails' }], // passive only!
  handler: async () => { /* ... */ },
}
// Must add: bin script, API endpoint, OR autoRun
```

```ts
// WRONG: duplicate scheduling — both handle schedules for same queue
pnpm payload jobs:handle-schedules --cron "* * * * *"
// + autoRun without disableScheduling: true → duplicate jobs queued
```

```ts
// FIX: autoRun run-only mode
autoRun: [{ cron: '* * * * *', queue: 'emails', disableScheduling: true }]
```

## Expose Jobs in Admin UI

```ts
jobs: {
  jobsCollectionOverrides: ({ defaultJobsCollection }) => {
    defaultJobsCollection.admin = { hidden: false }
    return defaultJobsCollection
  },
}
```

## Related Articles

- [[wiki/payloadcms/jobs-queue-jobs|Jobs Queue — Jobs Detail]] — queuing from hooks, `waitUntil`, job status schema, access control, cancellation
- [[wiki/payloadcms/hooks|PayloadCMS — Hooks]] — how to queue jobs from afterChange/afterOperation hooks
- [[wiki/payloadcms/configuration|Payload Config — Overview]] — `autoRun` and bin script config in `buildConfig`
- [[wiki/payloadcms/production|Production & Performance]] — deployment patterns for dedicated vs serverless workers
