One binary, six roles. Every deployment shape on this page is the same jaque executable started with a different -target; there is nothing to build separately and nothing to install differently per role. The page is in two halves: section 1 is each role's contract, stated as what it requires and what it refuses at startup, and sections 2 and 3 are how those roles compose. A role that refuses a flag refuses it at startup with an error, not silently; the lists below are the lists the binary enforces.

Status: the remote agent (section 4) is planned and does not exist. See project status.

1. The six targets

1.1 all (default)

All: one process owns the whole check loop; UI, API and metrics are served from it toojaque -target allscheduleexecutefoldappend+ UI/API + /metrics
Text version
+----------------------------------------------+
|              jaque -target all               |
|                                              |
|   schedule --> execute --> fold --> append   |
|      ^                               |       |
|      +-------------------------------+       |
+----------------------------------------------+
              + UI/API + /metrics

Schedules and executes checks in the same process. Requires -config. Forbids -queue, because there is no second process to dispatch checks to, and -notifier-id, because there is no separate notifier identity to name.

1.2 engine

Engine: schedules and dispatches work to a queue, never executes a check itselfjaque -target engineowns the check loopqueue(memory/shared)workresult
Text version
+------------------------+                  .---------------------.
|  jaque -target engine  | ---- work ---->  (        queue        )
|  owns the check loop   | <--- result ---- (   (memory/shared)   )
+------------------------+                  `---------------------'

Decides what runs and when, and never runs a check itself: it publishes each one to -queue and waits for the result. Requires -config and -queue. Forbids -notifier-id.

1.3 worker

Worker: pulls work from the queue and executes it, no config or event logjaque -target workerruns the checksqueue(memory/shared)workresult
Text version
+------------------------+                  .---------------------.
|  jaque -target worker  | <--- work -----  (        queue        )
|  runs the checks       | ---- result ---> (   (memory/shared)   )
+------------------------+                  `---------------------'

No config, no event log, no projection. It pulls work items from -queue and executes them. Requires -queue; forbids -config, -coordination, -heartbeat-ttl and every notification flag. A worker needs its own disk: any legacy plugin or WASM module a remote check uses is installed on the worker's machine, not the engine's, because the worker is where the check runs.

1.4 ui

UI: read-only projection that follows the event log and submits commands over jaque.work.cmd.ingress for an engine to claimjaque -target uiprojection + dashboardlog servereventlog + coordinationfollowcmd ingress
Text version
+--------------------------+                   .-----------------------------.
|  jaque -target ui        | <== follow ====   (          log server         )
|  projection + dashboard  | -- cmd ingress -> (   eventlog + coordination   )
+--------------------------+                   `-----------------------------'

Read-only. It follows the event log and serves the dashboard and the API; it never schedules or runs a check and never handles SIGHUP. Requires -config, for labels, views and the dependency graph. Forbids -queue, -command-file, -events-out, both -livestatus-* flags, -heartbeat-ttl and every notification flag.

With -coordination pointed at the shared store, a command the ui receives is forwarded to the engine fleet over jaque.work.cmd.ingress, fire-and-forget. Without -coordination, writes are rejected with 503. A -target ui process never joins engine membership.

1.5 sink

Sink: follows the event log for perfdata onlyjaque -target sinkperfdata onlyevent log(shared)follow
Text version
+----------------------+                 .---------------.
|  jaque -target sink  | <== follow ==== (   event log   )
|  perfdata only       |                 (    (shared)   )
+----------------------+                 `---------------'

Runs perfdata (metrics-input) sinks and nothing else, on its own sink/membership/ bucket and a -sink-id (hostname by default). Requires -config. Forbids -queue, -command-file, -events-out, both -livestatus-* flags, -snapshot-out, -api-token, every SMTP/Telegram flag and every notification flag; none of that surface exists in this role.

-sinks selects which entries of the CUE config's sinks: block this process runs; empty runs all of them. A sink declared with input: "events" is rejected for this target: no events-input sink runs under -target sink. This role does not reconcile its sink set on SIGHUP; restart the process to pick up an added, removed or changed sink.

1.6 notifier

