jobs
Run work in the background or on a schedule, with retries when it fails.
What it is
@kitr/jobs runs work in the background. Define a job with defineJob and a typed payload, dispatch it from a controller or action, and the worker runs it with retries, timeouts and an optional schedule.
Runs on the server only. For work that must finish before the response, call the code directly.
Install
kitr add jobsFirst time? Run npm i -g @kitr/kitr once. Inside a project, the global kitr runs your project's own version.
Adds @kitr/jobs, its provider, config/jobs.ts and an example job. Adds server first if missing. Every change.
Quick start
Generate a job with kitr make:job generate-invoice:
// server/jobs/generate_invoice.ts
import { defineJob } from '@kitr/jobs'
import { z } from 'zod'
export const generateInvoice = defineJob('generate_invoice', {
schema: z.object({ teamId: z.string(), month: z.string().regex(/^\d{4}-\d{2}$/) }),
retries: 3,
async run({ teamId, month }, { attempt }) {
// Load the team's usage, render the PDF, store it.
return { invoiceNumber: `INV-${month}-${teamId}`, attempt }
},
})
List it in config/jobs.ts next to the example, then dispatch it from a controller. dispatch() checks the payload, queues the job and resolves with its id straight away:
// server/controllers/invoices_controller.ts
import type { HttpContext } from '@kitr/api'
import { useJobs } from '@kitr/jobs'
import { generateInvoice } from '#server/jobs/generate_invoice'
export default class InvoicesController {
async store({ app, params, response }: HttpContext<{ teamId: string }>) {
const jobId = await useJobs(app).dispatch(generateInvoice, { teamId: params.teamId, month: '2026-10' })
return response.json({ jobId }, { status: 202 })
// => { "jobId": "3f0c9a52-6b1e-4d7a-9a51-0e2f8c1d7b44" }
}
}
The request answers at once with the job id. The worker picks the job up within half a second and retries it up to three times. A bad payload throws before anything is queued. Next in the guide: Dispatch your first job.
Built on
kitr adds the typed payload, retries with backoff, timeouts, cron and interval schedules, a memory queue and a JobsDriver interface for Redis.
Problems it solves
- Slow work inside a request. Dispatch your first job.
- Untyped payloads. Define a job.
- Work that must happen later. Delay a job.
- Nightly and recurring tasks. Run a job on a schedule.
- Flaky third parties. Retry a failing job.
- Jobs that hang. Time out a stuck job.
- One worker competing with web traffic. Run the worker in its own process.