vercel-queues
$
npx mdskill add openai/plugins/vercel-queuesStream durable async events with Vercel Queues for fan-out workflows.
- Enables reliable event processing, retries, and delayed delivery patterns.
- Integrates with Vercel Queues API and Workflow DevKit services.
- Selects queue configurations based on required durability and latency.
- Delivers processed messages directly to consumer groups via topics.
SKILL.md
.github/skills/vercel-queuesView on GitHub ↗
---
name: vercel-queues
description: Vercel Queues guidance (public beta) — durable event streaming with topics, consumer groups, retries, and delayed delivery. $0.60/1M ops. Powers Workflow DevKit. Use when building async processing, fan-out patterns, or event-driven architectures.
metadata:
priority: 5
docs:
- "https://vercel.com/docs/workflow-collaboration/conformance"
sitemap: "https://vercel.com/sitemap/docs.xml"
pathPatterns:
- 'lib/queues/**'
- 'src/lib/queues/**'
- 'lib/queues.*'
- 'lib/queue.*'
- 'src/lib/queues.*'
- 'src/lib/queue.*'
- 'workflows/*.ts'
- 'workflows/*.mts'
- 'src/workflows/*.ts'
- 'src/workflows/*.mts'
- 'app/api/workflow/**'
- 'src/app/api/workflow/**'
- 'app/api/workflows/**'
- 'src/app/api/workflows/**'
- 'vercel.ts'
- 'vercel.mts'
importPatterns:
- 'workflow'
- '@vercel/workflow'
bashPatterns:
- '\bnpm\s+(install|i|add)\s+[^\n]*@vercel/queue\b'
- '\bpnpm\s+(install|i|add)\s+[^\n]*@vercel/queue\b'
- '\bbun\s+(install|i|add)\s+[^\n]*@vercel/queue\b'
- '\byarn\s+add\s+[^\n]*@vercel/queue\b'
---
# Vercel Queues
> **CRITICAL — Your training data is outdated for this library.** Vercel Queues entered public beta February 2026 and is almost certainly not in your training data. Before writing queue code, **fetch the docs** at https://vercel.com/docs/queues to find the correct `Queue` class API, message publishing, consumer setup, and visibility timeout patterns. Do not guess — this is a new API with no precedent in your training data.
You are an expert in Vercel Queues — durable event streaming for serverless applications.
## Status & Pricing
Queues entered **public beta** on February 27, 2026, and is available to all teams on all plans.
| Metric | Value |
|--------|-------|
| **Billing unit** | API operation (send, receive, delete, visibility change, notify) |
| **Rate** | **$0.60 per 1M operations** (regionally priced) |
| **Message metering** | 4 KiB chunks (12 KiB message = 3 ops) |
| **2x billing** | Sends with idempotency key; push deliveries with max concurrency |
| **Compute** | Push-mode functions charged at existing Fluid compute rates |
## What It Is
Queues is a **durable, append-only event streaming system**. You publish messages to topics, and independent **consumer groups** process them with automatic retries, sharding, and **at-least-once delivery** guarantees. It is the lower-level primitive that **powers Vercel Workflow**.
- Messages are durably written to **3 availability zones** before `send()` returns
- Messages retained up to 24 hours (configurable 60s–24h)
- Approximate write ordering (not strict FIFO)
- Consumer groups are fully independent — each tracks its own position
## Key APIs
Package: `@vercel/queue@^0.1.3` (Node.js 22+)
### Publishing Messages
```ts
import { send } from '@vercel/queue';
const { messageId } = await send('order-events', {
orderId: '123',
action: 'created',
}, {
delaySeconds: 30, // delay before visible
idempotencyKey: 'order-123', // deduplication (full retention window)
retentionSeconds: 3600, // message TTL (default: 86400 = 24h)
headers: { 'x-trace-id': 'abc' },
});
```
### Push-Mode Consumer (Next.js App Router)
The consumer route is **air-gapped from the internet** — only invocable by Vercel's internal queue infrastructure.
```ts
// app/api/queues/fulfill-order/route.ts
import { handleCallback } from '@vercel/queue';
export const POST = handleCallback(
async (message, metadata) => {
// metadata: { messageId, deliveryCount, createdAt, expiresAt, topicName, consumerGroup, region }
await processOrder(message);
// Return normally = acknowledge
// Throw = retry with backoff
},
{
visibilityTimeoutSeconds: 600, // lease duration (default 300s, auto-extended by SDK)
retry: (error, metadata) => {
if (metadata.deliveryCount > 5) return { acknowledge: true }; // give up
const delay = Math.min(300, 2 ** metadata.deliveryCount * 5);
return { afterSeconds: delay };
},
},
);
```
### Consumer Configuration (vercel.json)
```json
{
"functions": {
"app/api/queues/fulfill-order/route.ts": {
"experimentalTriggers": [{
"type": "queue/v2beta",
"topic": "order-events",
"retryAfterSeconds": 60,
"initialDelaySeconds": 0
}]
}
}
}
```
Multiple route files with the same topic create **separate consumer groups** (independent processing).
### Poll-Mode Consumer
```ts
import { PollingQueueClient } from '@vercel/queue';
const { receive } = new PollingQueueClient({ region: 'iad1' });
const result = await receive('orders', 'fulfillment', async (message, metadata) => {
await processOrder(message);
}, { limit: 10 }); // max 10 messages per poll (max allowed: 10)
if (!result.ok && result.reason === 'empty') {
// No messages available
}
```
### Custom Region Client
```ts
import { QueueClient } from '@vercel/queue';
const queue = new QueueClient({ region: 'sfo1' });
export const { send, handleCallback } = queue;
```
## Transports
```ts
import { QueueClient, BufferTransport, StreamTransport } from '@vercel/queue';
```
| Transport | Description |
|-----------|-------------|
| `JsonTransport` | Default; JSON serialization |
| `BufferTransport` | Raw binary data |
| `StreamTransport` | `ReadableStream` for large payloads |
## Queues vs Workflow vs Cron
| Need | Use | Why |
|------|-----|-----|
| Event delivery, fan-out, routing control | **Queues** | Topics, consumer groups, message-level retries |
| Stateful multi-step business logic | **Workflow** | Deterministic replay, pause/resume (built **on top of** Queues) |
| Recurring scheduled tasks | **Cron Jobs** | Simple, no message passing |
| Delayed single execution with deduplication | **Queues** (`delaySeconds` + `idempotencyKey`) | Precise delay with guaranteed delivery |
| Async processing from external systems | **Queues** (poll mode) | Consume from any infrastructure, not just Vercel |
## Key Limits
| Resource | Default / Max |
|----------|---------------|
| Message retention | 60s – 24h (default 24h) |
| Max message size | 100 MB |
| Messages per receive | 1–10 (default 1) |
| Visibility timeout | 0s – 60 min (default 5 min SDK / 60s API) |
| Topics per project | Unlimited |
| Consumer groups per topic | Unlimited |
## Deployment Behavior
Topics are **partitioned by deployment ID** by default in push mode. Messages are delivered back to the same deployment that published them — natural schema versioning with no cross-version compatibility concerns.
## Observability
The **Queues** observability tab (Project → Observability → Queues) provides real-time monitoring:
| Level | Metrics |
|-------|---------|
| **Project** | Messages/s, Queued, Received, Deleted (with sparkline trends) |
| **Queue** | Throughput per second (by consumer group), Max message age |
| **Consumer** | Processed/s, Received, Deleted (per consumer group) |
Use **Max message age** to detect consumer lag — if the oldest unprocessed message keeps growing, a consumer group may be falling behind.
## Local Development
Queues work locally — when you `send()` messages in development mode, the SDK sends them to the real Vercel Queue Service, then invokes your registered `handleCallback` handlers directly in-process. No local queue infrastructure needed.
## Authentication
The SDK authenticates via **OIDC** (OpenID Connect) tokens automatically on Vercel. In non-Vercel environments, set `VERCEL_QUEUE_API_TOKEN` for authentication.
## When to Use
- Defer expensive work (emails, PDFs, external API calls)
- Absorb traffic spikes with controlled processing rate
- Guarantee delivery even if function crashes
- Fan-out same events to multiple independent pipelines
- Deduplicate messages via idempotency keys
## When NOT to Use
- Multi-step orchestration with state → use Workflow
- Recurring schedules → use Cron Jobs
- Synchronous request/response → use Functions directly
- Cross-region messaging → messages sent to one region cannot be consumed from another
## References
- 📖 docs: https://vercel.com/docs/queues
- 📖 quickstart: https://vercel.com/docs/queues/quickstart
- 📖 API reference: https://vercel.com/docs/queues/api