Background jobs for Next.js without after() hacks or worker servers
Next.js gives you Server Actions, Route Handlers, and <code>after()</code>—but none of them replace a real background worker when PDFs, webhooks, or ETL outlive the HTTP window. Compare Next.js and Vercel background patterns with Inquir pipelines: keep the App Router on Vercel, move slow async work to serverless jobs with retries and execution history.
Last updated: 2026-06-23
- Keep on Next.js/Vercel: App Router UI, middleware, previews, edge caching, short API responses.
- Move to Inquir: work that exceeds function timeouts, cron beyond vercel.json limits, webhook continuation, parallel fan-out.
- Use both: Route Handlers return 202 and call Inquir gateway routes; pipelines finish the job and notify your app.
Answer first
Direct answer
Background jobs for Next.js without after() hacks or worker servers. Your Route Handler or Server Action calls an Inquir gateway route with an API key, returns 202 to the client, and moves on. Inquir pipelines handle queuing, retries, secrets, and execution history—same functions you use for webhooks and cron.
When it fits
- Your Next.js app needs background tasks, webhooks, or cron jobs that exceed Route Handler or
after()timeouts. - You want one async tier with shared observability instead of stitching BullMQ, Inngest, and Vercel Cron.
Tradeoffs
after()and Fluid Compute help when work is IO-bound and still fits inside the platform timeout—logging, cache warming, a single downstream API call.- Vercel Cron in
vercel.jsonworks for lightweight scheduled tasks that complete in seconds. Heavy ETL, report generation, or multi-step orchestration usually need a dedicated job tier.
Workload and what breaks
Why Next.js background patterns hit a wall
Server Actions and Route Handlers are request-scoped. after() and waitUntil() defer work until after the response—but on Vercel they still run inside the same function invocation with platform timeouts. PDF generation, bulk email, slow third-party chains, and large file transforms are the usual casualties.
Teams reach for BullMQ, Inngest, or a separate worker container. That means another deploy target, another secret store, and another dashboard when a Stripe webhook or nightly sync fails at 3 AM.
Trade-offs
When Next.js + Vercel background tooling is enough
after() and Fluid Compute help when work is IO-bound and still fits inside the platform timeout—logging, cache warming, a single downstream API call.
Vercel Cron in vercel.json works for lightweight scheduled tasks that complete in seconds. Heavy ETL, report generation, or multi-step orchestration usually need a dedicated job tier.
How Inquir helps
Next.js stays thin; Inquir runs the slow path
Your Route Handler or Server Action calls an Inquir gateway route with an API key, returns 202 to the client, and moves on. Inquir pipelines handle queuing, retries, secrets, and execution history—same functions you use for webhooks and cron.
One workspace for HTTP ingress, scheduled pipelines, and async jobs. No Redis to babysit, no worker Dockerfile beside your Next.js repo—just gateway routes your app already knows how to fetch.
What you get
Background job patterns for Next.js apps
Fast ACK from Route Handlers
App Router POST handler validates input, enqueues on Inquir, returns { status: "queued" } with 202—user never waits on PDF or email delivery.
Webhook continuation
Inquir webhook function verifies the provider signature, acks within the timeout, then continues in a pipeline step—Stripe and GitHub retries do not re-run expensive work.
Cron beyond vercel.json
Nightly ETL, token rotation, and report generation as scheduled pipelines with visible run history—not a black-box cron hitting a fragile Route Handler.
Server Action handoff
Server Actions stay for form validation and auth; heavy side effects enqueue to Inquir so you do not block the UI thread or risk Action timeouts.
What to do next
How to wire background jobs from Next.js to Inquir
Route Handlers and Server Actions stay thin: validate, enqueue on Inquir, return 202. Pipelines carry retries, secrets, and execution history for the slow path.
Extract the slow handler to Inquir
Move PDF, email, or sync logic into an Inquir function or pipeline step. Keep inputs explicit and handlers idempotent.
Call from a Route Handler or Server Action
POST to the Inquir gateway with Authorization: Bearer <key> from process.env. Return 202 before the pipeline finishes.
Monitor in execution history
Every run, retry, and failure appears in Inquir—no digging through Vercel function logs for a job that started in after().
Code example
Next.js App Router → Inquir: enqueue after form submit
Server Action validates the form and calls an Inquir gateway route that enqueues work. The user sees success immediately; the pipeline step generates the asset and notifies your app when done.
'use server'; export async function submitReport(formData: FormData) { const reportId = formData.get('reportId') as string; if (!reportId) throw new Error('reportId required'); await fetch(process.env.INQUIR_GATEWAY_URL + '/jobs/generate-report', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${process.env.INQUIR_API_KEY}`, }, body: JSON.stringify({ reportId }), }); // User sees success UI; slow work runs on Inquir }
export async function handler(event) { const { reportId } = JSON.parse(event.body || '{}'); if (!reportId) return { statusCode: 400, body: JSON.stringify({ error: 'reportId required' }) }; const { instanceId: jobId } = await global.durable.startNew('generate-report', undefined, { reportId }); return { statusCode: 202, body: JSON.stringify({ jobId, status: 'queued' }) }; }
export async function handler(event) { const { reportId } = event.payload ?? {}; const pdf = await buildReport(reportId); await storage.upload(pdf, `reports/${reportId}.pdf`); await notifyApp(reportId); return { reportId, size: pdf.byteLength }; }
When it fits
When this pattern helps
When this works
- Your Next.js app needs background tasks, webhooks, or cron jobs that exceed Route Handler or
after()timeouts. - You want one async tier with shared observability instead of stitching BullMQ, Inngest, and Vercel Cron.
When to skip it
- All background work fits inside
after()/ Fluid Compute and you do not need cross-request job history or retries beyond the platform.
FAQ
FAQ
Should I replace after() with Inquir?
after() with Inquir?Not always. Use after() for quick post-response work inside the timeout. Use Inquir when the job can fail independently, needs retries, runs on a schedule, or outlives the function invocation.
Can I keep deploying Next.js on Vercel?
Yes. This page compares Next.js background patterns, not hosting. Keep Vercel for the frontend; Inquir handles the worker tier.
How is this different from background jobs for Vercel?
Same architecture—thin frontend, Inquir for slow work. This page focuses on Next.js APIs (after(), Server Actions, Route Handlers) and when each stops being enough.
Do I need a separate queue like BullMQ?
No. Inquir pipelines provide queuing, retries, and observability. Your Next.js code calls a gateway route; Inquir manages the rest.