Live Metrics — Real-Time Feed
The Praevis dashboard updates every 5 seconds with live auction data — no manual refresh, no polling. Behind the dashboard is a WebSocket feed powered by a stream aggregation pipeline that turns raw auction events into structured metrics in near-real-time.
What you see
The dashboard metrics ribbon shows, live and updating:
| Metric | Update frequency | Source |
|---|---|---|
| RPS (requests per second) | 5 seconds | Live Redis counter |
| Active auctions | 5 seconds | Live Redis counter |
| Fill rate (rolling 1m) | 5 seconds | Redis stream aggregate |
| Revenue (period total) | 60 seconds | Stream aggregator |
| P50 / P95 / P99 latency | 60 seconds | Stream aggregator |
Architecture
Auction engine (Go)
↓
Auction event → Redis Stream (XADD)
↓
Stream Aggregator (60s batches)
↓
Aggregated metrics → Redis time-series keys
↓
WebSocket server reads Redis (every 5s)
↓
Browser dashboard receives push updateRedis Stream
Every completed auction writes a lightweight event to a Redis Stream:
XADD auction:events * \
publisher_id pub-uuid \
dsp_id dsp-uuid \
winning_price_micros 50000 \
latency_ms 3 \
filled 1The stream is the source of truth for all real-time metrics. It’s append-only and retained for 24 hours before automatic trimming.
Stream Aggregator
The stream aggregator runs as a separate Go service. Every 60 seconds it:
- Reads all new events from the Redis Stream since the last run
- Aggregates by publisher, DSP, partner, and region
- Calculates fill rate, eCPM, latency percentiles, and revenue
- Writes aggregated values to Redis time-series keys
- PostgreSQL batch-write for persistent storage (90-day retention)
The 60-second aggregation window is the source of the ~60s dashboard lag for revenue and latency metrics. RPS is separately maintained as a live counter and updates instantly.
WebSocket Server
The WebSocket server:
- Accepts authenticated connections from the dashboard
- Reads from Redis every 5 seconds
- Pushes the latest snapshot to all connected clients
- Automatically reconnects on disconnect (handled client-side)
Time period selector
The dashboard lets you view metrics across different windows:
| Period | Bucket size | Data source |
|---|---|---|
| 1h | 1-minute buckets | Redis time-series |
| 6h | 5-minute buckets | Redis time-series |
| Today | Hourly buckets (UTC day) | Redis time-series |
| 24h | Hourly buckets (rolling) | Redis time-series |
| 7d | Daily buckets | PostgreSQL |
| 30d | Daily buckets | PostgreSQL |
Switching the time period changes which data source is queried — short windows come from Redis (fast), longer windows from PostgreSQL (accurate, permanent).
Per-entity breakdown
Live metrics are tracked separately for:
- Per supply source: fill rate, revenue, eCPM, latency
- Per demand source: win rate, spend, avg CPM, timeout rate
- Per region: FRA / NYC / LON independent tracking
- Per partner: aggregate across all partner supply sources/demand sources
All breakdowns are available in the dashboard and via the Metrics API.
API access
Pull the same data that powers the dashboard:
# Platform-wide snapshot
GET /api/metrics?period=1h
# Publisher breakdown
GET /api/metrics/publisher/{publisher_id}?period=6h
# DSP performance
GET /api/metrics/dsp/{dsp_id}?period=24hWebSocket API
For programmatic real-time access:
const ws = new WebSocket('wss://api.praevis.com/ws/metrics', {
headers: { 'Authorization': 'Bearer ' + apiKey }
});
ws.on('message', (data) => {
const update = JSON.parse(data);
console.log(update.rps, update.fill_rate_1m, update.revenue_cents_1m);
});Push payload:
{
"type": "metrics_update",
"timestamp": "2026-02-17T14:30:05Z",
"rps": 1359,
"auctions_1m": 81540,
"fill_rate_1m": 0.863,
"revenue_cents_1m": 4820,
"p50_ms": 3,
"p95_ms": 15
}Data retention
| Data | Storage | Retention |
|---|---|---|
| Raw auction events | Redis Stream | 24 hours |
| Aggregated time-series | Redis | 7 days |
| Daily aggregates | PostgreSQL | 90 days |
| Billing-relevant records | PostgreSQL | 7 years (planned) |
Flushing Redis (e.g., for infrastructure maintenance) clears the live time-series but does not affect PostgreSQL historical data. The dashboard falls back to PostgreSQL for periods >7 days automatically.