Architecture

A real transport layer, not a shortcut

Agents never write storage directly. Every record passes through a Kafka-API transport, keeping storage credentials off the edge and letting ClickHouse and Tantivy fail independently of each other.

Edge / transport Independent consumers Query path

agent → ingest → Redpanda → {ClickHouse-writer, Tantivy-indexer} → api → web

Query engine

Structured filters and full-text search, compiled once

A query like service=api status>=500 | stats count by host and a query like message:"connection refused" aren't two different code paths — the compiler routes each clause to whichever backend actually answers it.

query bar → compiler → IR → {ClickHouse, Tantivy} → merged results

Multi-tenancy

Isolation at the connection layer, not a row filter

Tenant isolation lives where it can't be bypassed by a clever query: each tenant gets its own ClickHouse connection pool and its own Tantivy index, resolved from the authenticated request identity — never a parameter a client can override. The raw-SQL escape hatch runs through the same scoped connection as everything else, so there's no query shape that reaches another tenant's data.

  • OIDC and SAML SSO, verified against real identity providers
  • Per-resource dashboard grants, not just tenant-wide roles
  • Append-only, hash-chained audit log for every query

Deployment

docker-compose to a Kubernetes fleet

Start with a single docker compose up for a homelab or small team. Move to a Kubernetes Operator and Helm chart when you need it — the same Tenant custom resource drives per-tenant provisioning either way, so growing past one node doesn't mean a rewrite.

  • A Go controller-runtime Operator managing one CRD
  • Helm chart covering every service, gated behind one flag
  • Real credentials synced onto the CR, not placeholders

See the dependencies behind it

Every choice on the stack page was picked for being proven, not novel.

View the stack →