Queue
@vitehub/queue gives Vite and Nitro apps one way to define background job handlers, enqueue work from request code, and deliver those jobs through Cloudflare Queues or Vercel Queue.
Use Queue when the request should return before the work finishes. The application keeps a small typed enqueue call. The provider handles delivery, retry behavior, and callback execution.
import { runQueue } from '@vitehub/queue'
import type { WelcomeEmailPayload } from '../queues/welcome-email'
export default defineEventHandler(async (event) => {
const payload = await readBody<WelcomeEmailPayload>(event)
const result = await runQueue('welcome-email', payload)
return { ok: true, result }
})
import { defineQueue } from '@vitehub/queue'
export type WelcomeEmailPayload = {
email: string
template: 'default' | 'vip'
}
export default defineQueue<WelcomeEmailPayload>(async (job) => {
console.log(`Processing ${job.payload.template} welcome email for ${job.payload.email}`)
})
{
"ok": true,
"result": {
"status": "queued",
"messageId": "queue_7f1b6f8e-7b5c-4c5e-b3a1-8d6a4b3d4c2a"
}
}
What Queue solves
Inline request work is the simplest option until the work can happen after the response, needs provider-managed retry, or should move behind a named background boundary.
Queue moves that work behind a discovered definition:
Fast request paths
Portable producers
runQueue() and deferQueue() calls the same while provider setup stays in framework config.Provider delivery
Discovered handlers
One portable flow
The same shape works across providers:
- Register the Vite plugin or Nitro module.
- Choose
cloudflareorvercelinqueue.provider. - Define a named queue with
defineQueue(). - Enqueue work with
runQueue(name, payload). - Use
deferQueue(name, payload)when dispatch can happen after the response.
Discovery model
Vite discovers queue definitions from src/**/*.queue.ts.
The queue name comes from the path under src, without the .queue suffix. src/email/welcome.queue.ts becomes email/welcome.
Supported providers
Start here
Start with Quickstart for the smallest complete setup. Use the primitive comparison when you are deciding between KV, Blob, Queue, Sandbox, or inline request code.

