Backend Overview
The Proxima Console backend is a Go 1.26+ API server that serves as the central hub for infrastructure data collection, storage, and retrieval. It exposes a RESTful API for the frontend, ingests telemetry data from agents via NATS JetStream, and provides observability through OpenTelemetry tracing and Prometheus metrics.
Technology Stack
- Language: Go 1.26+
- HTTP Router: chi — lightweight, composable router
- Database Access: sqlx with raw SQL (no ORM)
- Logging: slog — structured JSON logging to stdout
- Messaging: NATS 2.10+ with JetStream for agent data ingestion
- Tracing: OpenTelemetry with OTLP exporter
- Metrics: Prometheus exposition format at
/metrics
Architecture
The backend runs as a single process that combines the HTTP API server and background workers. This simplifies deployment for the MVP phase while still maintaining clean internal separation of concerns.
┌─────────────────────────────────────────────┐
│ Backend Process │
│ │
│ ┌─────────────┐ ┌──────────────────┐ │
│ │ HTTP API │ │ Workers │ │
│ │ (chi) │ │ (NATS consumers)│ │
│ └──────┬──────┘ └────────┬─────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ Domain / Store │ │
│ └──────────────┬──────────────────────┘ │
│ │ │
└─────────────────┼───────────────────────────┘
▼
┌───────────────┐ ┌────────────────────┐
│ PostgreSQL │ │ VictoriaMetrics │
│ (relational) │ │ (time-series) │
└───────────────┘ └────────────────────┘
Request Flow
- HTTP requests arrive at the chi router.
- Middleware handles authentication, request ID injection, CORS, and logging.
- Handlers validate input, call the store layer, and return JSON responses.
- All responses follow a consistent envelope format with
data,meta, anderrorfields.
Data Ingestion Flow
- Agents publish inventory and telemetry data to NATS JetStream subjects.
- Workers subscribe to these subjects via durable consumers on the EVENTS and TELEMETRY streams.
- Messages are validated, transformed, and persisted to PostgreSQL (inventory/heartbeats) or VictoriaMetrics (metrics).
Three top-level workers run in the backend process:
- EventsWorker — Consumes from the EVENTS stream. Dispatches inventory messages to
InventoryWorkerand heartbeat messages toHeartbeatWorker. - TelemetryWorker — Consumes from the TELEMETRY stream. Dispatches metrics messages to
MetricsWorker, which sends metrics to VictoriaMetrics via the Prometheus import API. - StaleDetectorWorker — Periodically sweeps for agents that have not sent a heartbeat within the configured timeout (default 5 minutes) and sets their
agent_statustooffline.
Worker Architecture
Workers follow an interface-driven pattern for testability and extensibility:
MessageProcessorinterface — defined inworker/message.go. Every sub-worker (InventoryWorker,HeartbeatWorker,MetricsWorker) implements a single method:Process(ctx, *MessageEnvelope, *slog.Logger) error.- Parent workers accept processors via constructor —
EventsWorkerandTelemetryWorkerreceive their sub-workers asMessageProcessorinterfaces, not concrete types. This decouples the NATS consumer logic from database or VictoriaMetrics dependencies. - Handler-local interfaces —
StaleDetectorWorkerdefines a localstaleMarkerinterface with a singleMarkStaleOfflinemethod, following the Go idiom of defining interfaces at the consumer, not the producer. - Composition root in
main.go— Sub-workers are created with their concrete dependencies (e.g.,NewInventoryWorker(db)) and injected into parent workers. The worker packages have zero knowledge of what backs their interfaces.
This architecture enables unit testing workers with mock processors (no real database or VictoriaMetrics needed) and supports splitting workers into separate processes in the future without changing the interface contracts.
Key Packages
| Package | Path | Responsibility |
|---|---|---|
| api | internal/api/ | HTTP handlers, middleware (auth, logging, CORS, request ID), router setup |
| domain | internal/domain/ | Domain models and types (Client, Environment, Host, Service, etc.) |
| store | internal/store/ | Database access layer — raw SQL queries via sqlx |
| transport | internal/transport/ | NATS connection management, JetStream setup, message publishing/subscribing |
| worker | internal/worker/ | Background processors — EventsWorker (inventory, heartbeats), TelemetryWorker (metrics) consume NATS messages, and StaleDetectorWorker marks unresponsive agents offline |
| metrics | internal/metrics/ | VictoriaMetrics-backed MetricsService implementing metricStore and aggregateMetricStore interfaces using MetricsQL queries |
| vmclient | internal/vmclient/ | HTTP client for VictoriaMetrics Cluster (Import, QueryRange, Query, LabelValues, Health) |
| tenantcache | internal/tenantcache/ | Thread-safe TTL cache for host→tenant resolution (avoids per-metric DB lookups) |
Design Decisions
- Raw SQL over ORM: All database queries are written as plain SQL using sqlx. This provides full control over query performance, makes it easy to use PostgreSQL-specific features, and avoids the abstraction overhead of an ORM.
- slog for logging: Structured JSON logs are written to stdout, following twelve-factor app principles. Every log entry includes a
request_idfor traceability. - Single process for MVP: The API server and workers run in the same process to reduce operational complexity. They can be separated into distinct services in a future phase if scaling demands it.
- No WebSocket/GraphQL/gRPC: The backend uses REST with polling and SSE only. This keeps the API surface simple and widely compatible.