> Section: [4. Configuration](https://jaque.sh/docs/config/cue-in-practice.md)
> Next: reference/config-schema
> Index: https://jaque.sh/llms.txt


SIGHUP makes jaque compile the config file again, diff the result against
the running object graph, and swap the new graph in atomically on the
engine's own goroutine. Objects the diff calls unchanged are not touched:
no reschedule, no reset of soft-state counters, no check storm. A config
that fails validation is rejected and the previous one keeps running.
Both outcomes are written to the event log as facts, so "what changed and
when" survives in history rather than in a log line that scrolled past.

Status: the old version of this page named the rejection event
`ConfigRejected`; the event the log carries is `ConfigReloadRejected`.
Documented under the old name, verified under the new one. See [project
status](../project/status.md).

## 1. Signal

```sh
kill -HUP $(pgrep jaque)
```

A SIGHUP that arrives while the previous reload is still loading is
coalesced; reloads are applied one at a time, in order.

## 2. What a reload does, in order

The order is pinned, because each step depends on the one before it.

```text
SIGHUP
  |
  v
compile the new config ----- fails ----> ConfigReloadRejected
  |                                       (old config keeps running)
  v
diff against the running graph: added / removed / changed / unchanged
  |
  v
append ConfigReloaded, then one ObjectRetired per removed object
  |
  v
swap the object graph, runners, policies, labels and topology
  |
  v
removed: cancel and forget     changed: cancel and re-arm
added: arm                     unchanged: nothing
  |
  v
recompute reachability; emit only for objects whose answer changed
```

Facts go to the log before the in-memory swap, the same rule every
command follows: a crash between the two loses the in-memory update,
never the fact. `ConfigReloaded` carries the four counts, which is what
makes "a reload that changed nothing rescheduled nothing" readable from
the log alone. [Event sourcing](https://jaque.sh/docs/concepts/event-sourcing.md) is why
this is the same mechanism as everything else in jaque and not a special
case.

## 3. What needs no restart

Adding, removing or editing hosts and services. Changing check
schedules, thresholds or flap settings. Adding or editing contacts,
notification policies and escalations. Adding or editing labels and
saved views. A changed object is cancelled and re-armed on its new
schedule; its projected state, soft counters included, is not reset,
because only removed objects have their state dropped.

## 4. A rejected reload

Bad CUE or a schema violation leaves the previous, still-valid config
running and appends `ConfigReloadRejected` with the loader's own error
text. A typo in a config edit cannot take down monitoring that was
already working; it can only fail to change it, on the record.

## 5. A removed object

An object that disappears from the new config does not vanish from view:
it is retired (`ObjectRetired` in the log), its scheduler entry is
cancelled, and its projection, notification state and due time are
dropped. The query API stops returning it, and history keeps the fact
that it existed and when it was removed. This is how the projection and
the history stay consistent with what is actually being checked.

## 6. Security considerations

Whoever can send SIGHUP to the process, or write the file `-config`
names, can change what is monitored and who is notified. Both are
controlled by the host's user and file permissions, not by jaque. The
rejected-reload path never partially applies a config, so a truncated or
half-written file cannot leave the engine running a mix of old and new.
