Skip to main content
npm i @asyncbase/sdk
# or: bun add, pnpm add, yarn add
Plain fetch under the hood, so it also runs in Cloudflare Workers, Deno, and the browser (server-side only — never ship a key to the browser).

Configure

.env.local
ASYNCBASE_KEY=sk_live_...

Minimal example

import { Queue } from "@asyncbase/sdk"

const q = new Queue(process.env.ASYNCBASE_KEY!)

// Send
await q.send("emails", { to: "a@b.com", subject: "hi" }, { delay: "30s" })

// Consume
for await (const msg of q.consume("emails", { group: "workers" })) {
  try { await handle(msg.payload); await msg.ack() }
  catch { await msg.nack() }
}

Next.js — enqueue from a route handler

app/api/send-email/route.ts
import { Queue } from "@asyncbase/sdk"

const q = new Queue(process.env.ASYNCBASE_KEY!)

export async function POST(req: Request) {
  const body = await req.json()
  const r = await q.send("emails", body)
  return Response.json({ id: r.id })
}
Run the consumer as a separate Node process (Fly Machine, Railway worker). Don’t put it in a Vercel serverless function — it will time out.

NestJS — consumer as a service

@Injectable()
export class QueueConsumer implements OnApplicationBootstrap, OnApplicationShutdown {
  private readonly q = new Queue(process.env.ASYNCBASE_KEY!)
  private readonly abort = new AbortController()
  private loop?: Promise<void>

  onApplicationBootstrap() { this.loop = this.run() }
  async onApplicationShutdown() { this.abort.abort(); await this.loop }

  private async run() {
    for await (const msg of this.q.consume("emails", {
      group: "nest-workers", signal: this.abort.signal,
    })) {
      try { await handle(msg.payload); await msg.ack() }
      catch { await msg.nack() }
    }
  }
}

TypeScript types

import type {
  SendOptions, PullOptions, ConsumeOptions, ConsumedMessage,
  NackResponse, HeartbeatResponse,
  Message, EnqueueRequest, EnqueueResponse,
  DequeueResponse, AckResponse, ErrorCode, ErrorEnvelope,
} from "@asyncbase/sdk"

Error handling

import { AsyncBaseError } from "@asyncbase/sdk"

try {
  await q.send("emails", payload)
} catch (err) {
  if (err instanceof AsyncBaseError && err.code === "RATE_LIMITED") {
    await new Promise(r => setTimeout(r, 1000))
  } else throw err
}