Workhorse
Reference

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


Exact database requirements and schema compatibility boundary: architecture reference.