Overview
Learn about background tasks & cron jobs and how they can power your application.
Background work lets an HTTP request acknowledge an operation before all of its work finishes. Use it for jobs that need retries, scheduling or more execution time than the request path should consume.
Background providers are optional recipes
The starter kits do not install or configure a background-task provider by default. The guides in this section show patterns you can add after choosing a provider. Install only the SDK you plan to operate.
Choose the simplest execution model
| Requirement | Recommended starting point | Why |
|---|---|---|
| The user needs the result immediately | Keep it in the request | The response can report success or failure directly |
| Deliver an HTTP message later or on a schedule | QStash | HTTP delivery, signing and retries fit serverless routes |
| Run durable steps with retries and observability | Trigger.dev, Inngest or Vercel Workflow | The provider records progress outside the request process |
| Run a small recurring operation | A provider schedule that invokes a protected handler | Scheduling remains outside the web process |
| Run a persistent in-process worker | A separately operated worker service | Serverless application instances are not persistent workers |
Do not add a queue only because a function is asynchronous. A short operation that must succeed before the response is often clearer and safer when it stays in the request.
Good background-task candidates
- Generate exports, reports or media after accepting a request.
- Send batches of notifications with provider rate limits.
- Synchronize data with an external service and retry transient failures.
- Process a webhook after its signature and minimum payload are validated.
- Run scheduled cleanup against records that are safe to process repeatedly.
- Execute a durable multi-step workflow where progress must survive a restart.
Keep authentication, authorization decisions and ordinary interactive database queries in the request path. Run schema migrations as a controlled release step, not as a background job.
Design the job before choosing a provider
Every job should define:
- Identity: a stable job or idempotency key.
- Tenant scope: the organization or user that owns the operation.
- Input contract: a small validated payload containing identifiers rather than large or sensitive objects.
- Retry behavior: which failures are transient and how many attempts are safe.
- Completion state: where the application records pending, successful and failed outcomes.
- Operations: logs, alerts and a documented way to replay or cancel work.
Assume every delivery can happen twice
Retries, timeouts and provider redelivery can run the same task more than once. Make writes idempotent with a unique operation key, database constraint or transactional state transition. A queue does not make a non-idempotent operation safe automatically.
Secure the producer and worker
- Authorize the user before publishing a job.
- Derive organization access from the authenticated session instead of trusting an organization ID supplied by the browser.
- Verify provider signatures on public task endpoints.
- Store provider tokens and signing keys as server-only environment variables.
- Re-check permissions in the worker when delayed execution could outlive the user's membership or access.
- Avoid putting access tokens, full customer records or other unnecessary secrets in queue payloads and logs.
Provider guides
These guides are alternatives, not steps that must all be completed:
Trigger.dev
Upstash QStash
Inngest
Vercel Workflow
Start with one provider and one narrow job. Verify success, retry, duplicate delivery and permanent failure paths before moving business-critical work out of the request.