# Processes, workers and cron

> Run queue workers, Horizon, daemons and scheduled jobs beside a Falak site — how the agent supervises them, restarts on deploy, heartbeats and crash loops.

Source: https://falak.sh/docs/guides/processes/

Falak's agent includes a process supervisor and a cron scheduler. You declare what should run in the site's **Processes** tab; Falak compiles the full desired set per server and the agent converges to it. No supervisord, no crontab editing.

## Kinds of processes

| Kind | Program name | Created by |
|---|---|---|
| Web process (Node, Bun, Deno) | `<slug>.app` | Automatically for JavaScript runtimes |
| Queue worker | `<slug>.worker-<id>` | You (Processes → Queue workers) |
| Horizon | `<slug>.horizon` | Settings → Laravel → Horizon |
| Octane | `<slug>.octane` | Settings → Laravel → Octane |
| Daemon | `<slug>.daemon-<id>` | You (Processes → Daemons) |
| Laravel scheduler | `<slug>.schedule` | Settings → Laravel → Scheduler (leader only) |
| Cron job | `<slug>.cron-<id>` | You (Processes → Scheduled jobs) |

All run in `current/` of the site, as the site user, with the release's environment plus `FALAK_SITE`, `FALAK_SITE_ID`, `FALAK_SERVER_ID`, `FALAK_RELEASE_ID` and `FALAK_DEPLOYMENT_ID`.

## Queue workers

1. Open the site's **Processes** tab → **Queue workers** → **Add**.
2. Fill in the fields below and save. The workers start on every selected server that has a live release.

| Field | Meaning | Allowed |
|---|---|---|
| Connection | Queue connection name (empty = the app default) | letters, digits, `_ . -` |
| Queue | Queue names, comma-separated (empty = `default`) | |
| Processes | Parallel worker processes | 1–64 |
| Timeout | `--timeout` seconds | 0–86400 |
| Sleep | `--sleep` seconds | 0–3600 |
| Tries | `--tries` | 0–1000 |
| Backoff | `--backoff` seconds | 0–86400 |
| Max jobs | `--max-jobs` | 0–1000000 |
| Max time | `--max-time` seconds | 0–604800 |
| Memory | `--memory` MB | 32–65536 |
| Command | Replaces `artisan queue:work` entirely (run with `bash -c`) | |
| Environment | Extra variables (up to 50) | |
| Servers | Subset of the site's servers (default: all) | |

![The site's Queues page: a per-server status block (leader app-2, applied state, Logs, Refresh status and Restart actions) and the list of queue workers with an Add worker button.](./_images/sites-site-queues.png)

Generated command for PHP sites:

```bash
php8.4 artisan queue:work redis --queue=high,default --sleep=3 --tries=3 --timeout=60 --memory=128 --backoff=10
```

Non-PHP sites must set **Command** (for example `node dist/worker.js`).

## Daemons

Any long-running command: a WebSocket server, `bin/console messenger:consume`, a BullMQ consumer.

| Field | Meaning | Allowed |
|---|---|---|
| Name | Label | up to 64 characters |
| Command | Command line | up to 2000 characters |
| Directory | Absolute working directory (default: `current/`) | |
| User | Linux user (not `root`) | default: site user |
| Instances | Processes to run | 1–64 |
| Restart | `always`, `on-failure`, `never` | |
| Stop signal | `TERM`, `INT`, `QUIT`, `HUP`, `KILL`, `USR1`, `USR2` | |
| Stop timeout | Seconds before `SIGKILL` | 1–3600 |
| Environment, Servers | As for workers | |

## Scheduled jobs (cron)

| Field | Meaning |
|---|---|
| Name, Command | What to run |
| Expression | 5-field cron (`*/5 * * * *`), `@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly`, or `@every <duration>` (Go duration, at least 1 s, e.g. `@every 90s`) |
| Timezone | IANA timezone (default UTC) |
| User | Not `root` |
| Overlap | `allow` or `skip` (skip a run while the previous one is still running) |
| Timeout | 1–86400 seconds |
| Heartbeat | Report each run to Insights so missed runs are detected |
| Enabled | Pause without deleting |
| All servers | Run on every server, or only on the leader |

The Laravel scheduler is a built-in job: `php artisan schedule:run` every minute on the leader, overlap allowed, heartbeat on, timeout 3600 s.

## Lifecycle

- **Nothing runs before the first deployment.** A site's programs and cron jobs start on a server once the site has a live release there. A server added to a deployed site gets them at the next deployment.
- **Deploys restart processes.** After activation, the restart phase applies the new process set; every program whose definition (including environment) changed restarts in the new release. Horizon receives `horizon:terminate`; Octane is restarted.
- **Restart processes** in the panel menu restarts the site's processes on the same release (Octane gets a graceful `octane:reload`).
- Process changes are debounced by 2 seconds (`FALAK_PROCESSES_APPLY_DELAY`), then applied as one `proc.apply`/`cron.apply` per server.
- Restarting the agent restarts supervised programs.

## Crash loops

Every 5 minutes (`FALAK_PROCESSES_STATUS_POLL`, `0` disables) Falak polls the status of programs. A program that is `fatal`, or in backoff after 5 or more restarts, raises the **Process keeps crashing** alert (`processes.crash_loop`, critical). **Process running again** (`processes.recovered`) follows when it recovers.

## Logs

Program output goes to `/var/log/falak` on the server and is shipped to Loki. See it in the site's **Logs** tab.

## Limits

- Processes are not run for Docker and Compose sites (container runtimes). Add them as containers.
- Cron jobs and daemons cannot run as `root`.

## Next steps
