·5 min read

QStash: Messaging for the Serverless

Enes AkarEnes AkarCofounder @Upstash

We are proud and excited to announce QStash 🔥🔥🔥

Formally, QStash is a message queue and task scheduler designed for serverless runtimes. Informally, QStash is a glue for your serverless functions.

There was a perception serverless was only good for simple tasks. Not anymore. People build powerful systems with serverless stack. Powerful systems are composed of multiple components. Communication among those components is a big engineering problem. There are already great solutions for this problem. But we think existing solutions do not fit in serverless space. Either they are too complex or not designed to work with stateless runtimes. So we want a solution which (is):

  • Works anywhere including serverless and edge.
  • Messaging as a service with no backend for users to run.
  • Lightweight, easy to understand, requires nothing to learn.
  • Price scales to zero.

Let’s talk about a real world example. We have an e-commerce app and we want to send an informational email after each purchase. We have a service (an API route) for new purchases (newPurchase) and a second service for sending emails and notifications (sendEmail). We can call the sendEmail service from the newPurchase service. But what if the call fails? Should we wait for the response and retry? What if too many calls congest the sendEmail service and the service does not respond on time? You need to handle all these cases in your newPurchase service. Moreover, when you change the contract of sendEmail service; you have to update your newPurchase service too.

If you use QStash in the above example, you simply send a request to QStash from the newPurchase service. QStash will queue the request and call the sendEmail service. If the service does not respond, QStash will retry with a backoff strategy. The latency of sendEmail service will not affect the newPurchase service, because it will not wait for a response from the sendEmail service. QStash decouples the newPurchase and sendEmail services. You can update both services independently as long as you keep the message format compatible.

With QStash, you can add delays to the requests. Send an email 3 days after the shipment to remind the customer to add a review. You can also schedule tasks. You can send the requests with a CRON expression, so it will be run repetitively.

Now let’s briefly visit features of QStash:

Works Anywhere

Instead of traditional pull-based messaging where you require a long-running process to consume from the queue, QStash pushes messages to your API. This allows you to use serverless functions to process them. We handle retries, custom delays and scheduling for you. All you need is a publicly accessible HTTP API.

Price Scales to Zero

QStash price is $1 per 100.000 requests. The good thing is that there is no minimum or fixed payment. You only pay for what you use. If you expect millions of requests, we will offer you an enterprise plan with lower per request prices.

Update - September 2022

We reduced QStash pricing to $1 per 100K requests. See QStash Pricing page for the latest pricing information.

Endpoints and Topics

You include an endpoint together with the message to QStash. So QStash sends the message to this endpoint. Also, you can define a topic which allows grouping one or more endpoints into a single namespace. Thanks to the topic abstraction, you can modify endpoints without touching the backend implementation. The below sends the requests to the topic user-apis. A copy of the message will be delivered to each endpoint.

Sending to an endpoint
curl -XPOST \
    "https://qstash.upstash.io/v1/publish/https://example.com" \
	-H "Authorization: Bearer XXX" \
	-H "Content-Type: application/json" \
	-d "{ \"hello\" : \"world\" }"
Sending to a topic
curl -XPOST \
	"https://qstash.upstash.io/v1/publish/user-apis" \
	-H "Authorization: Bearer XXX" \
	-H "Content-Type: application/json" \
	-d "{ \"hello\" : \"world\" }"


QStash can repeat sending your task in a schedule. Set a CRON expression as a value to the header Upstash-Cron. The below example instructs QStash to call the API every minute.

curl -XPOST \
    -H 'Authorization: Bearer XXX' \
    -H "Content-type: application/json" \
    -H "Upstash-Cron: * * * * *" \
    -d '{ "hello": "world" }' \


  • Retries: If your API does not respond with a success status code, QStash retries the request to ensure every message will be delivered.
  • Delays: Delay the delivery of a message by up to 90 days.
  • Deduplication: You can prevent duplicate messages using Deduplication-Id or automatic content based deduplication.
  • Request signing: Your APIs must be public. You can verify the authenticity of each incoming request by verifying the signature.
  • JS/TS SDK: REST API is simple, but if you are building on JS/TS, our SDK is even simpler.

Closing Words

QStash aims to provide the best messaging service for the serverless world. This is our first release, so we strongly need your feedback and contributions. Check the QStash documentation. Reach out to us on GitHub, Discord and Twitter for your comments and suggestions..