Not everything can happen in the request. Some work happens in the background.
Sending emails, processing files, generating reports, syncing data with external APIs — these tasks shouldn't block the user's request. Background jobs run asynchronously, retry on failure, and process at scale. Understanding the queue-based job architecture.
Application that does work synchronously that should happen in the background — slow requests, user-facing timeouts, or work that needs to happen on a schedule rather than on demand
Serverless functions time out (Vercel: 10 seconds on the hobby plan, 5 minutes on Pro). Traditional web servers block other requests if a synchronous operation takes too long. Some work genuinely takes minutes:
- Sending bulk emails (1,000 users × 0.1 seconds = 100 seconds)
- Processing uploaded documents (PDF parsing, image resizing)
- Generating large reports
- Syncing records with external CRMs or ERPs
- Running ML/AI inference on user data
This work needs to happen off the request path.
The queue-based architecture:
- API endpoint receives the request, enqueues a job, and immediately returns a response ("your report is being generated")
- A worker process picks up the job from the queue and processes it
- The worker stores the result (in the database, S3, etc.)
- The user is notified (email, in-app notification, polling endpoint) when the job is complete
The stack:
BullMQ + Upstash Redis: BullMQ is the Node.js job queue library. Upstash provides managed Redis for the queue storage. Workers run on a traditional server (Fly.io, Railway) — not serverless.
Inngest: A newer managed job queue service. Workers can run on Vercel (bypassing the serverless timeout with Inngest's long-running function support). Good DX; paid service.
Trigger.dev: Similar to Inngest — managed background jobs that integrate with serverless deployments.
Background job system that processes work asynchronously with reliable queuing, retry logic, and failure visibility
BullMQ + Upstash Redis
queue infrastructure
Job producers
API routes that enqueue jobs
Worker service
processes jobs with retry and failure handling
Job monitoring
visibility into queue depth and failed jobs
User notification
when async jobs complete
One honest number to start.
Fixed-scope, fixed-price. The number below is the starting point — final scope is built from your brief.
Background job system that processes work asynchronously with reliable queuing, retry logic, and failure visibility
Three steps, every time.
The same repeatable engagement on every project. No surprises, no mystery, no billable ambiguity.
Brief & discovery.
We send you questions, then get on a call. Output: a written scope with every step, feature, and integration listed.
Build & ship.
Fixed schedule, weekly reviews. No scope creep unless you change the scope — and if you do, we reprice it transparently.
Warranty & retainer.
30-day warranty on every launch. Most clients stay on a monthly retainer for ongoing features and maintenance.
Why Fixed-Price Matters Here
Background job scope is defined by the job types and the queue infrastructure. Fixed-price build.
Questions, answered.
With Inngest or Trigger.dev, yes — they handle the long-running execution outside Vercel's function timeout. Without these services, background workers need a traditional server.
BullMQ automatically retries failed jobs with exponential backoff. Failed jobs that exhaust retries land in the "failed" queue. Monitoring tools alert on failed job accumulation.
Tell Ryel about your project.
Describe what you’re building and what outcome you need. You’ll have a written, fixed-price scope within the week.