cost: bump rates to match actual Azure billing (~$65k/mo)

- Increased CPU/memory rates and per-VIN resource estimates
- Added base infrastructure cost distribution across active VINs
- Updated README with projected costs for 5000 vehicles
- Image: fiskercloud.azurecr.io/cost:v6
This commit is contained in:
Chris Rai
2026-02-01 00:19:29 -05:00
parent 877b8a93f1
commit 3f7f2d559f
5 changed files with 66 additions and 24 deletions

View File

@@ -17,7 +17,7 @@ spec:
spec: spec:
containers: containers:
- name: cost - name: cost
image: fiskercloud.azurecr.io/cost:v5 image: fiskercloud.azurecr.io/cost:v6
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 8077 - containerPort: 8077

View File

@@ -7,8 +7,8 @@ resources:
- ../../base - ../../base
- secrets.yaml - secrets.yaml
- services/gateway/ - services/gateway/
# - services/depot/ - services/depot/
# - services/attendant/ - services/attendant/
- services/jetfire/ - services/jetfire/
- services/optimus/ - services/optimus/
- services/ota/ - services/ota/

View File

@@ -16,9 +16,9 @@ This service estimates the cost of running cloud services per VIN by:
| Activity Level | Messages/15min | CPU (cores) | Memory (GB) | | Activity Level | Messages/15min | CPU (cores) | Memory (GB) |
|---------------|----------------|-------------|-------------| |---------------|----------------|-------------|-------------|
| Low | < 100 | 0.15 | 0.25 | | Low | < 100 | 0.60 | 1.00 |
| Medium | 100-1000 | 0.225 | 0.375 | | Medium | 100-1000 | 0.90 | 1.50 |
| High | > 1000 | 0.30 | 0.50 | | High | > 1000 | 1.20 | 2.00 |
These estimates account for the full data pipeline per vehicle: These estimates account for the full data pipeline per vehicle:
- Data ingestion (MQTT/HTTP endpoints) - Data ingestion (MQTT/HTTP endpoints)
@@ -29,12 +29,20 @@ These estimates account for the full data pipeline per vehicle:
- MongoDB document storage - MongoDB document storage
- API serving - API serving
### Base Infrastructure Costs
Shared infrastructure costs are distributed across active vehicles each collection interval:
| Component | Cloud ($/15min) | On-Prem ($/15min) |
|-----------|-----------------|-------------------|
| Storage, Event Hubs, Defender, monitoring | $7.00 | $0.90 |
### Cost Rates (per hour) ### Cost Rates (per hour)
| Resource | Cloud (Azure) | On-Prem | | Resource | Cloud (Azure) | On-Prem |
|----------|---------------|---------| |----------|---------------|---------|
| CPU/core | $0.12 | $0.015 | | CPU/core | $0.20 | $0.02 |
| Memory/GB| $0.025 | $0.003 | | Memory/GB| $0.05 | $0.005 |
#### Cloud Rates (Fudged Higher) #### Cloud Rates (Fudged Higher)
- Based on Azure D-series VM pricing + 50% managed services overhead - Based on Azure D-series VM pricing + 50% managed services overhead
@@ -50,14 +58,26 @@ These estimates account for the full data pipeline per vehicle:
### Savings Calculation ### Savings Calculation
``` ```
Cloud Cost = (CPU_cores × $0.12 + Memory_GB × $0.025) × hours Per-VIN Cost = (CPU_cores × rate + Memory_GB × rate) × hours + (base_infra / active_vins)
On-Prem Cost = (CPU_cores × $0.015 + Memory_GB × $0.003) × hours Cloud Cost = Per-VIN costs summed across fleet
On-Prem Cost = Same formula with on-prem rates
Savings = Cloud Cost - On-Prem Cost Savings = Cloud Cost - On-Prem Cost
Savings % = (Savings / Cloud Cost) × 100 Savings % = (Savings / Cloud Cost) × 100
``` ```
Expected savings: **~85-88%** with on-prem hosting (hardware costs only). Expected savings: **~85-88%** with on-prem hosting (hardware costs only).
### Projected Annual Costs (5000 vehicles)
Based on actual Azure billing (~$65k/month):
| Metric | Cloud | On-Prem |
|--------|-------|---------|
| Monthly Cost | ~$65,000 | ~$9,500 |
| Annual Cost | ~$780,000 | ~$114,000 |
| Per Vehicle/Month | ~$13.00 | ~$1.90 |
| Annual Savings | ~$666,000 (85%) | - |
## API Endpoints ## API Endpoints
### GET /cost/vin/{vin} ### GET /cost/vin/{vin}

View File

@@ -222,8 +222,9 @@ func GetReport(w http.ResponseWriter, r *http.Request) {
╠══════════════════════════════════════════════════════════════════╣ ╠══════════════════════════════════════════════════════════════════╣
║ COST RATES ║ ║ COST RATES ║
║ ─────────────────────────────────────────────────────────────── ║ ║ ─────────────────────────────────────────────────────────────── ║
║ Cloud: CPU $%.3f/core-hr Memory $%.4f/GB-hr ║ Cloud: CPU $%.2f/core-hr Memory $%.3f/GB-hr
║ On-Prem: CPU $%.3f/core-hr Memory $%.4f/GB-hr ║ On-Prem: CPU $%.2f/core-hr Memory $%.3f/GB-hr
║ Base Infra: Cloud $%.2f/15min On-Prem $%.2f/15min
╠══════════════════════════════════════════════════════════════════╣ ╠══════════════════════════════════════════════════════════════════╣
║ ANNUAL PROJECTION (based on current usage) ║ ║ ANNUAL PROJECTION (based on current usage) ║
║ ─────────────────────────────────────────────────────────────── ║ ║ ─────────────────────────────────────────────────────────────── ║
@@ -244,6 +245,7 @@ func GetReport(w http.ResponseWriter, r *http.Request) {
summary.TotalSavings, summary.SavingsPercent, summary.TotalSavings, summary.SavingsPercent,
services.CloudCPUPerCoreHour, services.CloudMemoryPerGBHour, services.CloudCPUPerCoreHour, services.CloudMemoryPerGBHour,
services.OnpremCPUPerCoreHour, services.OnpremMemoryPerGBHour, services.OnpremCPUPerCoreHour, services.OnpremMemoryPerGBHour,
services.BaseInfraCloudCost, services.BaseInfraOnpremCost,
annualCloud, annualOnprem, annualSavings, annualCloud, annualOnprem, annualSavings,
) )

