https://github.com/kvet/queuert
Control flow library for your persistency layer driven applications
https://github.com/kvet/queuert
background-jobs job-queue mongodb nodejs postgresql queue sqlite transactional-outbox typescript workflow
Last synced: 27 days ago
JSON representation
Control flow library for your persistency layer driven applications
- Host: GitHub
- URL: https://github.com/kvet/queuert
- Owner: kvet
- License: mit
- Created: 2025-10-28T06:50:21.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2026-05-14T18:58:33.000Z (about 1 month ago)
- Last Synced: 2026-05-14T19:05:39.393Z (about 1 month ago)
- Topics: background-jobs, job-queue, mongodb, nodejs, postgresql, queue, sqlite, transactional-outbox, typescript, workflow
- Language: TypeScript
- Homepage: https://kvet.github.io/queuert/
- Size: 3.89 MB
- Stars: 20
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Queuert
[](https://www.npmjs.com/package/queuert)
[](https://github.com/kvet/queuert/blob/main/LICENSE)
**Durable, typed job chains that commit with your database transactions.**
Queuert is a job-chain library — durable, typed background work in your database. Job chains compose like Promise chains (`.then`, `Promise.all`), but they survive crashes and commit with your transactions. Postgres or SQLite, no Redis required, no separate server.
[**Documentation**](https://kvet.github.io/queuert/) | [**Getting Started**](https://kvet.github.io/queuert/getting-started/introduction/) | [**Comparison**](https://kvet.github.io/queuert/comparison/)
## How it looks
Define a typed chain of jobs. Each step's input, output, and continuation are inferred — wrong-shape continuations are compile errors.
```ts
const jobTypes = defineJobTypes<{
"provision-account": {
entry: true;
input: { userId: number };
continueWith: { typeName: "send-welcome-email" };
};
"send-welcome-email": {
input: { userId: number; accountId: string };
continueWith: { typeName: "sync-to-crm" };
};
"sync-to-crm": {
input: { userId: number; accountId: string };
};
}>();
```
Start the chain _inside_ your DB transaction. If the transaction rolls back, the chain is never created. No outbox glue, no dual-write window.
```ts
const client = await createClient({ stateAdapter, jobTypes });
await withTransactionHooks(async (transactionHooks) =>
db.transaction(async (tx) => {
const user = await tx.users.create({ name: "Alice", email: "alice@example.com" });
await client.startChain({
tx,
transactionHooks,
typeName: "provision-account",
input: { userId: user.id },
// ↑ wrong shape here is a compile error
});
}),
);
```
Each handler continues with the next step. The compiler enforces that `continueWith` matches the declared next type's input.
```ts
const worker = await createInProcessWorker({
client,
processors: createProcessors({
client,
jobTypes,
processors: {
"provision-account": {
attemptHandler: async ({ job, complete }) => {
const accountId = await provisionAccount(job.input.userId);
return complete(async ({ continueWith }) =>
continueWith({
typeName: "send-welcome-email",
input: { userId: job.input.userId, accountId },
// ↑ missing accountId would be a compile error
}),
);
},
},
// ...handlers for "send-welcome-email" and "sync-to-crm"
},
}),
});
const stop = await worker.start();
```
## Where it fits
Background-work libraries trade off across two axes: what storage tier they own, and what shape of work they model.
| | Queuert | pg-boss | BullMQ | Temporal | Inngest |
| --------------------- | --------------------- | ------------------- | ----------------- | ----------------- | ----------------- |
| Category | Job-chain library | Job queue | Job queue | Workflow platform | Workflow platform |
| Storage | Your DB (PG / SQLite) | Postgres | Redis | Separate cluster | Inngest server |
| Transactional enqueue | ✅ structural | 🟡 per-call adapter | ❌ app discipline | ❌ app discipline | ❌ app discipline |
| Operate a server? | No | No | Redis | Yes | Yes |
Queuert sits between job queues and workflow engines. A one-job chain _is_ a queue; a multi-step chain with blockers is closer to a workflow. Neither label fully fits, which is why the canonical term is "job-chain library."
For deeper comparisons, see the [docs site](https://kvet.github.io/queuert/comparison/) — one page per neighbor.
## Why Queuert
- **Transactional, both ends.** Enqueue commits inside your DB transaction; handler completion and next-step `continueWith` commit in the same transaction as your domain writes. For DB-bound work, no outbox at enqueue and no idempotency-key ritual at processing — both halves are structural.
- **Typed job chains.** Inputs, outputs, continuations, and blockers infer end-to-end via `defineJobTypes`. Refactoring is compiler-checked.
- **Lives in your database.** Postgres or SQLite. No Redis required, no workflow server, no separate persistence tier to operate.
- **Sub-second wakeup.** `LISTEN/NOTIFY` (or Redis pub/sub, or NATS) wakes workers when a row commits — not on a polling timer.
- **Schedule for later.** Delay a chain to a specific time or duration. Schedule retries with backoff. Future work, no extra infrastructure.
- **Deduplication.** Pass a deduplication key on enqueue. Identical keys collapse to a single chain — at-most-once, by construction.
- **Lean and battle-tested.** Zero runtime dependencies in every package — driver libraries are `peerDependencies` you already own. 4,000+ tests across adapters and a shared conformance suite every state and notify adapter must pass.
## Installation
```bash
# Core (required)
npm install queuert
# State adapter (pick one)
npm install @queuert/postgres # PostgreSQL — recommended for production
npm install @queuert/sqlite # SQLite (experimental)
# Notify adapter (optional, for sub-second wakeup)
npm install @queuert/redis # Redis pub/sub
npm install @queuert/nats # NATS pub/sub (experimental)
# Or use PostgreSQL LISTEN/NOTIFY via @queuert/postgres — no extra infra
# Dashboard (optional, experimental)
npm install @queuert/dashboard
# Observability (optional)
npm install @queuert/otel
```
## Learn more
- [Getting Started](https://kvet.github.io/queuert/getting-started/introduction/)
- [Chain Patterns](https://kvet.github.io/queuert/guides/chain-patterns/)
- [Transaction Hooks](https://kvet.github.io/queuert/guides/transaction-hooks/)
- [Job Blockers](https://kvet.github.io/queuert/guides/job-blockers/)
- [Comparison with other libraries](https://kvet.github.io/queuert/comparison/)
- [Benchmarks](https://kvet.github.io/queuert/benchmarks/)
- [API Reference](https://kvet.github.io/queuert/reference/queuert/client/)
## License
MIT.