Compatibility
Node.js 22+, PostgreSQL 15+, no extensions, and an exact-match schema — what is tested and what that means.
You need to know two things before adopting a queue: will it run on your stack, and what does "supported" actually prove. Workhorse requires Node.js 22 or newer and PostgreSQL 15 or newer, and a version counts as supported only when continuous integration runs the full suite against it on every change. Workhorse may run elsewhere, but untested versions do not carry the same correctness evidence.
The tested matrix
CI exercises every combination of Node.js 22 and 24 with PostgreSQL 15, 16, 17, and 18. The
runtime exports the same boundary to tooling: MINIMUM_NODE_MAJOR is 22, MINIMUM_POSTGRES_MAJOR
is 15, and SUPPORTED_NODE_MAJORS and SUPPORTED_POSTGRES_MAJORS list the CI majors. A test in
the repository fails whenever the CI matrix, the package engines fields, and these constants
drift apart, so the published numbers are always the exercised numbers. The
compatibility matrix
tracks them as they change.
You can classify a connected server at runtime. readPostgresSupport reports whether it is tested,
merely newer than tested, or below the minimum; assertSupportedPostgres refuses to proceed below
the minimum before schema installation can fail confusingly.
import { readPostgresSupport } from "@stablemates/workhorse";
const support = await readPostgresSupport(pool);
console.log(support); // { major: 17, version: "17.2 …", supported: true, tested: true }A server newer than the tested majors is reported as supported but untested rather than rejected — refusing to run on a release that did not exist at publish time would strand you on every PostgreSQL upgrade.
Plain PostgreSQL, no extensions
Workhorse requires only stock PostgreSQL with its default procedural language. It installs no extension, so it runs on managed services — RDS, Cloud SQL, Neon, Supabase — without an allowlist conversation.
Published packages are ESM with TypeScript declarations. Plain JavaScript uses the same runtime; CommonJS loading is outside the supported package format.
Match the schema exactly
The PostgreSQL schema is the durable protocol. The application runtime and the installed schema must agree exactly, because mismatched workers could interpret lifecycle state differently.
Call assertSchemaCompatible during startup. A mismatch should fail the process before it claims
or changes work.
Use installSchema for a fresh database and migrateSchema for an installed schema. The migration
entrypoint applies immutable, forward-only steps from the supported baseline and refuses missing,
older-than-baseline, or newer schemas before changing them. Each step commits one version in its
own transaction behind an advisory lock and rolls back atomically on failure. Development schemas
at versions retired before the baseline still require a reset.
The dashboard transport has its own dashboard/v1 contract. TypeScript, Python, and Go backends
use its shared procedure schemas, HTML placeholders, request order, and HTTP fixtures. Embed a
shipped backend for operator access; use Queue for application operations and Admin for
operator integrations.
Clients in other languages use the versioned SQL functions and JSON fixtures under protocol/v1/
as their compatibility boundary. The fixtures require clients to reject an incompatible schema or
protocol before mutation, then verify canonical requests, results, transitions, and structured
errors. See Language clients for the ownership split.
The Python stablemates-workhorse package supports Python 3.10 through 3.14. It uses Psycopg synchronously
or asynchronously and asyncpg asynchronously. Every worker runtime delegates cron evaluation to
the versioned PostgreSQL functions and each definition's stored IANA timezone. Its release test
installs the built wheel and source distribution bare, with the compatibility psycopg extra, and
with the asyncpg extra. It runs the public examples and checks the active Python and PostgreSQL
versions against the declared matrix. The package version floats
independently from the TypeScript packages because schema and SQL protocol versions define their
compatibility.
Bun and Deno
Bun and Deno hold a smoke-tested tier, not support. On pull requests, pushes to main, and nightly
runs, CI executes an enqueue, claim, and complete round-trip through the built package against
PostgreSQL under the latest release of each; SMOKE_TESTED_JS_RUNTIMES exports the tier to tooling. A green lane proves the driver
connects, the schema installs, and one job completes there — the full test suites run under
Node.js only, so no stronger claim is made. Known runtime-specific findings live in the
compatibility matrix.
Serverless platforms have a separate lifetime and connectivity matrix. Read Serverless and edge before choosing where producers and worker processes run.
Release each package line from its own changelog
Core and its integration packages release together. Keep their versions aligned so adapters, dashboard contracts, and exported types describe the same source revision. The changelog records breaking changes and the schema version each release requires.
The first public beta is 0.1.0-beta.1 for npm and Go, and 0.1.0b1 for Python. Any 0.x minor
release may break compatibility, including the schema. There is no upgrade path between 0.x
releases; ordered migrations begin at 1.0.0.
The dashboard and core may use different patch releases within the same minor line. The dashboard server reads core-owned versioned views and functions, so a core patch remains compatible when its migration preserves those contracts.
stablemates-workhorse releases from its own python/vX.Y.Z tag after its format, lint, type, test, packed,
and site lanes pass. Its tag must match python/pyproject.toml and python/CHANGELOG.md. The release
builds a source distribution and universal wheel, then PyPI trusted publishing uploads both.
The Go module records independent versions in go/CHANGELOG.md. The repository release script
runs the full gate before it creates and pushes the matching go/vX.Y.Z tag.
GitHub Actions remain disabled while the repository is private, so these release paths are defined
but must not run until that restriction is lifted. Once public, pull requests run support-boundary
pairs and main plus nightly runs execute the full matrix. Branch protection requires the stable
CI / required check, and protected npm and PyPI environments require a second person to approve
publication.
One honest caveat: support proves correctness under the tested matrix. It does not promise a throughput level for your database, payloads, handlers, or deployment topology.
Next
- Installation — install and check the schema deliberately
- Language clients — implement the versioned SQL protocol
- Limitations — compare support with your application requirements
- Deployment and operations — enforce compatibility before workers start
Exact database requirements and schema compatibility boundary: architecture reference.