Skip to main content
QStash is an HTTP-based messaging and scheduling service. You hand it a request, and QStash delivers it to your endpoint later — with retries, delays, ordering, rate limits, and a dead letter queue when things go wrong. That makes it a fit for any work that shouldn’t happen inside the request that triggered it: tasks that take too long, tasks that must survive a failure, tasks that must run on a schedule, and tasks that must not overwhelm the service they call. Because everything is HTTP, there is no consumer to keep running. Your existing API endpoints are the consumers, wherever they are deployed — Vercel, AWS Lambda, Cloudflare Workers, Fly.io, or your own servers.

Background jobs

Serverless platforms cap how long a function can run. Anything heavier than a few seconds — video processing, report generation, importing a CSV, calling a slow third-party API — risks a timeout, and the user is waiting for it. With QStash, your handler publishes a message and returns immediately. QStash calls a second endpoint that does the real work, retrying if it fails.
If the job itself is longer than a single function invocation allows, use callbacks so QStash delivers the response to another endpoint once it’s ready, instead of your caller blocking on it.

Background Jobs

Full walkthrough, including local development

Scheduled and recurring tasks

Anything you would put in a cron job — nightly reports, resetting billing cycles, expiring trials, syncing a search index, warming a cache — becomes a schedule that calls your endpoint on a cron expression.
Schedules run in UTC by default and support timezones. Unlike platform-native cron (such as Vercel Cron), schedules are not tied to a deploy, are not limited to one per plan tier, and retry on failure.

Reliable webhook delivery

Webhooks are the most common reason people reach for QStash, in both directions: Receiving webhooks. Point Stripe, GitHub, Shopify, or Clerk at a QStash publish URL instead of your endpoint directly. QStash absorbs the burst, retries if your app is down or mid-deploy, and applies whatever delay, timeout, or flow control you configure. The provider gets a fast 2xx even when your processing is slow. Sending webhooks. If you deliver webhooks to your own customers, QStash handles the part nobody wants to build: exponential retries, per-customer concurrency limits, and a dead letter queue for endpoints that stay down.

Use as Webhook Receiver

Publish URLs, URL Groups, and header forwarding

Building Reliable & Type-Safe Webhooks

Designing an outbound webhook system on QStash

Fan-out to multiple services

One event often needs to reach several places: a purchase should trigger a receipt email, a Slack notification, an analytics event, and a warehouse webhook. Publish once to a URL Group and QStash creates an independent, independently-retried delivery for each subscribed endpoint. Adding or removing a consumer is a URL Group change — no redeploy of the producer.
The same shape works for alerting: one alert source fanned out to Slack, email, and PagerDuty.

Rate-limited and fragile third-party APIs

When you call an API with a quota — OpenAI, Resend, Shopify, a partner’s internal service — the hard part is not calling it, it’s not calling it too often. Flow Control lets QStash hold messages back for you, by request rate, by concurrency, or both.
You can publish ten thousand messages at once and let QStash drip them out at the rate your downstream tolerates, instead of building a queue and a limiter yourself. Limits apply per key, so the same key can span multiple URLs.

Efficient Article Summarization with QStash

Handling API rate limits and parallel processing in Python

AI and LLM requests

LLM calls are slow, variable, and expensive to retry by hand — a bad match for a 10-second serverless timeout. QStash gives them a 2-hour HTTP timeout, delivers the response to a callback endpoint when it’s done, and can batch many requests in one publish. There are built-in integrations for OpenAI-compatible providers and Anthropic, so QStash calls the provider for you and you only handle the callback. Combined with flow control, this is a practical way to run bulk embedding jobs, document summarization, or content generation without hitting provider rate limits.

Delayed and time-based messages

Some work is defined by when it should happen: a welcome email 10 minutes after signup, a trial-ending reminder 3 days out, an abandoned-cart nudge, a retry of a payment tomorrow. Delay a message by a duration or to an absolute timestamp, and QStash holds it until then — up to 7 days on the free plan and up to a year on pay-as-you-go.
With the Resend integration you can skip the endpoint entirely and have QStash send the email itself at the scheduled time.

Scheduling emails in the user's timezone

Per-user send times with QStash

Building an Email Scheduler

An email scheduler with the Python SDK

Ordered processing

Some pipelines break if messages overtake each other — applying a sequence of updates to the same record, processing a customer’s events in order, or writing to a system that can’t handle concurrent writes. Queues deliver messages one at a time in FIFO order. The next message only becomes active after the current one is delivered, has exhausted its retries, or its callback has finished.

Syncing and periodic data updates

Instead of querying a slow or rate-limited third-party API on every request, schedule a job that pulls fresh data into your own database, and serve reads from there. The same pattern covers flushing Redis state to a primary database, refreshing a cache, and rebuilding a search index.

Periodic Data Updates

Recipe: keep third-party data fresh in your own database

Sync Redis state to your database

Write-behind from Redis using QStash

Decoupling services

Beyond individual jobs, QStash works as the messaging layer between your services: producers publish, QStash guarantees at-least-once delivery, and consumers are just HTTP endpoints. Deduplication keeps retries from double-processing, signature verification proves a request came from QStash, and the DLQ holds anything that never succeeded. This is the pattern behind cutting serverless costs, too: move expensive work out of long-running function invocations and let QStash drive short, cheap ones.

Get Rid of Function Timeouts and Reduce Vercel Costs

Why offloading work changes your bill

Multi-step workflows

If your task has several dependent steps — call an API, wait for a human, branch, then call another — chaining QStash messages by hand gets awkward. Upstash Workflow is built on QStash and gives you durable, resumable functions where each step is checkpointed automatically.
Use QStash directly for single messages, schedules, and fan-out. Reach for Upstash Workflow when the logic spans multiple dependent steps.

More examples

Building a seriously reliable serverless API

Retries, idempotency, and failure handling end to end

Decouple Webhook Processing on Next.js

Taking webhook work off the request path

Build a Subscription Service with Next.js & Prisma

Recurring billing cycles driven by schedules

Refresh stale data in a SvelteKit app

Scheduled revalidation outside the request path

Serverless Background Jobs and Message Queues Compared

How QStash compares to the alternatives

Why We Chose QStash at Scale

A production user’s account of running QStash
More posts are on the QStash blog. If there’s a use case you’d like documented, tell us on Discord or X.