Workhorse
Operating

Operations

A map of Workhorse's operational surface — which page owns each concern, and the fleet controls that live nowhere else.

Running Workhorse in production splits into a few distinct concerns: supervising processes, maintaining the database, controlling the fleet, and watching health. Each has its own page. This page is the map, plus the fleet controls that belong to no single sibling.

Process supervision

Worker processes owns startup, termination signals, drain behavior, readiness and liveness probes, and database pool ownership. Deploy workers there first; every other concern assumes a supervised process already exists.

Database maintenance

Maintenance and retention owns promotion, expired-lease recovery, history partitions, cleanup, retention policy, and the health budgets that reveal lag. Workers drive this work automatically; the page explains how to observe and tune it.

Rolling statistics

The dashboard reads time-window statistics from minute, hour, or day summaries chosen for the requested horizon. Queue-wait percentiles merge a logarithmic sketch across those summaries, so long-window reads stay bounded without keeping every sample. Worker and tag breakdowns remain live queries because their data-controlled cardinality would make aggregate storage unbounded.

A background rollup summarises fully elapsed periods and records how far it got as a watermark. Window reads combine pre-computed rows below the watermark with live computation above it, so a window is correct the instant a job runs; a lagging rollup means a longer live section and a slower query, never a wrong answer. Retention never deletes history the rollup has not summarised yet, so a stuck rollup surfaces as growing lag on the health page, not as a hole in your numbers.

OpenTelemetry

TypeScript, Python, and Go workers emit the same worker span and metric names, so one set of dashboards can cover a mixed-language fleet. A Go worker restores the W3C context stored by a TypeScript enqueue, which keeps the handler in the enqueue trace across processes.

The Python package exposes telemetry through its optional telemetry extra. Applications supply OpenTelemetry providers and exporters, while Go applications also pass an application-owned log/slog logger through WorkerOptions.Logger. Without a configured provider, telemetry stays inert and worker behavior is unchanged.

Worker metrics use queue, job type, and a closed outcome vocabulary. Job IDs remain on sampled spans and structured events, while payloads, results, and error messages never enter telemetry.

Worker metrics cover only what each process does. Database-wide state — queue depth, the age of ready work, expired leases, paused queues, and fleet capacity — needs a dedicated collector. Run WorkhorseMetricsObserver against a pool, or registerQueueMetrics through a Queue when you also want policy and orchestration gauges, in one long-lived service per database and telemetry resource. Do not start a collector in every worker replica: each one reads the same rows, so replicas would export duplicate gauges and add unnecessary queries.

Fleet controls

Every worker registers itself in PostgreSQL on its registryIntervalMs cadence — 5 seconds by default, 0 to opt out. That registry is how you see and steer a fleet you do not host:

const admin = new Admin(pool);
const workers = await admin.listWorkers();
await admin.setWorkerPaused("billing-worker-1", true, {
  actor: actor.email, reason: "investigating slow provider", requestId: incidentId,
});

Pause is cooperative: the worker notices on its next registry refresh, stops asking for jobs, and any in-flight handler runs to completion. The pause is scoped to the running process — a restarted worker comes back running, so a forgotten pause can never idle a future deployment. Use queue pause when work must stop durably.

Use AsyncAdmin.from_psycopg or AsyncAdmin.from_asyncpg when the operator process is async.

Job controls

Cancellation owns durable requests to stop one job. Dead letters and redrive owns replaying jobs that failed terminally.

Inspection and authorization

Queries and timelines owns read-only inspection: point lookups, bounded listings, lifecycle evidence, and queue.health. Dashboard renders the same read models for humans and owns the authorization boundary for operator mutations. Embedded hosts return a verified principal through authorize, while the standalone dashboard can enable its built-in administrator login.

Terminal operations

The packaged CLI carries the same operator surface into a shell. workhorse admin inspects jobs, queues, schedules, failures, workers, and maintenance state — as aligned tables for humans, or with --json as the exact objects the TypeScript operator API returns:

workhorse admin queues
workhorse admin failures --queue billing --json | jq '.items[].jobId'

Guarded commands — admin cancel, admin redrive, admin pause, admin resume — refuse to run until the target database is named explicitly with --env, verified against current_database() on the live connection, and the operation is confirmed interactively or with --yes. Attribution and redrive idempotency follow the same contracts as the programmatic APIs.

workhorse tui renders the same views as a live, self-refreshing terminal application. It is read-only unless launched with a verified --env, which enables pausing and resuming the selected queue behind an explicit confirmation.

Telemetry attributes producer calls such as Queue.enqueue to deployment.environment.name and service.name; Go accepts a *slog.Logger for the same runtime context. Stable metrics include workhorse.jobs.enqueued, workhorse.jobs.claimed, workhorse.queue.paused, workhorse.jobs.enqueue.outcomes, workhorse.handler.executions, workhorse.handler.duration, workhorse.jobs.completed, workhorse.jobs.failed, and workhorse.jobs.retried. The non_replaceable outcome distinguishes a rejected keyed replacement from a transport failure. Enqueue outcome labels remain accepted, replayed, replaced, and coalesced across runtimes.

Next


Exact process and maintenance boundaries: architecture reference.