# Operations and capacity

The work with mail is done by the **worker** — a process that goes through
the mailboxes in turn, calls the models and writes drafts. The **Operations**
page (operator, Installation → Operations) shows whether enough of them run.
It refreshes every 30 seconds.

## What the page shows

**Capacity** — a verdict in a word:

| Verdict | What it means | What to do |
|---|---|---|
| capacity is enough | no assistant lags behind its rhythm by more than five minutes | nothing |
| add a worker | some assistant lags by more than five minutes | raise the concurrency, or start another process |
| no worker is running | no worker checked in during the last minute | `docker compose ps` and the logs of the `worker` service |

**Workers** — the running processes, their concurrency, which mail systems
they serve, which mailbox they hold right now and when they last checked in.

**Late mail checks** — assistants past their due time by more than a minute
(named by organisation and assistant, never by mailbox address).

**Job queue** — how many wait and run, and how many finished or failed in the
last 24 hours. **Errors in 24 hours** — what went wrong where.

## How to add capacity

1. **Raise the concurrency first** — in the **Worker settings** card, the
   "Mail checks at once per process" field (1–50). A mail check is mostly
   waiting for the mail and the model, so even a small container copes with
   more than the default 3. Workers take the change within seconds, no restart.
2. **Another process on the same machine**: write in `.env` how many processes
   should run in total (`WORKER_REPLICAS=2`) and run `docker compose up -d`. The
   number in `.env` survives an update too; `--scale worker=N` would only last
   until the next `docker compose up`.
3. **Another machine**: a clone of the repository, the same `.env` with
   `DATABASE_URL` pointing at the shared database (the `db` service's port 3306
   must be reachable from there), then `docker compose up -d --no-deps worker`.

A new worker shows on the page within seconds. Workers split the work through
the database by themselves: each mailbox is held by one only, so two checks
never meet. A process that crashes only delays that one mailbox until its lock
runs out.

The same card sets the **default mail check interval** (60–86,400 s) for
assistants without an interval of their own.

## Advanced

- `WORKER_PROVIDERS=google` (a list of `graph`, `google`) limits a process to
  some mail systems only — so a slower provider does not hold up the others,
  say.
- `WORKER_ID` names a process in the log (hostname:pid by default).
- A mail check that left work for later (the per-check limit, more than 200 new
  messages) queues the assistant again at once, so a flooded mailbox catches up
  in rounds.

Scaling is a human decision; draften never starts workers by itself.
