Docs Guides
Workers and scheduled jobs
Under the manifest's services key, a project runs processes that answer no request: a worker that runs for good, or a job at set times.
Declare the services
Link to the section Declare the servicesEach entry names a service and takes a start. What else it declares sets its kind:
| Kind | Declares | Runs |
|---|---|---|
| Server | port | for good, listening on its port |
| Worker | "internal": true, no port | for good, listening on nothing |
| Scheduled | schedule | at the times it names, each run to its end |
A worker or a scheduled service goes under services even alone: a top-level start is always a server.
In sitesolide.json, a page, a worker and a job every quarter of an hour:
{
"slug": "background",
"services": {
"web": { "start": "/usr/local/bin/bun run web.ts", "port": 3041 },
"worker": { "start": "/usr/local/bin/bun run worker.ts", "internal": true },
"tally": { "start": "/usr/local/bin/bun run tally.ts", "schedule": "*:0/15", "timeout": "1m" }
}
}
The repository's background example deploys as it is.
Write a worker
Link to the section Write a workerA worker suits a queue's consumer, a bot holding a connection, or an agent.
- It comes back. systemd restarts it 2 seconds after a failure, then waits longer each time, up to 5 minutes.
- It yields. When they compete for the processor, a site gets five times a worker's share.
- It stops on SIGTERM. At a deploy or a restart, systemd sends SIGTERM, and kills it if it still runs 90 seconds later. Finish the current step and exit.
Schedule a job
Link to the section Schedule a jobschedule takes a systemd calendar expression:
schedule | Runs |
|---|---|
daily | every day at midnight |
*:0/15 | every quarter of an hour |
Mon..Fri 08:00 | on weekdays at eight in the morning |
*-*-* 06:30 Europe/Paris | every day at 6:30, Paris time |
Times are the server's, UTC on most cloud images, unless the expression names a time zone. timeout stops a run that hangs: 90s, 15m, 2h, an hour by default and a day at most. A schedule systemd cannot read stops deploy before it writes anything.
- A deploy runs nothing: the first run comes at the next scheduled time.
- A time that comes during a run is skipped: runs never overlap.
- A failed run is not retried before its next time.
- A time missed while the server was down runs once, when it is back.
Run a project with no page
Link to the section Run a project with no pageA project whose services are all workers or scheduled jobs, with no publicDir, serves no page. Its address answers 200 with a line saying so, and it cannot have its own domain.
{
"slug": "nightly",
"services": {
"sync": { "start": "/usr/local/bin/bun run sync.ts", "schedule": "daily" }
}
}
Check the runs
Link to the section Check the runssitesolide status shows each scheduled service's last run, how it ended, and its next run. sitesolide logs shows every run beside the project's other services.
sitesolide status
Keep heavy work off the server
Link to the section Keep heavy work off the serverA background service shares the server with every site, and can slow them down. Light work fits, such as waiting on an outside API. These do not:
- A headless browser. The unit's confinement refuses Chromium's sandbox.
- Heavy computing, such as video encoding or a model run on the processor.
- Mass email from the server's address. Blocklists would hit every site: call a mail provider's API instead.
Next steps
Link to the section Next steps- Calling outside services: let a service reach the APIs it calls.
- Backups and restore: see what the hourly snapshot keeps of the data folder.
- Monitoring: hear about a worker crashing in a loop, or a failed run.