Build & ship

Workers & jobs

Not everything answers HTTP. Workers keep running in the background, jobs run to completion on a schedule or on demand, and one-off commands run once in the live release.

Workers

A worker is a service without a port: queue consumers, bots, stream processors. It deploys like any other service — same builds, releases, variables, logs, metrics, rollback, and autoscaling — but has no address and can’t have domains.

Terminal
apprail services create shop worker --worker
apprail build shop/worker --git https://github.com/acme/shop --context worker

Jobs

A job is a named command attached to a service and environment. Each run starts a fresh container from the service’s live release — same image, variables, CPU, and memory — runs the command through sh -c, and records its exit code, duration, and output.

Terminal
apprail jobs create shop/web nightly-report --schedule "0 3 * * *" --timezone Europe/Stockholm -- node scripts/report.js
apprail jobs run shop/web nightly-report
apprail jobs runs shop/web nightly-report
apprail jobs logs RUN_ID
OptionWhat it does
--scheduleFive-field cron, or @hourly, @daily, @weekly, @monthly, @yearly. At most every 5 minutes. Leave it out for a job you only run by hand
--timezoneAn IANA zone; default UTC. 0 3 * * * in Europe/Stockholm runs at 03:00 local time all year, across daylight-saving changes
--concurrencyforbid (default) skips a run while the previous one is still going; replace stops the old run; allow runs both
--retriesExtra attempts after a failure, 0–5
--timeoutSeconds before a run is stopped; default one hour

A job that starts failing sends one alert to your alert channels — not one per run — and another only after it has succeeded again.

One-off commands

Seed a database, fix some data, run a script once. apprail run starts the command in the live release with the environment’s variables and streams its output back until it exits. It exits with the command’s own exit code, so it works in scripts and CI. Ctrl-C cancels it. The console’s Run a command does the same.

Terminal
apprail run shop/web -- npx prisma db seed
apprail run shop/web --env staging -- python manage.py createsuperuser --noinput

Which one to use

You want to…Use
Migrate the database before every releasea pre-deploy command
Do something once, nowapprail run
Do something on a schedulea job with --schedule
Keep something runninga worker