Skip to content

Architecture

FourEyes is a single central server that many probe nodes dial into. One server binary, one node binary, one bidirectional mTLS stream per node.

┌─────────────────────────────────────────────┐
│ Central server (Go) │
│ gRPC + grpc-gateway (REST) · React UI │
│ ring buffer → flush → time-series store │
│ control-plane stream registry + scheduler │
│ alert engine · correlator · metrics taps │
└──────────────────▲──────────────────────────┘
│ one outbound mTLS gRPC stream each
┌────────────────────┼────────────────────┐
│ │ │
┌───┴────┐ ┌───┴────┐ ┌───┴────┐
│ node │ │ node │ │ node │
└────────┘ └────────┘ └────────┘

A single Go binary that:

  • Terminates node mTLS gRPC connections and reverse-proxies REST via grpc-gateway.
  • Hosts the React UI (built by Vite, embedded at release).
  • Buffers incoming results in a ring buffer, then flushes in batches to the time-series store.
  • Runs the control plane: the node/stream registry, test assignments, and a full resync on reconnect (plus diff-at-write on change).
  • Hosts the alert engine, the event correlator, and the observability taps (Prometheus /metrics, OTLP metrics/traces, live SSE).

A single Go binary that:

  • Holds an outbound mTLS bidi stream to the server and reconnects automatically.
  • Runs an in-process scheduler driving a closed executor registry.
  • Buffers to local disk (bbolt) so results survive a transient disconnect.
  • Optionally self-updates: downloads an ed25519-verified binary, swaps atomically, and re-execs.

A GitOps CLI that declares tests, alert rules, and dashboards as YAML and reconciles them against the live server (apply / diff / export). See GitOps.

  1. Connect — each node opens one mTLS gRPC stream and stays connected.
  2. Assign — the server pushes test assignments down the stream; nodes resync on reconnect.
  3. Probe — nodes run scheduled tests through the closed executor registry and stream results up.
  4. Ingest — results enter a ring buffer, flush in batches to the time-series store, and fan out to every consumer.
  5. Act — the alert engine, correlator, live SSE stream, Prometheus endpoint, and OTLP exporter all tap the same flush (no re-querying the store).

Every wire shape — node protocol, REST API, TypeScript client, OpenAPI document — is generated from protobuf under proto/foureyes/<ctx>/v1/. There is no hand-maintained parallel schema to drift.

  • Relational store: SQLite by default (goose migrations), explicit Scope on every method for tenant isolation.
  • Time-series store: pluggable. SQLite TS (pure Go, default) or DuckDB (CGO opt-in, -tags duckdb). A shared storetest suite proves both behave identically.

See Storage & configuration and the security model for more.