Skip to content

Quick Start — Node.js

Job definitions and client creation are identical to Next.js — just import from @queuebase/node instead of @queuebase/nextjs.

Terminal window
npm install @queuebase/node zod

Zod is used in this guide, but Queuebase supports any Standard Schema-compatible validation library (Valibot, ArkType, etc.). The CLI runs via npx — no separate install needed.

Create a job router with validated inputs:

src/jobs/index.ts
import { createJobRouter, job } from "@queuebase/node";
import { z } from "zod";
export const jobs = createJobRouter({
sendEmail: job({
input: z.object({
to: z.string().email(),
subject: z.string(),
body: z.string(),
}),
handler: async ({ input, jobId, attempt }) => {
console.info(`[job ${jobId}] Sending email to ${input.to} (attempt ${attempt})`);
// your email sending logic here
return { sent: true };
},
defaults: {
retries: 3,
backoff: "exponential",
},
}),
});
export type JobRouter = typeof jobs;

The handler receives a context object with:

  • input — the validated payload (typed from your schema)
  • jobId — unique identifier for this job execution
  • attempt / maxAttempts — retry tracking (attempts are 1-indexed)
  • fail(reason) — explicitly mark the job as failed

See Defining Jobs for more options.

The client gives you a type-safe way to enqueue jobs:

src/jobs/client.ts
import { createClient } from "@queuebase/node";
import { jobs } from "./index";
export const jobClient = createClient(jobs, {
apiUrl: process.env.QUEUEBASE_API_URL ?? "http://localhost:3847",
apiKey: process.env.QUEUEBASE_API_KEY,
callbackUrl:
process.env.QUEUEBASE_CALLBACK_URL ??
"http://localhost:3000/api/queuebase",
});
  • apiUrl — where the Queuebase API lives. In development, this is the CLI dev server (http://localhost:3847). In production, it’s your hosted Queuebase API.
  • apiKey — authenticates with the production API. Not needed during local development.
  • callbackUrl — the URL Queuebase POSTs to when it’s time to execute a job. This points to the webhook handler you’ll create next.

This is the endpoint Queuebase calls to execute your jobs. createNodeHandler works with Node’s http.IncomingMessage/ServerResponse. It accepts an optional second argument for configuration:

import { createNodeHandler } from "@queuebase/node";
import { jobs } from "./jobs";
const handler = createNodeHandler(jobs);
// Or pass a webhook secret explicitly (overrides QUEUEBASE_WEBHOOK_SECRET env var)
const handler = createNodeHandler(jobs, {
webhookSecret: process.env.MY_WEBHOOK_SECRET,
});

Express parses request bodies as JSON by default. Queuebase needs the raw body for webhook signature verification, so use express.raw() to bypass the parser for this route:

import express from "express";
import { createNodeHandler } from "@queuebase/node";
import { jobs } from "./jobs";
const app = express();
const handler = createNodeHandler(jobs);
app.post("/api/queuebase", express.raw({ type: "*/*" }), (req, res) => {
handler(req, res);
});
import Fastify from "fastify";
import { createNodeHandler } from "@queuebase/node";
import { jobs } from "./jobs";
const fastify = Fastify();
const handler = createNodeHandler(jobs);
fastify.post("/api/queuebase", (req, reply) => {
handler(req.raw, reply.raw);
});

Call .enqueue() from a route handler or anywhere in your server code:

import { jobClient } from "./jobs/client";
app.post("/send-email", async (req, res) => {
const { jobId } = await jobClient.sendEmail.enqueue({
to: req.body.to,
subject: "Welcome",
body: "Hello!",
});
res.json({ jobId });
});

When you call .enqueue(), the SDK validates the input against your schema, sends the job to the Queuebase API, and returns a jobId you can use to check status later. The worker picks up the job and POSTs back to your webhook handler to execute it.

In one terminal, start the Queuebase dev server:

Terminal window
npx queuebase dev

In another terminal, start your app:

Terminal window
node src/index.ts

The Queuebase dev server starts on port 3847, stores jobs in a local SQLite database, and polls for pending jobs to execute.

What you should see: Trigger the enqueue from your app (e.g. hit your /send-email endpoint). The Queuebase CLI should log the job being received and executed. If you added the console.info in step 2, you’ll see the log output in the terminal where your app runs.