Jobs
Now that we have covered Tasks and Workflows, we can tie them together with a concept called a Job.
For example, let's say we have a Workflow or Task that describes the logic to sync information from Payload to a third-party system. This is how you'd declare how to sync that info, but it wouldn't do anything on its own. In order to run that task or workflow, you'd create a Job that references the corresponding Task or Workflow.
Jobs are stored in the Payload database in the payload-jobs collection, and you can decide to keep a running list of all jobs, or configure Payload to delete the job when it has been successfully executed.
Queuing a new job
In order to queue a job, you can use the payload.jobs.queue function.
Here's how you'd queue a new Job, which will run a createPostAndUpdate workflow:
In addition to being able to queue new Jobs based on Workflows, you can also queue a job for a single Task:
Where to Queue Jobs
Jobs can be queued from anywhere in your application. Here are the most common scenarios:
From Collection Hooks
The most common place - queue jobs in response to document changes:
From Field Hooks
Queue jobs based on specific field changes:
From Custom Endpoints
Queue jobs from your API routes:
From Server Actions
Queue jobs from Next.js server actions:
Job Options
When queuing a job, you can pass additional options:
Common options
waitUntil- Schedule the job to run at a specific date/time in the futurequeue- Assign the job to a specific queue (defaults to'default')log- Add custom log entries for debugging or trackingreq- Pass the request context for access controloverrideAccess- Skip Jobs access control when set totrue(defaults tofalse)
Check Job Status
After queuing a job, you can check its status:
Job Status Fields
Each job document contains:
Payload increments totalTried after each completed attempt. While the handler runs, Payload automatically renews processingUntil. The claim also gets a processingToken, and worker updates only start while that token still matches and enough lease time remains for the configured safety buffer. If the worker disappears, the lease expires and a later jobs runner call can claim the job again. A crashed worker does not increment totalTried or consume a handler retry.
Access Control
Use Payload's dedicated Jobs APIs and endpoints, such as payload.jobs.*, /run, and /handle-schedules. Calling generic Local API, REST, or GraphQL CRUD directly on payload-jobs is not recommended because it bypasses the job operations and does not run jobs.access.*.
Raw collection create, read, update, and delete access is denied by default. You can adjust these rules through jobsCollectionOverrides. REST, GraphQL, and Local API CRUD run these access rules by default. Set overrideAccess: true only for trusted server-side operations that should bypass them.
The dedicated job operations use jobs.access.queue, run, and cancel. payload.jobs.queue(), run(), runByID(), cancel(), and cancelByID() run these functions by default because their overrideAccess option defaults to false. Set overrideAccess: true to bypass Jobs access control for trusted server-side work. The /run and /handle-schedules endpoints always check jobs.access.run.
Configure access for the dedicated job operations in your Jobs Config:
These functions receive the current req and return a boolean. By default, they allow authenticated users.
Omit overrideAccess or pass overrideAccess: false to run them from the Local API:
Cancelling Jobs
Payload allows you to cancel jobs that are either queued or currently running. When cancelling a running job, the current task will finish executing, but no subsequent tasks will run. This happens because the job checks its cancellation status between tasks.
To cancel a specific job, use the payload.jobs.cancelByID method with the job's ID:
To cancel multiple jobs at once, use the payload.jobs.cancel method with a Where query:
From within a task or workflow handler, you can also cancel the current job by throwing a JobCancelledError:
Was this page helpful?