Quickstart
From zero to a working background job in a Next.js app. There's no server or Redis to set up — that's the part we manage.
Prerequisites#
- A Next.js App Router app.
- A public URL for deployed jobs, or a tunnel for local development.
1. Create a project#
Sign up and create a project in the NextMQ dashboard. You'll get one connection string — it bundles your server URL, API key, and webhook secret. Keep it handy for the next step.
2. Install the SDK#
npm install @nextmq/sdk3. Add your environment#
Paste the connection string from your dashboard, plus your app's public URL.
NEXTMQ_CONNECTION_STRING=nextmq://v1....
NEXT_PUBLIC_APP_URL=https://your-app.comNEXT_PUBLIC_APP_URL is where NextMQ calls back to run your jobs. Keep the connection string server-only — it's a secret.
4. Define a queue and a worker#
The same primitives as BullMQ. The processor is the code NextMQ calls back to run.
import { Queue, Worker } from '@nextmq/sdk'
export const imageQueue = new Queue<{ uploadId: string }>('images')
export const imageWorker = new Worker('images', async (job) => {
await job.updateProgress(25)
const thumb = await makeThumbnail(job.data.uploadId)
return { thumbnailUrl: thumb.url }
})
async function makeThumbnail(uploadId: string) {
// Replace with your image pipeline.
return { url: `https://cdn.example.com/thumbs/${uploadId}.jpg` }
}5. Add the webhook route#
One catch-all route handles every queue. It verifies signatures, dispatches jobs to the right worker, and exposes a /health path. It must run on the Node.js runtime.
import { createNextMQHandler } from '@nextmq/sdk/next'
import { imageWorker } from '@/jobs/images'
export const runtime = 'nodejs'
export const { GET, POST } = createNextMQHandler({
workers: [imageWorker],
})6. Enqueue a job#
From a route handler or server action:
import { imageQueue } from '@/jobs/images'
export async function POST(req: Request) {
const { uploadId } = await req.json()
const job = await imageQueue.add('thumbnail', { uploadId }, {
attempts: 5,
backoff: { type: 'exponential', delay: 1000 },
})
return Response.json({ queued: true, jobId: job.id })
}7. See it run#
Open the dashboard and look at the images queue, or wait for the result when the job is short enough for the original request to stay open.
const job = await imageQueue.add('thumbnail', { uploadId })
const result = await job.waitUntilFinished({
timeoutMs: 15_000,
pollIntervalMs: 500,
})What happens now#
NextMQ stores the job, a real BullMQ worker picks it up, and it calls your /api/nextmq route to run imageWorker. If your processor throws, NextMQ retries with exponential backoff up to five attempts — no extra code from you.
Keep going#
- Queues & job options — every supported
add()option. - Workers & processing — concurrency, rate limits, and outcomes.
- Deploying to Vercel — env vars and keeping idle queues warm.
- Examples — copy-paste patterns for common jobs.