Skip to content

Defining Jobs

Use job() to define a job and createJobRouter() to group them into a router. The input field accepts any Standard Schema-compatible library — Zod, Valibot, ArkType, and others.

import { createJobRouter, job } from "@queuebase/nextjs"; // or @queuebase/node
import { z } from "zod"; // or valibot, arktype, etc.
export const jobs = createJobRouter({
myJob: job({
input: z.object({ /* your schema */ }),
handler: async (ctx) => { /* returns output */ },
defaults: { /* optional EnqueueOptions */ },
}),
});

The handler receives a JobContext object:

FieldTypeDescription
inputInferred from schemaValidated input data
jobIdstringUnique job ID
attemptnumberCurrent attempt (1-indexed)
maxAttemptsnumberMaximum attempts allowed
fail(reason: string) => neverExplicitly fail the job
handler: async ({ input, jobId, attempt, maxAttempts }) => {
console.log(`Job ${jobId}, attempt ${attempt}/${maxAttempts}`);
// use input (fully typed from your schema)
return { success: true };
}

Call ctx.fail() to immediately mark a job as failed with a reason. This throws a JobFailureError internally, so any code after it won’t run.

handler: async ({ input, fail }) => {
const user = await findUser(input.userId);
if (!user) {
fail("User not found");
}
// this only runs if user exists
await sendEmail(user.email);
return { sent: true };
}

This is useful when a job should fail for a business logic reason rather than an unexpected exception. The failure reason is recorded on the job and visible in the dashboard.

You can set default enqueue options per job via the defaults field. These are merged with (and overridden by) options passed to .enqueue().

sendEmail: job({
input: z.object({ to: z.string().email() }),
handler: async ({ input }) => {
// ...
return { sent: true };
},
defaults: {
retries: 3,
backoff: "exponential",
backoffDelay: 2000,
},
}),

See Enqueueing Jobs for the full list of options.

Jobs with an empty input schema can define a schedule to run automatically on a cron schedule:

cleanupExpired: job({
input: z.object({}),
handler: async () => {
// runs every hour
return { cleaned: true };
},
schedule: "every hour",
}),

Schedules accept plain English strings ("every day at 9am"), raw cron expressions ("0 9 * * *"), or a config object for full control over timezone and overlap behavior. See Scheduled Jobs for details.