Skip to content

Background Jobs

The Booking Kit uses background jobs for tasks that shouldn’t block the request/response cycle: sending emails, syncing calendars, auto-rejecting overdue bookings.

interface JobAdapter {
enqueue(jobName: string, payload: unknown, options?: { delay?: number }): Promise<void>;
scheduleAt(jobName: string, payload: unknown, runAt: Date): Promise<void>;
}
Job namePurpose
send-confirmation-emailSend booking confirmation email
send-reminder-emailSend pre-appointment reminder
send-cancellation-emailSend cancellation notice
send-reschedule-emailSend reschedule notice
auto-reject-pendingReject pending bookings past deadline
sync-to-calendarCreate/update calendar event
delete-from-calendarRemove cancelled calendar event
Terminal window
npm install inngest

Create the API route at app/api/inngest/route.ts:

import { serve } from "inngest/next";
import { inngest } from "@/lib/inngest/client";
import { bookingFunctions } from "@/lib/inngest/functions";
export const { GET, POST, PUT } = serve({
client: inngest,
functions: bookingFunctions,
});
import { inngest } from "./client";
import { sendConfirmationEmail } from "@thebookingkit/core";
export const handleBookingCreated = inngest.createFunction(
{ id: "send-confirmation" },
{ event: "booking/created" },
async ({ event, step }) => {
await step.run("send-email", async () => {
await sendConfirmationEmail(event.data, emailAdapter);
});
await step.run("sync-calendar", async () => {
await syncBookingToCalendar(event.data, calendarAdapter);
});
},
);
INNGEST_EVENT_KEY=your-event-key
INNGEST_SIGNING_KEY=your-signing-key # Production only
import { Queue, Worker } from "bullmq";
const bookingQueue = new Queue("bookings", { connection: redis });
// JobAdapter implementation
const bullMqAdapter: JobAdapter = {
async enqueue(jobName, payload, options) {
await bookingQueue.add(jobName, payload, {
delay: options?.delay,
});
},
async scheduleAt(jobName, payload, runAt) {
const delay = runAt.getTime() - Date.now();
await bookingQueue.add(jobName, payload, { delay });
},
};

For simpler setups, use Vercel Cron for scheduled tasks:

vercel.json
{
"crons": [
{
"path": "/api/cron/auto-reject",
"schedule": "*/15 * * * *"
},
{
"path": "/api/cron/send-reminders",
"schedule": "0 * * * *"
}
]
}