Initial deployment is a modular monolith — control plane, ingest gateway, telemetry pipeline, and report engine live in one binary and communicate in-process, but are structured as independent modules with clean boundaries. Kafka/NATS is wired in from day one as the internal event bus, so extracting any module later requires only a deployment change.
architecture.txt
SDK (Go / Node / Python / Java / PHP / Rust) ↓ gRPC + ingest tokenAPI Gateway / TLS Termination ↓----------------------------------------------Ingest Gateway │ Control PlaneTelemetry Pipeline │ Report Engine │ Auth & Token Service---------------------------------------------- ↓Internal Event Bus (Kafka / NATS) ↓Worker Pool (Go routines) ↓Data Layer ├── PostgreSQL — tenants, projects, apps, tokens, quotas ├── ClickHouse — metrics, spans, logs (tenant-labeled) ├── Object store — long-term archive └── Redis — token cache, quota counters, hot scheduling ↓Observability (Prometheus + OpenTelemetry + Zap)
Extraction trigger
Ingest Gateway extraction is considered when sustained ingestion across any single tenant exceeds 50,000 spans/sec for 10 minutes, or service CPU stays above 70% for 10 minutes. Report Engine extraction follows the same pattern with a read-side P99 latency trigger above 2 seconds. Extraction is an operator decision after confirming stable event contracts, idempotent consumers, and observability coverage.