Notifier: follows the event log for notification delivery onlyjaque -target notifierdelivery onlyevent log(shared)follow
Text version
+--------------------------+                 .---------------.
|  jaque -target notifier  | <== follow ==== (   event log   )
|  delivery only           |                 (    (shared)   )
+--------------------------+                 `---------------'

Runs notification delivery and nothing else, on its own notifier/membership/ bucket (a sibling of membership/ and sink/membership/, nested under neither) and a -notifier-id. Requires -config, because contacts and policies live there. Forbids -queue, -command-file, -events-out, -snapshot-out, both -livestatus-* flags and -api-token.

It also forbids -notify-delivery. That flag belongs to all and engine, which decide where delivery happens; the notifier is the delivery target and has nothing to decide. It accepts -smtp-*, -telegram-token, -notify-workers and -notify-queue.

2. Two decisions, three shapes

Every deployment sits somewhere on two independent axes: how many processes (one -target all, or one process per role) and how many engines (one, or several sharing ownership of the object set). The axes compose; production is usually both split by role and running more than one engine. The three shapes below are the useful corners of that grid, not three rungs of a ladder.

2.1 Standalone

Standalone: one process owns the whole check loop, nothing crosses a network boundaryjaque -target allscheduleexecutefoldappendeventlog: embedded, in-processOne process. Nothing crosses a network boundary.
Text version
+------------------------------------------------+
|                 jaque -target all              |
|                                                |
|     schedule --> execute --> fold --> append   |
|        ^                               |       |
|        +-------------------------------+       |
|                                                |
|          eventlog: embedded, in-process        |
+------------------------------------------------+

One process. Nothing crosses a network boundary.

Everything in one process. Overview, section 2, says when this is enough. The chart renders this shape with deploymentMode: standalone.

2.2 Split by role

Split over an external log server: engine dispatches to worker through one shared log, ui/sink/notifier follow the same logjaque -target engineowns the check looplog serverexternal-target workerruns the checks-queue-eventlogfolds-target ui-target sink-target notifiereach follows the log on its own membership bucket
Text version
   +------------------------+     -queue      +------------------+
   |  jaque -target engine  | --------------> |  -target worker  |
   |  owns the check loop   |                 |  runs the checks |
   +------------------------+                 +------------------+
                |                                      |
                +--------------- -eventlog ------------+
                                 |
                                 v
                        .-----------------.
                       (    log server     )
                       (     external      )
                        `-----------------'
                                 |
              +----------- folds -+------------+
              |                   |            |
              v                   v            v
     +----------------+  +------------------+  +----------------------+
     |  -target ui    |  |  -target sink    |  |  -target notifier    |
     +----------------+  +------------------+  +----------------------+

each follows the log on its own membership bucket

Every role points -eventlog and -coordination at the same external log server. engine dispatches work over -queue nats://...; one or more worker processes pull it, scoped by -zones (section 3). ui, sink and notifier each follow the log independently and each scale on their own membership bucket.

Splitting by role buys scale for worker, ui, sink and notifier, and network isolation between them. It does not buy availability of the check loop: there is still exactly one engine process, and if it dies checks stop until it comes back. Section 2.3 is the second axis that fixes that, and the two combine.

2.3 Multiple engines

HA: rendezvous-hashed engines share one external log server for both the event log and coordinationrendezvous hash (HRW) over the live engines-target engine-target engine-target enginelog servereventlog + coordinationreplicas: 3+ -- active/active, every engine owns a share, none idlereplicas: 2 -- active/passive failover: the survivor takes over
Text version
      rendezvous hash (HRW) over the live engines
                          |
      +-------------------+-------------------+
      |                   |                   |
+----------------+ +----------------+ +----------------+
| -target engine | | -target engine | | -target engine |
+----------------+ +----------------+ +----------------+
      |                   |                   |
      +-------------------+-------------------+
                          |
                          v
            .---------------------------.
           (         log server          )
           (   eventlog + coordination   )
            `---------------------------'

replicas: 3+ -- active/active, every engine owns a share, none idle replicas: 2 -- active/passive failover: the survivor takes over

This is 2.2's second axis, not a replacement for it: the same role split, with more than one engine process instead of one. Cluster and coordination is how membership, rendezvous-hashed ownership, heartbeats and epoch fencing combine to make that safe. deploymentMode: split renders this shape; engine.replicas is the second axis.

3. Worker zones

-zones (default default, comma-separated) names the zones a worker serves. Each host in CUE carries a zone (default "default"); each service inherits its host's zone unless it sets its own. The engine publishes each check to the queue of its object's zone, and only a worker subscribed to that zone picks it up. This is the whole mechanism for routing a check to a worker that can reach a given network segment: there is no per-check worker address, only a zone name both sides agree on.

4. The remote agent: not built

A remote agent, outbound gRPC streaming over mTLS, is planned for sites where even the pull-based worker model does not fit. It does not exist. Today, cross-network execution is the engine/worker split of section 2.2, over a queue both sides can reach.

5. Security considerations

Splitting changes which process holds which secret and which process opens which listener. worker holds no config and no notification secret; sink and notifier open no dashboard, API or Livestatus listener, which is why they forbid -api-token and the -livestatus-* flags. A ui process with -coordination can submit writes to the engine fleet, so it is not read-only toward the cluster, only toward the log. Security lists what each listener authenticates.