Limitations
What Workhorse does not do today — with the workaround for each boundary that has one.
Choosing infrastructure means knowing what it will not do before it is load-bearing. Workhorse fits PostgreSQL-backed applications that accept at-least-once handlers and exact schema compatibility. This page lists every boundary honestly, with the workaround where one exists.
Workhorse is a public beta. It is usable for evaluation and early production adoption, but any minor release may break compatibility, including the schema. There is no upgrade path between 0.x releases; ordered migrations begin at 1.0.0.
Workflow orchestration lives in handlers
Workhorse supports job prerequisites, fan-in policies, child jobs, external signals, and human decisions. It does not provide a separate workflow definition language or graph deployment model.
Workaround: compose those durable boundaries in ordinary handler code. If a workflow must be defined and deployed independently of application code, use a workflow system on top or instead.
No cross-queue concurrency policies
Concurrency and rate-limit policies are scoped to one queue. You cannot express "at most 10 active jobs across these three queues".
Workaround: route work that shares a budget onto one queue, and use concurrencyKey for per-tenant
budgets within it.
Cancellation is cooperative, never forced
JavaScript cannot be preempted safely, so Workhorse never kills a running handler. Cancellation,
deadlines, and execution timeouts abort the handler's AbortSignal; the code runs until it
observes that signal or loses its lease. Process shutdown likewise drains handlers rather than
preempting them.
Workaround: pass context.signal into every cancelable operation and check it between units of
work. If work truly requires forced termination, isolate it in a process you can kill and make its
effects recoverable.
External effects are at least once
PostgreSQL cannot commit an HTTP call, email, or payment in the same transaction as job completion. A worker can perform the effect and die before recording success, so the effect can happen again. Enqueue idempotency keys deduplicate job identities; they cannot make one accepted handler execute exactly once. Redrive is another at-least-once execution.
Workaround: this is the designed model, not an accident. Wrap each effect in a named checkpoint
so completed stages never rerun, and give the provider an idempotency key — the job ID or a domain
ID — to close the final gap between effect and checkpoint commit.
Schema and terminal tooling ship in TypeScript
Python and Go ship transactional queue clients, complete worker runtimes, and Admin operator
clients over the shared SQL protocol. Schema installation and migration (migrateSchema) and the
workhorse admin CLI and TUI ship only in the TypeScript package, so a polyglot deployment keeps
that package available for those operations.
No public HTTP ingress
Nothing accepts jobs over HTTP. Producers need a database connection and the SDK.
Workaround: enqueue from your own API routes — which is also where transactional enqueue with your business writes lives.
Retired pre-release schemas have no upgrade source
migrateSchema applies ordered, forward-only migrations from the supported baseline. Schemas at
versions retired before that baseline have no migration history, so operators must reset those
development schemas instead of upgrading them.
Workaround: keep schema changes in the deployment path and call migrateSchema — or
workhorse schema migrate — before starting a new runtime. The changelog records each release's
required schema version.
Dashboard authentication has one built-in role
The standalone dashboard provides one administrator login with expiring sessions, logout, credential rotation, and login throttling. It does not provide multiple users, roles, SSO, or tenant isolation.
Workaround: mount the dashboard behind your application's existing authentication boundary and
return its verified operator from authorize.
Next
- Core concepts — the guarantees behind these boundaries
- Compatibility — the tested runtime and schema matrix
- Deployment and operations — design recovery around cooperative processes
Exact delivery guarantees, timing bounds, and unsupported protocol behavior: architecture reference.