Relay is a queue and scheduler you call like a function. Durable retries, observability, and zero servers to babysit — add it to your app in a few lines.
$ npm i @relay/sdk
# enqueue a job in one line
await relay.run("send-email", { to: user.email });Works with any Node, Bun, or edge runtime.
Durable, observable, and pleasant to use.
Exponential backoff, dead-letter queues, and replay — built in.
Human-readable schedules.
Every run, traced.
Your job payloads are type-checked from enqueue to handler — no stringly-typed surprises.
Per-queue concurrency control.
Define a handler, enqueue from anywhere — payloads are type-checked end to end.
import { defineJob } from "@relay/sdk";
export const sendWelcome = defineJob({
name: "send-welcome",
retries: 5,
run: async ({ userId }: { userId: string }) => {
const user = await db.users.find(userId);
await email.send(user.email, "welcome");
},
});
// elsewhere — fully typed, no stringly-typed payloads
await sendWelcome.enqueue({ userId: user.id });Same code runs on Node, Bun, and the edge.
Drops into the stack you already run
Start free, no card. A run is one job attempt that starts — retries don't multiply your bill.
For apps in production.
The honest answers — pricing, self-host, migration, and what happens at the limit.
Both. The SDK and worker are open-source (Apache-2.0) and run against your own Postgres and Redis — no phone-home. The hosted plans add the dashboard, retention, and on-call; you can start self-hosted and move later, or never.
Because your whole team benefits from one queue, but your bill should track what you actually push through it. A run is one job attempt that starts; retries of the same job don't multiply your count. No per-developer tax.
Point your existing handlers at defineJob and enqueue through the SDK — the shape is deliberately familiar. Run both queues in parallel during cutover; Relay never touches the old one. Most teams migrate one queue a day, not all at once.
At-least-once, like every honest queue — a handler can run twice if a worker dies mid-run. Make handlers idempotent (each job carries a stable key you can dedupe on) and you get exactly-once behavior without us pretending the network is reliable.
Enqueues keep succeeding — nothing drops on the floor. Overflow jobs queue and we email you to upgrade; they run as soon as you do. We'd rather you notice a bill than lose a job.
Add Relay in a few lines and watch your queue actually behave.
Free forever for small projects · no card required · Apache-2.0 SDK