Enqueue a job
Call a discovered queue from Vite or Nitro server code and return a clear application response.
This guide defines a welcome-email queue, then calls it from a server route. It assumes Queue is already registered in Vite or Nitro config.
Define the queue
Create one queue definition with the payload shape the producer will send.
server/queues/welcome-email.ts
import { defineQueue } from '@vitehub/queue'
export type WelcomeEmailPayload = {
email: string
template: 'default' | 'vip'
}
export default defineQueue<WelcomeEmailPayload>(async (job) => {
console.log(`Send ${job.payload.template} welcome email to ${job.payload.email}`)
})
Call pattern
Every producer follows the same shape:
- Read or build a payload.
- Call
runQueue(name, payload). - Return the
QueueSendResult.
server/api/welcome.post.ts
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 }
})
Add delivery options
Use an enqueue envelope when the send needs provider options:
const result = await runQueue('welcome-email', {
id: 'welcome-email-1',
payload: {
email: 'ava@example.com',
template: 'vip',
},
delaySeconds: 30,
})
Keep provider-specific fields out of shared helper code unless the helper is intentionally provider-specific.
Defer the enqueue call
Use deferQueue() when the route does not need the queued result:
import { deferQueue } from '@vitehub/queue'
export default defineEventHandler(() => {
deferQueue('welcome-email', {
email: 'ava@example.com',
template: 'default',
})
return { ok: true }
})
The runtime uses waitUntil() when available, so the response can finish while the enqueue promise continues.
Verify the route
curl -X POST http://localhost:3000/api/welcome \
-H 'content-type: application/json' \
-d '{"email":"ava@example.com","template":"vip"}'
Expected response:
{
"ok": true,
"result": {
"status": "queued",
"messageId": "queue_7f1b6f8e-7b5c-4c5e-b3a1-8d6a4b3d4c2a"
}
}
Avoid these mistakes
| Mistake | Fix |
|---|---|
Expecting runQueue() to return the handler result | Treat it as a provider send result only. |
| Calling a name that does not match discovery | Check the queue file path and generated queue name. |
| Passing provider-only fields everywhere | Keep contentType, idempotencyKey, region, and retentionSeconds close to provider-aware code. |

