Architecture¶
Status: design baseline (Phase 0). Sections are filled in as phases land.
Provisioning layers¶
See ADR 0003.
flowchart TB
subgraph L0["Layer 0 · Substrate (OpenTofu, substrate-specific)"]
kind["kind (local)"]
pve["Proxmox + Talos (on-prem, designed)"]
end
subgraph L1["Layer 1 · Bootstrap (OpenTofu)"]
argo["Argo CD"]
end
subgraph L2["Layer 2 · Platform & apps (GitOps, substrate-agnostic)"]
plat["Platform services"]
data["Data platform"]
apps["Applications"]
end
kind -- kubeconfig --> argo
pve -- kubeconfig --> argo
argo -- "app-of-apps + overlays<br/>(dev / perf / dr)" --> L2
Data flow¶
Market model: ADR 0021 · Matching engine: ADR 0022. Service boundaries are finalised in Phase 4.
flowchart LR
sim["trader-sim<br/>synthetic participants"] --> oe["order entry<br/>pre-trade risk"]
oe <--> valkey[("Valkey<br/>idempotency · last price")]
oe --> orders[("orders<br/>key = instrument")]
orders --> me["matching engine<br/>price-time · deterministic"]
me --> exec[("executions ·<br/>book updates")]
exec --> md["market data<br/>L1/L2 · OHLCV"]
exec --> surv["surveillance<br/>MAR patterns"]
exec --> pt["post-trade<br/>positions · T+2"]
md & surv & pt --> ch[("ClickHouse<br/>analytics · audit")]
ch --> graf["Grafana"]
reg["Apicurio Registry"] -. schemas .- oe & me
Components¶
Namespaces are planned and confirmed in the phase that introduces each component.
| Component | Purpose | Namespace | Config path | ADR |
|---|---|---|---|---|
| SeaweedFS | OpenTofu state store, outside the clusters | Docker (host) | infra/stacks/foundation/ |
0025 |
| cloud-provider-kind | LoadBalancer services for kind | Docker (host) | infra/stacks/substrate-kind-shared/ |
0014 |
| Cilium | CNI, NetworkPolicy, Hubble | kube-system |
gitops/platform/cilium/ |
0028 |
| Argo CD | GitOps controller (self-managed) | argocd |
gitops/platform/argocd/, gitops/root/ |
0030 |
| Strimzi + Kafka | Event backbone | kafka |
Phase 3 | 0008 |
| Apicurio Registry | Schema registry | kafka |
Phase 3 | 0012 |
| Kafbat UI | Kafka inspection | kafka |
Phase 3 | 0016 |
| trader-sim | Synthetic market participants (load) | apps |
Phase 4 | 0009 |
| order entry | Validation, pre-trade risk (tick size, price corridors) | apps |
Phase 4 | 0021 |
| matching engine | Price-time order book, exactly-once | apps |
Phase 4 | 0022 |
| market data / surveillance / post-trade | Downstream consumers of executions | apps |
Phase 4 | 0022 |
| ClickHouse | Analytical sink and audit store | clickhouse |
Phase 4 | 0010 |
| Valkey | Dedup + cache | apps |
Phase 4 | 0011 |
| Kyverno | Admission policies | kyverno |
Phase 2 | 0013 |
| Envoy Gateway | North-south traffic | envoy-gateway-system |
Phase 2 | 0014 |
| kube-prometheus-stack | Metrics, alerts, dashboards | monitoring |
Phase 2 | 0015 |
Profiles¶
| Profile | Nodes | Kafka | Lifecycle |
|---|---|---|---|
dev |
1 control-plane + 1 worker | 3 combined pods, RF=3, min ISR=2 | Daily |
perf |
Sized for the billion-event run | Dedicated controller and broker pools | On demand |
dr |
Secondary site | Replica of primary | On demand, for drills |
Delivery semantics¶
- Producers:
acks=all, idempotence on. - Order entry: idempotency keys in Valkey reject resubmitted orders.
- Matching: Kafka transactions (read-process-write), one engine loop per partition, deterministic replay from the order log.
- Proof: end-to-end reconciliation (produced = processed = stored), see benchmarks.