Skip to content

State Adapters

State adapters abstract database operations for job persistence. They handle job creation, status transitions, leasing, and queries. Queuert ships three options: PostgreSQL for production workloads, SQLite for lightweight or embedded use cases, and an in-process adapter for single-process apps that don’t need persistence.

Package: @queuert/postgres

Recommended for production. Supports horizontal scaling with database-level locking (FOR UPDATE SKIP LOCKED), writeable CTEs for atomic batch operations, and all Queuert features including concurrent multi-worker deployments.

Terminal window
npm install @queuert/postgres
ORM / DriverExample
Raw pgstate-postgres-pg
postgres.jsstate-postgres-postgres-js
Prismastate-postgres-prisma
Drizzlestate-postgres-drizzle
Kyselystate-postgres-kysely

A State Provider bridges your database client (Kysely, Drizzle, Prisma, raw drivers, etc.) with the state adapter. You implement a simple interface that provides transaction handling and SQL execution:

  • withTransaction — Manages connection acquisition and transaction lifecycle. The callback receives a transaction context representing an active transaction.
  • executeSql — Executes SQL statements. When a transaction context is provided, uses that connection; when omitted, acquires and releases its own connection from the pool.

Each example linked above demonstrates a complete State Provider implementation for its corresponding ORM or driver.

You’re not limited to the ORMs and drivers listed here — you can write a provider for any database client that supports the same semantics, or implement the StateAdapter interface from scratch for an entirely different database engine. See Custom Adapters for a walkthrough.

Queuert ships a conformance runner that exercises the full state adapter suite against any provider you build. Embed it in a single test() block from your test framework to validate correctness:

import { runStateAdapterConformance } from "queuert/conformance";
test("my provider passes state adapter conformance", async () => {
await runStateAdapterConformance(async () => ({
stateAdapter,
poisonTransaction,
reset: async () => { /* truncate tables */ },
dispose: async () => { /* close connections */ },
}));
}, 300_000);

Every example’s src/provider.spec.ts is a working template. See the Custom Adapters guide for a full walkthrough and the Conformance reference for the complete API.

For horizontal scaling, multiple worker processes can share the same PostgreSQL database. Workers coordinate via FOR UPDATE SKIP LOCKED — no external coordination required.

See state-postgres-multi-worker for an example spawning multiple worker processes sharing a PostgreSQL database.