Skip to content
Dashboard
Create 5 min read

Background Workers

Run a long-lived process for queues, media processing, and asynchronous work.

Background Workers#

Choose Background Worker for a process that should remain running but does not serve a public HTTP application directly. Typical uses include queue consumers, media transcoding pipelines, event handlers, continuous synchronization loops, and any asynchronous workload whose job is not "accept an HTTP GET and prove itself healthy," but "keep pulling work and making progress."

A worker is not a Web Service with a hidden port — it has no public URL. Selecting the correct service type aligns the deployment’s lifecycle with the process’s semantics: the platform watches for whether the process stays alive, not whether a public HTTP path is ready.

When to use — and when not to#

Use a Background Worker when:

  • The process consumes from a queue or stream continuously (for example an AMQP-compatible queue, cloud queues, or internal task tables) and should retry and back off in the application’s own job logic.
  • The work is long-lived and stateful across many items (media processing, index building, event propagation) and there is no natural "request" that defines a timeout.
  • There is no external client that needs an HTTP endpoint; the worker’s only interface is the queue it reads and whatever datastore it writes to.

Do not use a Background Worker when:

  • The work is naturally scheduled and finite — a single command that should run once per hour, per day, or per window and then exit. Use Cron Job instead when the work is bounded by a clock.
  • The work is an on-demand bounded container task that needs a retry limit, a formal timeout, and per-run history (for example a one-off import or a per-invoice render). Use Workflow.
  • The deliverable serves traffic and must be reachable on a hostname — use Web Service or Frontend App.
Info

A queue consumer that stays up for hours is a Worker; a nightly reconciliation script that has finished once it prints the report is a Cron Job. The question is not how much work there is, but whether there is a reader that should stay open.

Configure the process#

Set the source and start command that keeps the worker running — the start command is the whole process definition here, not a complement to a health path:

  • Source — a repository, ZIP archive, or folder (and, when the dashboard offers it, an existing container image — see the Docker Quickstart). Confirm the branch and root directory for that source.
  • Start command — the statement that stays alive. Typical forms: node worker.js, python -m myapp.worker, sidekiq, celery -A proj worker, a custom binary invocation, or an npm run worker that encodes the same.
  • Environment variables — configure connection strings, credentials, and queue settings as scoped secrets in the dashboard. The scope guidance in Environment Variables applies identically to workers: a variable needed only at runtime should not ride in a build-scoped place.

A worker should handle retries and failures in its own job logic. The platform observes the process lifecycle and deployment history, but per-message retry, dead-lettering, and idempotency are application concerns. Common patterns:

  • Fetch → attempt → ack or requeue with backoff, with a bounded retry count and a dead-letter queue for the surprising failures that need human eyes.
  • Lease per-message visibility so a duplicate lease does not double-process when a previous lease had not yet timed out.
  • Record progress externally (database row, queue offset) so restarts pick up from the last acknowledged item rather than from the beginning.
Warning

A start command that completes rather than stays up (python import_once.py that prints the report and exits) belongs in a Cron Job or Workflow, not a Worker. That distinction determines whether a "success" means "finished once" or "still consuming."

Observe releases#

Use the deployment detail page to inspect source preparation, dependency installation, and startup state — the same stages runtime services show, minus the public health probe. If a worker exits unexpectedly, review the start command and its application output before redeploying.

Day-to-day reading:

  • The detail page shows the underlying commit or archive name, the resolved configuration, and the staged text output in order. When the worker’s log ends with a successful exit code rather than a crash, it probably ran the wrong command.
  • Framework detection and environment snapshot ride with the release record, so two releases that differ only in an environment variable are distinguishable without reconstructing a commit history.
  • Process restarts are visible in application output — a crash that loops is not the same as a commit that never built.
Tip

Locally reproduce worker behavior with the same command you configure in the dashboard. A behavior invisible to HTTP (sleep 1; exit 0) is a full-day bug when placed in a long-lived process definition — catch it before the platform does.

  • Cron Jobs — when work is clock-scheduled and finite.
  • Workflows — on-demand bounded tasks with explicit timeouts and retry limits.
  • Logs — reading stage output and application text for a process with no public health check.
  • Deployments and Deployment Troubleshooting — diagnosing dependency and startup failures from the detail page.
  • Environment Variables — scoping so queue credentials and app configuration arrive where they are needed.