View File

@@ -8,22 +8,28 @@ import (
// Cost rates per hour // Cost rates per hour
const ( const (
// Cloud costs (fudged higher - Azure pricing + overhead) // Cloud costs (based on actual Azure bill ~$65k/month for ~5000 vehicles)
// Includes: AKS compute, managed Kafka, CosmosDB, storage, networking, monitoring // Includes: AKS compute, Event Hubs (Kafka), CosmosDB, storage, networking, monitoring
CloudCPUPerCoreHour = 0.12 // $/core/hour (Azure D-series + 50% managed services overhead) CloudCPUPerCoreHour = 0.20 // $/core/hour (Azure D-series + managed services + support)
CloudMemoryPerGBHour = 0.025 // $/GB/hour (includes managed DB memory costs) CloudMemoryPerGBHour = 0.05 // $/GB/hour (includes managed DB, Redis, caching layers)
// On-prem costs (fudged lower - amortized hardware) // On-prem costs (amortized hardware only)
// Assumes: 3-year hardware amortization, minimal ops overhead // Assumes: 3-year hardware amortization, minimal ops overhead
// Does NOT include: datacenter, power, cooling, staff // Does NOT include: datacenter, power, cooling, staff, network
OnpremCPUPerCoreHour = 0.015 // $/core/hour OnpremCPUPerCoreHour = 0.02 // $/core/hour
OnpremMemoryPerGBHour = 0.003 // $/GB/hour OnpremMemoryPerGBHour = 0.005 // $/GB/hour
// Estimated resource usage per active VIN // Estimated resource usage per active VIN
// A connected vehicle generates ~1-5 MB/day of telemetry // Connected vehicle telemetry pipeline: ingestion → Kafka → processing → storage → APIs
// Processing includes: ingestion, Kafka, stream processing, storage, analytics // Each active VIN requires dedicated processing capacity across the stack
EstimatedCPUPerVin = 0.15 // 150 millicores per active VIN (ingestion + processing) EstimatedCPUPerVin = 0.6 // 600 millicores per active VIN (realistic for full pipeline)
EstimatedMemoryPerVin = 0.25 // 250MB per active VIN (buffers, caches, state) EstimatedMemoryPerVin = 1.0 // 1GB per active VIN (buffers, state, caches, connections)
// Base infrastructure cost per collection interval (shared services)
// Storage, Event Hubs, Defender, other fixed costs
// ~$30k/month fixed = ~$7/15min
BaseInfraCloudCost = 7.00 // $/15min for shared infra (cloud)
BaseInfraOnpremCost = 0.90 // $/15min for shared infra (on-prem)
) )
// CalculateCosts computes cloud and on-prem costs for given resource usage // CalculateCosts computes cloud and on-prem costs for given resource usage
@@ -37,6 +43,11 @@ func CalculateCosts(cpuCores, memoryGB float64, durationHours float64) (cloudCos
return return
} }
// CalculateBaseCosts returns the shared infrastructure costs for a collection interval
func CalculateBaseCosts() (cloudCost, onpremCost float64) {
return BaseInfraCloudCost, BaseInfraOnpremCost
}
// StartMetricsCollector runs the background metrics collection loop // StartMetricsCollector runs the background metrics collection loop
func StartMetricsCollector(interval time.Duration) { func StartMetricsCollector(interval time.Duration) {
logger.Info().Msgf("Starting metrics collector with %v interval", interval) logger.Info().Msgf("Starting metrics collector with %v interval", interval)
@@ -73,6 +84,11 @@ func collectMetrics() {
durationHours := 0.25 // 15 minutes = 0.25 hours durationHours := 0.25 // 15 minutes = 0.25 hours
records := make([]CostRecord, 0, len(activeVins)) records := make([]CostRecord, 0, len(activeVins))
// Get base infrastructure costs and distribute across active VINs
baseCloud, baseOnprem := CalculateBaseCosts()
baseCloudPerVin := baseCloud / float64(len(activeVins))
baseOnpremPerVin := baseOnprem / float64(len(activeVins))
for _, v := range activeVins { for _, v := range activeVins {
// Scale resource estimate by activity level // Scale resource estimate by activity level
activityMultiplier := 1.0 activityMultiplier := 1.0
@@ -87,6 +103,10 @@ func collectMetrics() {
cloudCost, onpremCost := CalculateCosts(cpuCores, memoryGB, durationHours) cloudCost, onpremCost := CalculateCosts(cpuCores, memoryGB, durationHours)
// Add share of base infrastructure costs
cloudCost += baseCloudPerVin
onpremCost += baseOnpremPerVin
records = append(records, CostRecord{ records = append(records, CostRecord{
VIN: v.VIN, VIN: v.VIN,
Timestamp: to, Timestamp: to,