Your app works great — until a user action takes 30 seconds to complete. Sending a batch of emails, generating a PDF report, processing an uploaded video, syncing data from an external API. These operations are too slow to run while the user waits. They need to happen in the background.
Background jobs are one of the most common things vibe coders need but rarely learn about until something breaks. This guide explains what background jobs are, when you need them, and which tools make them accessible without a DevOps degree.
What Are Background Jobs?
A background job is any task your app runs outside the normal request-response cycle. When a user clicks a button on your site, your server typically needs to respond within a few seconds. If the work takes longer than that — or if it does not need to happen immediately — you move it to a background process.
Real examples from vibe-coded apps:
- Sending welcome emails when a user signs up. The signup should complete instantly; the email can arrive 5 seconds later.
- Generating invoices at the end of each month. No user is waiting for this — it happens on a schedule.
- Processing image uploads — creating thumbnails, optimizing file sizes, extracting metadata. Upload completes quickly; processing happens after.
- Syncing data from a third-party API every hour. No user triggers this; it runs automatically.
- Running AI analysis on user-submitted content. An LLM call might take 10–60 seconds; you do not want the user staring at a spinner.
If your app does any of these things synchronously (in the main request), users experience slow page loads, timeouts, and frustration. Background jobs fix this by decoupling the work from the response.
Three Patterns You Need to Know
Background jobs generally fall into three categories. Understanding which pattern fits your use case helps you pick the right tool.
Pattern 1: Cron Jobs (Scheduled Tasks)
A cron job runs on a fixed schedule: every hour, every day at midnight, every Monday at 9 AM. The name comes from the Unix cron utility, which has been scheduling tasks since the 1970s.
Use cron jobs for:
- Daily database cleanup (delete expired sessions, archive old records)
- Sending weekly digest emails to subscribers
- Refreshing cached data from external APIs
- Generating daily/weekly/monthly reports
- Checking for subscription renewals or trial expirations
Cron jobs are the simplest background pattern. You define a function and a schedule, and the platform runs it for you.
Pattern 2: Task Queues (Event-Driven Jobs)
A task queue processes work in response to events. Instead of running on a schedule, tasks are added to a queue when something happens — a user uploads a file, a payment succeeds, a form is submitted — and a worker picks them up and processes them.
Use task queues for:
- Sending transactional emails (welcome email after signup, receipt after purchase)
- Processing file uploads (image resizing, video transcoding)
- Calling external APIs that might be slow or rate-limited
- Running AI/LLM tasks triggered by user actions
- Handling webhook events from Stripe, GitHub, or other services
The key advantage of queues is reliability. If the worker crashes or the external API is down, the task stays in the queue and retries automatically. No work gets lost.
Pattern 3: Long-Running Processes
Some tasks take minutes or even hours: data migrations, bulk imports, complex AI pipelines, large file processing. These do not fit neatly into a serverless function with a 30-second timeout. They need a process that can run for extended periods, report progress, and handle failures gracefully.
This pattern is less common in early-stage vibe-coded apps, but it comes up when you start dealing with data processing at scale. Tools like Trigger.dev and Inngest handle this with "durable execution" — your function can run for hours, and the platform manages retries, timeouts, and state across restarts.
Tool Comparison: What Works for Vibe Coders
Here are the four most accessible tools for adding background jobs to a vibe-coded project:
| Tool | Best for | Free tier | Pricing starts at |
|---|---|---|---|
| Vercel Cron Jobs | Simple scheduled tasks on Vercel | 2 cron jobs, daily minimum | $20/mo (Pro, more cron jobs) |
| Inngest | Event-driven workflows, multi-step jobs | 5,000 runs/month | $25/mo (25K runs) |
| Trigger.dev | Long-running tasks, complex pipelines | 5,000 runs/month | $25/mo (25K runs) |
| Upstash QStash | Simple HTTP-based message queue | 500 messages/day | $1/100K messages |
Pricing verified April 2026. Check official sites for current rates.
Vercel Cron Jobs: The Simplest Starting Point
If your app is on Vercel, cron jobs are built in. You add a vercel.json file with a cron schedule, and Vercel calls your API route on that schedule. That is it.
{
"crons": [
{
"path": "/api/daily-cleanup",
"schedule": "0 0 * * *"
}
]
}
The free tier allows 2 cron jobs with a minimum interval of once per day. The Pro plan ($20/month, which most Vercel users already pay) unlocks 40 cron jobs with intervals down to every minute.
Limitations: Vercel cron jobs are just HTTP calls to your API routes. They are subject to Vercel's function timeout limits (10 seconds on free, 60 seconds on Pro, 300 seconds on Enterprise). If your task takes longer than that, you need a different approach. There is also no built-in retry logic, queue management, or event triggering — it is purely schedule-based.
Inngest: Event-Driven Background Functions
Inngest takes a different approach. Instead of scheduling tasks, you define functions that respond to events. When your app sends an event (like user.signed.up or invoice.created), Inngest triggers the associated function.
import { inngest } from './client';
export const sendWelcomeEmail = inngest.createFunction(
{ id: 'send-welcome-email' },
{ event: 'user/signed.up' },
async ({ event }) => {
await sendEmail({
to: event.data.email,
subject: 'Welcome!',
body: '...',
});
}
);
The power of Inngest is in multi-step functions. A single function can chain multiple operations with automatic retries at each step. If step 3 fails, Inngest retries step 3 without re-running steps 1 and 2. This is useful for workflows like: charge the customer, then send the receipt, then update the database, then notify the team.
Inngest also supports scheduling (cron-style), throttling (limit how fast events are processed), debouncing (wait for events to stop before processing), and concurrency control (limit how many instances run in parallel).
Best for: Apps that need event-driven workflows with reliability guarantees. If you find yourself writing complex chains of async operations with try/catch at every step, Inngest can simplify that significantly.
Trigger.dev: Long-Running and Complex Tasks
Trigger.dev focuses on tasks that need to run longer than serverless function limits allow. It provides a serverless execution environment where your background tasks can run for up to 5 minutes on the free tier and much longer on paid plans.
The v3 architecture runs your code in isolated containers, so you can use any Node.js library without worrying about serverless constraints. This makes it particularly good for:
- AI/LLM pipelines that chain multiple model calls
- Document processing (PDF generation, data extraction)
- Data sync operations with external APIs
- Bulk operations (mass email sends, batch updates)
Trigger.dev integrates with Next.js, Remix, and other frameworks. You define tasks in your codebase, and the platform deploys and executes them separately from your main app.
Best for: Tasks that exceed serverless timeouts or need complex orchestration. If Vercel Cron Jobs are too simple and Inngest is more event-driven than you need, Trigger.dev fills the gap.
Upstash QStash: Lightweight Message Queue
Upstash QStash is the simplest tool in this comparison. It is an HTTP-based message queue: you send a message to QStash with a destination URL, and QStash delivers it to that URL. If the destination is down, QStash retries with exponential backoff.
Think of it as a reliable HTTP relay. Instead of your app calling an API directly (and risking timeouts or failures), you tell QStash to make the call, and it guarantees delivery.
QStash also supports scheduling (cron-style) and delayed delivery (send this message in 30 minutes). The pricing is usage-based: 500 free messages per day, then $1 per 100,000 messages. For most vibe-coded apps, the free tier is enough.
Best for: Simple async tasks where you need reliable delivery but do not need complex workflows. Webhook forwarding, delayed notifications, simple scheduled tasks.
How to Ask Your AI Assistant to Add Background Jobs
The hardest part of background jobs for vibe coders is knowing what to ask for. Here are effective prompts for AI coding assistants:
- "Add a Vercel cron job that runs every day at midnight and deletes all database records older than 30 days from the sessions table."
- "Set up Inngest in my Next.js app. Create a function that sends a welcome email via Resend when the user.signed.up event is triggered."
- "Add a background task using Trigger.dev that processes uploaded images: resize to 800px width, convert to WebP, and upload to Cloudflare R2."
- "Use Upstash QStash to queue webhook events from Stripe instead of processing them synchronously in my API route."
Be specific about what the task should do, what triggers it, and what happens when it fails. Your AI assistant can scaffold the integration, but you need to define the business logic. Check the prompting techniques guide for more strategies.
Cost Considerations
Background job costs are usually a rounding error compared to your other infrastructure costs. Most free tiers cover early-stage apps comfortably:
- Side project: Vercel Cron (free) or Upstash QStash (free) handles everything you need. $0/month.
- Growing app (1,000–10,000 users): Inngest or Trigger.dev free tier likely covers your volume. $0–25/month.
- Production SaaS: Paid plans for reliability and higher limits. $25–100/month depending on volume.
The real cost risk is not the background job platform itself but what the jobs do. A cron job that calls an AI API 1,000 times per day adds up. A queue that sends 10,000 emails per month incurs email service costs. Factor in the downstream costs of whatever your background jobs trigger.
When to Add Background Jobs
You do not need background jobs on day one. Add them when:
- Users complain about slow actions (anything over 3 seconds should be moved to background).
- You need scheduled operations (daily reports, weekly emails, periodic cleanup).
- External API calls are unreliable and you need automatic retries.
- You are processing uploads or generating content that takes time.
Start with the simplest tool that solves your problem. Vercel Cron for scheduled tasks, Upstash QStash for simple queues, and graduate to Inngest or Trigger.dev when your workflows get more complex. You can always migrate later — background job tools are relatively easy to swap because they are loosely coupled to your main application.