Feature Spec: Distributed Streaming Aggregator with Clustering/Sharding
1. Executive Summary
Scale NeuralBudget's Rust engine from 15k to 1M+ metrics/sec via distributed clustering, sharding, and per-node optimization while maintaining consistency and fault tolerance.
2. Current Limitations
- Single-node throughput: 15k metrics/sec (CPU-bound)
- Memory overhead: 2GB for 1M windows
- p99 latency: 500ms+
- State recovery: 10+ minutes
- Loss rate: 5% during backpressure
3. Design Goals
- Throughput: 1M metrics/sec sustained
- Latency: p99 < 100ms
- Consistency: At-least-once delivery
- Fault Tolerance: Survive single node failure
- Scalability: Linear throughput up to 64 nodes
- Simplicity: Auto-scaling, minimal ops
4. Architecture Overview
Metric Producers → Load Balancer → Sharding Router →
Aggregator Cluster (Raft Consensus) → Tiered Storage
Cluster Design
Each Node:
├─ Metric Receiver (Tokio task pool, gRPC/HTTP)
├─ 4 Shards per node (250k metrics/sec each)
├─ In-memory windows + RocksDB persistence
├─ Raft consensus for replication
├─ Async flush to storage
└─ Health monitoring
4-node cluster: 1M metrics/sec (4 nodes × 4 shards × 250k/sec)
5. Sharding Strategy
Deterministic Routing
fn compute_shard_id(metric: &Metric, num_shards: u32) -> ShardId {
let key = format!("{}:{}", metric.name, metric.labels);
fasthash::metro::hash64(key.as_bytes()) % num_shards as u64
}
Properties:
- Same metric + labels → Always same shard
- No inter-shard coordination
- Improved cache locality
Consistent Hash Ring
- Virtual nodes for even distribution
- Rebalancing: 25% shards migrate on node add
- Cold start: 30 seconds per shard
6. Data Model
Metric
- name: string
- value: f64
- timestamp: i64 (ms)
- labels: Map<string, string>
- source_id: string
AggregationWindow
- key: MetricKey (name + sorted labels)
- window_time: i64 (aligned bucket)
- sum, count, min, max: aggregates
- percentiles: {p50, p90, p99, p999}
- ingestion_count, dedup_count: quality metrics
- last_update_time: timestamp
Consistency Level
- Strong consistency: Majority quorum replication
- Replication latency: <10ms (intra-datacenter)
- Durability: Survives single node failure
7. Performance Optimizations
CPU (35% improvement target)
- Lock-free DashMap: 16x vs Mutex (fine-grained buckets)
- Single-threaded event loops: Tokio pinned to cores
- SIMD batch operations: Vectorized aggregation
- Zero-copy deserialization: Protobuf streaming
Memory (65% reduction)
- CompactWindow: 36 bytes vs 128 bytes per window
- Use f32 instead of f64
- Store IEEE 754 bits for min/max
- Pack percentiles efficiently
- Ring buffer: Pre-allocate time windows, reuse memory
- Bloom filter: 100MB for 1B deduplicates (0.01% FPR)
Network
- Protocol Buffers: ~500ns per metric
- Batch processing: 1000-metric chunks (50x overhead reduction)
- Intra-cluster: Optimized RPC, no serialization for internal state
Storage (Tiered)
Hot (7 days): TimescaleDB (8:1 compression)
Warm (30 days): S3 Parquet (15:1 compression)
Cold (365 days): S3 Iceberg (20:1 compression)
8. Raft Consensus
Write Path
- Metric arrives at leader (in-memory window update)
- Append to WAL (local disk)
- Add to Raft log
- Replicate to followers (parallel)
- Once majority acks: Mark committed
- Return success
Latency: <10ms replication, strong consistency
Leader Election
- Term-based leadership
- Election timeout: 300ms
- Failover detection: <500ms
Snapshots
- Frequency: Every 100k log entries or 5 minutes
- Size: ~500MB for 1M windows
- Recovery: 2 seconds (parallel deserialization)
9. Duplicate Detection
Metric ID = SHA256(producer_id + source_timestamp + metric_name + labels)
Detection window: Configurable (default: 1 hour)
Storage: HashMap with cleanup on expiry
Collision probability: < 1 in 2^128
10. API Specification
gRPC (Native Protocol)
service AggregatorService {
rpc IngestMetrics(IngestMetricsRequest) returns (IngestMetricsResponse);
rpc StreamMetrics(stream Metric) returns (stream IngestResponse);
rpc QueryWindows(QueryRequest) returns (QueryResponse);
rpc GetStatus(StatusRequest) returns (StatusResponse);
}
HTTP (Prometheus Compatible)
POST /api/v1/write # Ingest metrics
GET /api/v1/query?metric=name # Query aggregated windows
GET /api/cluster/status # Cluster health
POST /api/cluster/config # Update configuration
POST /api/cluster/snapshot # Manual snapshot
POST /api/cluster/rebalance # Shard rebalancing
11. Configuration
tracing:
otlp_port: 4317
batch_size: 1000
batch_timeout_ms: 5000
topology:
aggregation_window: 3600 # 1 hour
discovery_interval: 600 # 10 minutes
retention_days: 30
max_versions: 500
cluster:
enable_replication: true
quorum_size: 3
election_timeout_ms: 300
snapshot_interval: 100000
sharding:
shards_per_node: 4
rebalance_on_scale: true
performance:
worker_threads: 8
window_buffer_size: 1000
max_cardinality_per_shard: 10000000
12. Operational Commands
# Cluster status
curl http://aggregator:8080/api/cluster/status | jq
# Add node
kubectl scale deployment aggregator --replicas=5
# Trigger rebalancing
curl -X POST http://aggregator:8080/api/cluster/rebalance
# Create snapshot
curl -X POST http://aggregator:8080/api/cluster/snapshot
# Update config
curl -X POST http://aggregator:8080/api/cluster/config \
-H "Content-Type: application/json" \
-d '{"max_cardinality_per_shard": 5000000}'
13. Monitoring Metrics
Throughput:
aggregator_metrics_received_total
aggregator_metrics_processed_total
aggregator_metrics_dropped_total
aggregator_throughput_per_sec
Latency:
aggregator_ingestion_latency_ms (p50/p90/p99/p999)
aggregator_window_completion_latency_ms
aggregator_flush_latency_ms
Resources:
aggregator_memory_usage_bytes
aggregator_active_windows
aggregator_window_cardinality
Replication:
aggregator_raft_term
aggregator_raft_log_index
aggregator_replication_lag_ms
aggregator_raft_leader_changes_total
14. Alerting Rules
alerts:
- name: HighMetricDropRate
condition: (drop_rate / ingestion_rate) > 0.01
for: 5m
severity: critical
- name: HighIngestionLatency
condition: histogram_quantile(0.99, latency_ms) > 100
for: 5m
severity: warning
- name: ReplicationLagHigh
condition: replication_lag_ms > 1000
for: 2m
severity: critical
- name: NodeUnhealthy
condition: up{job="aggregator"} == 0
for: 30s
severity: critical
15. Performance Benchmarks
Throughput Scaling
Single Node (1 shard): 50k metrics/sec, 60% CPU, p99=80ms
Single Node (4 shards): 150k metrics/sec, 85% CPU, p99=90ms
3-node cluster: 450k metrics/sec, 80% CPU, p99=100ms
4-node cluster: 600k metrics/sec, 75% CPU, p99=95ms
8-node cluster: 1.2M metrics/sec, 70% CPU, p99=85ms
Memory Usage
Per node (4 shards, 1M windows each):
Active windows: 512MB (4M × 36B compact)
DashMap overhead: 100MB
RocksDB cache: 200MB
Bloom filter: 100MB
Arrow buffers: 50MB
──────────────────────
Total: 1GB (67% reduction from 3GB)
Latency Percentiles
At 1M metrics/sec:
p50: 8ms
p90: 35ms
p99: 95ms
p999: 200ms
Window completion: 5min window + 100ms = 5:00-5:05
16. Cost Analysis (1M metrics/sec)
Hardware (4 nodes):
Instance: c5.4xlarge × 4 = $16,400/month compute
Storage: 100GB EBS + 200GB S3 = $21/month
Total: $16,421/month
Cost per metric:
$16,421 / (1M metrics/sec × 2.592B sec/month)
= $0.0063 per 1M metrics
17. Implementation Roadmap
Phase 1 (Weeks 1-4): Single-node optimization → 50k/sec
- DashMap integration
- Tokio tuning
- Memory optimization
Phase 2 (Weeks 5-10): Distributed clustering → 150k/sec
- Raft consensus
- RPC framework
- Replication
Phase 3 (Weeks 11-14): Sharding layer → 1M+/sec
- Consistent hashing
- Shard rebalancing
- Cross-shard queries
Phase 4 (Weeks 15-18): Storage & export
- Parquet serialization
- Tiered storage
- TimescaleDB integration
Phase 5 (Weeks 19-24): Operations & tools
- Kubernetes auto-scaling
- Monitoring dashboard
- Operational runbooks
18. Node Lifecycle
LEADER/FOLLOWER → UNHEALTHY (unreachable 3s) →
DEAD (30s) → RECOVERING (snapshot restored) → HEALTHY
19. Scaling Operations
Add Node
- Join cluster (empty state)
- Leader creates snapshot
- Transfer snapshot (streaming)
- Replay log from snapshot
- Catch up to current state
- Rebalance shards
Time: 2-5 minutes
Remove Node
- Mark for decommission
- Migrate shards to other nodes
- Drain in-flight metrics (5s timeout)
- Shutdown gracefully
Time: <30 seconds
20. Failure Scenarios
Single Node Failure
- Detection: <500ms (Raft heartbeat timeout)
- Recovery: Automatic failover, no data loss
- Service impact: None (quorum consensus)
Network Partition
- Behavior: Leader steps down if loses majority
- Consistency: Maintained (some nodes unavailable)
- Recovery: Auto-heal on connectivity restore
Split-Brain Prevention
- Raft ensures only one leader per term
- Leader must have majority support
- Old leader auto-demotes without quorum
21. Backward Compatibility
- DAG APIs versioned (/v1/, /v2/)
- Manual aggregation still supported
- Gradual user migration (6 months)
- 12-month deprecation window
22. Success Metrics
- Throughput: 1M+ metrics/sec sustained
- Latency: p99 < 100ms
- Accuracy: >99% consistency across nodes
- Availability: 99.9% uptime
- Cost: <$0.01 per 1M metrics stored
23. Comparison: Before vs After
Metric Before After Improvement
────────────────────────────────────────────────────────
Max throughput 15k/sec 1M/sec 66.7x
Nodes required 1 4-8 distributed
CPU per metric 4μs 0.4μs 10x
Memory per window 128B 36B 3.5x
Latency p99 500ms 95ms 5.3x
Failure detection ~2min <500ms 240x
Recovery time >10min <30s 20x
Cost per metric $0.04 $0.006 6.7x
Feature Spec: Distributed Streaming Aggregator with Clustering/Sharding
1. Executive Summary
Scale NeuralBudget's Rust engine from 15k to 1M+ metrics/sec via distributed clustering, sharding, and per-node optimization while maintaining consistency and fault tolerance.
2. Current Limitations
3. Design Goals
4. Architecture Overview
Cluster Design
5. Sharding Strategy
Deterministic Routing
Properties:
Consistent Hash Ring
6. Data Model
Metric
AggregationWindow
Consistency Level
7. Performance Optimizations
CPU (35% improvement target)
Memory (65% reduction)
Network
Storage (Tiered)
8. Raft Consensus
Write Path
Latency: <10ms replication, strong consistency
Leader Election
Snapshots
9. Duplicate Detection
10. API Specification
gRPC (Native Protocol)
HTTP (Prometheus Compatible)
11. Configuration
12. Operational Commands
13. Monitoring Metrics
14. Alerting Rules
15. Performance Benchmarks
Throughput Scaling
Memory Usage
Latency Percentiles
16. Cost Analysis (1M metrics/sec)
17. Implementation Roadmap
Phase 1 (Weeks 1-4): Single-node optimization → 50k/sec
Phase 2 (Weeks 5-10): Distributed clustering → 150k/sec
Phase 3 (Weeks 11-14): Sharding layer → 1M+/sec
Phase 4 (Weeks 15-18): Storage & export
Phase 5 (Weeks 19-24): Operations & tools
18. Node Lifecycle
19. Scaling Operations
Add Node
Time: 2-5 minutes
Remove Node
Time: <30 seconds
20. Failure Scenarios
Single Node Failure
Network Partition
Split-Brain Prevention
21. Backward Compatibility
22. Success Metrics
23. Comparison: Before vs After