Architecture overview
Cairn's core follows a strict hexagonal architecture: domain → port → adapter. The dependency rule is the one rule that keeps the codebase clean.
domain ◀── port ◀── usecase adapters ──▶ port (implement)
(pure) (interfaces) (orchestration) (postgres / nats / s3 / connect)
internal/domainimports nothing from port/usecase/adapter. It's pure: types, invariants, the merge engine, segment matching, the visibility model.internal/portdefines driven-port interfaces (it imports only domain).internal/usecaseorchestrates domain + ports — never adapters.- Adapters implement the ports:
internal/adapter/secondary/{postgres, nats,s3,inmem}and the primaryinternal/adapter/primary/connect. cmd/server/wire.gois the only place concrete adapters meet concrete use-cases.
Surfaces
- Connect-RPC + REST — both are live and user-facing.
- Web UI — a SvelteKit CSR SPA embedded into the prod binary.
- NATS + JetStream — the async control plane between core and the workers.
Stack
Go 1.26 · Postgres 17 + TimescaleDB + PostGIS · pgx/v5 · goose migrations · NATS/JetStream · SvelteKit + Connect-Web + MapLibre + uPlot.
Read on: the ingest pipeline and provider workers.