obsidian/wiki/payloadcms/jobs-queue.md
2026-05-15 16:14:29 +01:00

4.4 KiB

title aliases tags sources created updated
Jobs Queue — Overview
payload-jobs-queue
jobs-queue-overview
payload-background-jobs
payloadcms
jobs-queue
background-tasks
scheduling
workers
raw/jobs-queue__overview.md
2026-05-15 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

// 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
// WRONG: duplicate scheduling — both handle schedules for same queue
pnpm payload jobs:handle-schedules --cron "* * * * *"
// + autoRun without disableScheduling: true → duplicate jobs queued
// FIX: autoRun run-only mode
autoRun: [{ cron: '* * * * *', queue: 'emails', disableScheduling: true }]

Expose Jobs in Admin UI

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