Quick Start
Build your first crash-safe background job in 2 minutes
Quick Start
This guide walks you through the three most common OqronKit patterns — a simple task queue, a distributed worker, and a cron schedule.
1. Bootstrap OqronKit
First, define your background triggers. Then, instantiate Oqron and call start(). OqronKit reads your definitions globally and enables the corresponding engines automatically.
import { Oqron } from "oqronkit";
// Import your definition files so they are registered before start:
import "./jobs/email-queue.js";
import "./jobs/billing.js";
import "./jobs/crons.js";
const oqron = new Oqron({
mode: "memory", // Use 'redis' or 'redis-postgres' in production
});
await oqron.start();In production, add a backend and identify your deployment — project scopes all state (services sharing queues must share it), environment separates stages on shared infrastructure:
const oqron = new Oqron({
mode: "redis-postgres",
redis: process.env.REDIS_URL!,
postgres: process.env.DATABASE_URL!,
project: "shop",
environment: process.env.NODE_ENV ?? "development",
});2. Simple Task Queue
The fastest way to get started. Publisher and consumer live in the same process.
import { Queue } from "oqronkit";
export const emailQueue = Queue<{ to: string; body: string }>({
name: "send-email",
handler: async (ctx) => {
console.log("Sending email to:", ctx.data.to);
await sendEmail(ctx.data.to, ctx.data.body);
return { sent: true };
},
});
// Enqueue a job (can be called anywhere after module execution)
await emailQueue.add({
to: "user@example.com",
body: "Welcome to OqronKit!",
});3. Distributed Worker
For production — separate your API servers (senders) from your worker servers (processors).
import { Queue, Worker } from "oqronkit";
// Publisher-only queue (no handler) — lives on API nodes
export const billingQueue = Queue<{ userId: string; amount: number }>({
name: "billing",
});
// Consumer-only worker — lives on worker nodes
export const billingWorker = Worker<{ userId: string; amount: number }>({
topic: "billing",
handler: async (ctx) => {
await chargeBilling(ctx.data.userId, ctx.data.amount);
return { charged: true };
},
});// Push a job from your API route
import { billingQueue } from "./jobs/billing.js";
app.post("/api/charge", async (req, res) => {
await billingQueue.add({ userId: req.body.userId, amount: 99 });
res.json({ status: "queued" });
});4. Cron Schedule
Run background jobs on a schedule.
import { Cron } from "oqronkit";
export const cleanup = Cron({
name: "daily-cleanup",
expression: "0 0 * * *", // Every day at midnight
timezone: "America/New_York",
handler: async (ctx) => {
const deleted = await db.deleteOldRecords();
ctx.log.info(`Cleaned up ${deleted} records`);
},
});5. Production Touches
Three options turn the examples above production-grade:
Cron({
name: "nightly-billing",
expression: "0 0 * * *",
durable: true, // crash-safe fires: each slot becomes a
// deduplicated job with retries + reclaim
retries: { max: 3, strategy: "exponential", baseDelay: 5_000 },
environments: ["production"], // never fires in dev/staging deployments
handler: runBilling,
});durable: true— a crash mid-handler is retried on another node instead of lost. Use for billing, emails, data mutations. (Scheduler → Durable fires)environments— the definition is inert outside the listed environments; works on every module. (Environments)retries+ dead letters — exhausted retries land in an inspectable, resendable DLQ. (Crash Safety)