Vercel Queues

The recommended scheduler on Vercel.

server/orders.ts
import { createServer } from 'experimental-a2/server'
import { redis } from 'experimental-a2/store-redis'
import { vercelQueues } from 'experimental-a2/scheduler-vercel'
import { orders } from '@/contracts'

export const scheduler = vercelQueues()

export const ordersServer = createServer({
  contract: orders,
  store: redis({ url: process.env.REDIS_URL }),
  scheduler,
  handlers: {
    /* ... */
  },
})
app/api/a2/scheduler/route.ts
import { ordersServer, scheduler } from '@/server'

export const POST = scheduler.handler(ordersServer)
vercel.json
{
  "functions": {
    "app/api/a2/scheduler/route.ts": {
      "experimentalTriggers": [
        {
          "type": "queue/v2beta",
          "topic": "a2"
        }
      ]
    }
  }
}
npm install @vercel/queue

The trigger is required. It connects the route to Vercel Queues and makes the function private, so only the queue can call it. Don't also expose the route publicly or wrap it in your own authentication.

Messages are kept for seven days (Vercel Queues' default is 24 hours, and seven days is its maximum), so timers can be scheduled up to seven days out. A longer delay goes out as asked, and Vercel Queues refuses it.

A drain delivery is acknowledged once its session settles or a later watchdog for it is stored, including when the drain fails after storing that watchdog. A drain that fails before then stays unacknowledged, so Vercel Queues redelivers it.

Options

OptionDefault
topic'a2'must match the trigger's topic, and [A-Za-z0-9_-]+
deploymentIdVERCEL_DEPLOYMENT_IDwhich deployment receives tasks; see below
transport, clockthe @vercel/queue client, the system clocktest seams for custom delivery

An injected transport receives the topic, the task, and send options, and owns its own provider configuration; deploymentId only configures the built-in client.

Deployments

deploymentId applies to every task: retries, timers, and scheduled clears. Leave it out to deliver to the deployment that sent the task, pass an ID to target one deployment, or pass null to let Vercel pick. Every deployment that sends or receives must use the same setting.

  • Tasks stay with their deployment. Promoting a new deployment doesn't move them, so older deployments keep receiving their own work until it's done or expires. Upgrading doesn't fix an older deployment's route.
  • null doesn't mean latest. Vercel picks any eligible deployment, so every one of them must use deploymentId: null and handle pending tasks.
  • Changing the setting doesn't move queued tasks. Keep the old deployments running until those tasks finish.