Skip to content
'; user_status_content.firstChild.appendChild(avatarContainer); } else { // Placeholder for LoggedOutUserMenu let loggedOutContainer = document.createElement('div'); // if LoggedOutUserMenu fallback let userBtn = document.createElement('button'); userBtn.style.width = "33px"; userBtn.style.height = "33px"; userBtn.style.display = "flex"; userBtn.style.alignItems = "center"; userBtn.style.justifyContent = "center"; userBtn.style.color = "var(--ds-gray-900)"; userBtn.style.border = "1px solid var(--ds-gray-300)"; userBtn.style.borderRadius = "100%"; userBtn.style.cursor = "pointer"; userBtn.style.background = "transparent"; userBtn.style.padding = "0"; // user icon ( from geist) let svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svg.setAttribute('data-testid', 'geist-icon'); svg.setAttribute('height', '16'); svg.setAttribute('stroke-linejoin', 'round'); svg.setAttribute('style', 'color:currentColor'); svg.setAttribute('viewBox', '0 0 16 16'); svg.setAttribute('width', '16'); let path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); path.setAttribute('fill-rule', 'evenodd'); path.setAttribute('clip-rule', 'evenodd'); path.setAttribute('d', 'M7.75 0C5.95507 0 4.5 1.45507 4.5 3.25V3.75C4.5 5.54493 5.95507 7 7.75 7H8.25C10.0449 7 11.5 5.54493 11.5 3.75V3.25C11.5 1.45507 10.0449 0 8.25 0H7.75ZM6 3.25C6 2.2835 6.7835 1.5 7.75 1.5H8.25C9.2165 1.5 10 2.2835 10 3.25V3.75C10 4.7165 9.2165 5.5 8.25 5.5H7.75C6.7835 5.5 6 4.7165 6 3.75V3.25ZM2.5 14.5V13.1709C3.31958 11.5377 4.99308 10.5 6.82945 10.5H9.17055C11.0069 10.5 12.6804 11.5377 13.5 13.1709V14.5H2.5ZM6.82945 9C4.35483 9 2.10604 10.4388 1.06903 12.6857L1 12.8353V13V15.25V16H1.75H14.25H15V15.25V13V12.8353L14.931 12.6857C13.894 10.4388 11.6452 9 9.17055 9H6.82945Z'); path.setAttribute('fill', 'currentColor'); svg.appendChild(path); userBtn.appendChild(svg); loggedOutContainer.appendChild(userBtn); loggedOutContainer.style.display = 'flex'; loggedOutContainer.style.gap = '8px'; loggedOutContainer.style.alignItems = 'center'; user_status_content.firstChild.appendChild(loggedOutContainer); } })();
Menu

Quickstart

Last updated February 27, 2026

This guide shows how to send your first queue message and process it with the @vercel/queue SDK.

AI Assistance

Help me set up Vercel Queues in this project. First, make sure the Vercel CLI is installed (`npm i -g vercel`). If I'm using Claude Code or Cursor, install the Vercel Plugin (`npx plugins add vercel/vercel-plugin`). For other agents, install Vercel Skills (`npx skills add vercel-labs/agent-skills`). Then: 1. Install @vercel/queue. 2. Run `vercel link` and `vercel env pull` to get OIDC credentials. 3. Create a producer route that sends messages to an 'orders' topic using the send function. 4. Create a consumer route at app/api/queues/fulfill-order/route.ts that processes messages using handleCallback. 5. Configure vercel.json with a queue trigger for the consumer route. 6. Test locally with `vercel dev`.

In this quickstart:

  • Your API route acts as a producer. It sends work to a queue topic.
  • The topic (orders) stores messages durably until a consumer processes them.
  • A second route acts as a consumer. Vercel invokes it automatically in push mode.
  • A Vercel account
  • Vercel CLI installed (npm i -g vercel)
  • Node.js 22+
  1. Install @vercel/queue so your app can send messages and receive push callbacks.

    Terminal
    pnpm i @vercel/queue
  2. The SDK authenticates via OIDC. Link your project if you haven't already, then pull environment variables so the SDK can authenticate during local development:

    Terminal
    vercel link
    vercel env pull

    This creates a .env.local file containing the OIDC tokens the SDK needs to connect to Vercel Queues from your machine. Without it, local calls to send and handleCallback can't authenticate. When you deploy to Vercel, authentication is automatic and no environment setup is needed.

  3. Import send directly from @vercel/queue and call it from any server-side context: a route handler, a Server Action, a Workflow step, or an error handler.

    app/cart/checkout/route.ts
    import { send } from '@vercel/queue';
     
    export async function POST(request: Request) {
      const order = await request.json();
      const { messageId } = await send('orders', order);
      return Response.json({ messageId });
    }
  4. app/api/queues/fulfill-order/route.ts
    import { handleCallback } from '@vercel/queue';
     
    export const POST = handleCallback(async (order, metadata) => {
      // await chargePayment(order);
      // await sendConfirmationEmail(order);
      console.log('Fulfilling order', metadata.messageId, order);
    });
  5. Add a consumer trigger to wire your route to a topic. This makes the route private: it has no public URL and only Vercel's queue infrastructure can invoke it.

    vercel.json
    {
      "functions": {
        "app/api/queues/fulfill-order/route.ts": {
          "experimentalTriggers": [{ "type": "queue/v2beta", "topic": "orders" }]
        }
      }
    }

The top-level send and handleCallback use an auto-configured default client. The region is detected from the VERCEL_REGION environment variable, which Vercel sets on every deployment. If the region can't be detected (for example, during local development), it falls back to iad1.

To target a specific region when sending, pass the region option:

await send('orders', payload, { region: 'sfo1' });

If your handler crashes after charging payment but before sending the email, Vercel redelivers the message so the email still goes out. If the email call fails, the message comes back and your handler runs again. Make each step idempotent (for example, pass an idempotency key to your payment provider) so retries are safe.

This works locally with next dev or vercel dev so you can test without deploying.

  1. Installed the SDK: Added @vercel/queue to your project.
  2. Created a producer: Published messages to the orders topic.
  3. Configured a consumer: Registered a push trigger and handler to process messages.

Was this helpful?

supported.