This project is a self-hosted, multi-cloud cost management system for AWS, Azure, GCP, and Kubernetes (via a third-party cost attribution platform) that I designed and built from scratch. It runs daily to collect granular cost line items at the service × region × account level, detects spend anomalies, sends configurable alerts, and produces a rich suite of reports in HTML, Excel, and PDF — from executive summaries and rolling-window trend views to per-owner and per-department drilldowns and an annual budget tracker. All data is stored locally in a local database, keeping the system lightweight and self-contained with no external SaaS dependencies.
Key Contributions
- Multi-cloud data collection via AWS Cost Explorer, Azure Cost Management, GCP BigQuery Billing Export, and a Kubernetes namespace cost attribution platform, stored as granular
service × region × account × dateline items in a local database. - 9 core report types with exports in HTML, Excel, and PDF: Executive Summary, Rolling Window, Executive Owners, Rolling Owners, Per-Owner, All Owners (batch), Department, All Departments (batch), and Alert Owner.
- Anomaly detection engine that flags spend changes only when both a configurable percentage threshold and a configurable absolute USD threshold are exceeded simultaneously, with a noise floor to suppress false positives from negligible-cost services.
- Budget Tracker showing YTD spend vs annual budget with a pro-rated period budget, an annualised forecast based on daily run rate, a progress bar with a pace marker, and four status badges (ON TRACK / AT RISK / OVER BUDGET / UNBUDGETED).
- Owner-centric YAML model (
owners.yaml) mapping cloud account IDs to named owners and departments with annual budgets, email delivery targets, and integrity checks (double-count and over-allocation warnings). - Efficient historical backfill using date-range API calls rather than day-by-day calls, supporting a gap-fill mode and safe re-runs via UPSERT semantics.
- Alerting via SMTP email and webhooks (Slack, HTTP webhook) with per-owner email delivery that auto-CCs department heads and attaches the HTML report as a MIME attachment.
- Unified Python CLI (
cc.py) with five subcommands —run,backfill,report,export,account-map— replacing per-script entry points with a single cross-platform interface. - Modular code architecture: providers, auth, analyzers, notifiers, cli, export, and budgeting packages with clean separation of concerns.
- 1000+ automated tests across 51 test files: providers (AWS, Azure, GCP, Kubernetes), analyzers, budget calculations, report renderers, CLI commands, Excel exports, and 43 cross-report numerical consistency checks.
Highlights
- All HTML reports are self-contained, fully styled files — emailable directly or opened in any browser with no server required. Excel and PDF exports maintain full section parity with the HTML output. The
account-mapcommand additionally produces a Markdown export ready to paste into Confluence, GitHub, or any wiki. - Dual-threshold detection prevents alert fatigue: a service jumping from $1 to $2 (100 % but negligible USD) does not trigger an alert.
- Azure auto-discovery: if
subscriptions:is omitted fromconfig.yaml, the system discovers all subscriptions for a tenant viaaz account list. - Azure rate-limit handling: automatic exponential backoff with
Retry-Afterheader respect, plus a configurable inter-subscription delay to avoid 429 errors during large backfills. - Budget over-allocation and account double-count issues surface as visible warning banners in every affected report rather than silently skewing numbers.
- Live validation via
cc run validate: SMTP connectivity probe, credential auth tests for all configured providers. - Interactive module dependency graph (
graph.html, 56 modules / 113 import edges) and Mermaid workflow diagrams (workflows.html) for 10 operational workflows. - The system explicitly does not replace cloud-native billing UIs — it aggregates and reports across providers for a single unified view.
Architecture
The system follows a layered, plugin-style design:
Cloud APIs (AWS / Azure / GCP / K8s)
│
▼
src/auth/* ← per-provider auth (profile, service principal, OAuth2, instance role)
│
▼
src/providers/* ← BaseProvider ABC; one implementation per cloud
│
▼
src/database.py ← database upsert into daily_costs + cost_line_items + k8s_namespace_costs
│
┌────┴────────────────┬──────────────────┐
▼ ▼ ▼
src/analyzers/* src/*_report.py src/budgeting/*
(anomaly detect) (HTML/Excel/PDF) (planning tools)
│ │
▼ ▼
src/notifiers/* reports/{html,xlsx,pdf,md}
(email / webhook)
│
▼
src/cli/* ← unified cc.py: run, backfill, report, export, account-map
src/export/* ← org map, account map (PDF/MD), owners CSV
Key source modules
| Module | Purpose |
|---|---|
cc.py | Unified CLI entry point — all subcommands |
src/main.py | Daily run orchestrator |
src/config_loader.py | YAML → typed dataclasses |
src/database.py | Database read/write with UPSERT + performance optimisations |
src/budget_calc.py | BudgetStatus dataclass, YTD/forecast maths |
src/report_utils.py | Shared formatting helpers |
src/report_queries.py | All SQL query functions |
src/report_html.py | CSS constants, inline HTML helpers, module-level note constants |
src/excel_utils.py | openpyxl helpers: auto-widths, frozen headers, currency/% formatting |
src/executive_report.py | Executive summary assembler |
src/executive_owners_report.py | Executive summary with owner-grouped notable changes |
src/rolling_report.py | Rolling N-day HTML report |
src/rolling_owners_report.py | Rolling window with owner-grouped notable changes |
src/owner_report.py | Per-owner scoped rolling report |
src/department_report.py | Per-department scoped rolling report |
src/alert_owner_report.py | Screens all owners; generates reports for flagged ones only |
src/aws_backfill.py | AWS bulk historical backfill |
src/azure_backfill.py | Azure bulk historical backfill |
src/gcp_backfill.py | GCP BigQuery billing export backfill |
src/k8s_backfill.py | Kubernetes namespace cost backfill |
src/analyzers/threshold.py | Percentage and absolute threshold checks |
src/notifiers/email.py | SMTP delivery with HTML attachment, implicit-SSL (port 465) support |
src/notifiers/webhook.py | HTTP POST (Slack / http webhook format) |
src/auth/{aws,azure,gcp}.py | Per-provider authentication (profile / assume_role / service principal / OAuth2) |
src/budgeting/budget_suggest.py | Historical analysis and budget recommendations |
src/budgeting/zero_spend_audit.py | Detect budgeted accounts with no recorded spend |
src/export/account_map_{pdf,md}.py | PDF and Markdown account-owner mapping exports |
Database schema
Three tables with UNIQUE constraints and UPSERT semantics make all operations idempotent. Connection-level performance tuning and three targeted indexes on cost_line_items optimize query performance for large datasets.
daily_costs — aggregated daily total per account (provider, account_id, cost_date, total_cost, currency).
cost_line_items — granular service × region records (provider, account_id, cost_date, service_name, region, cost, currency, plus JSON columns for provider-specific dimensions, tags, and metadata).
k8s_namespace_costs — Kubernetes namespace-level attribution joined with cost_line_items for unified drilldown.
Reports Overview
| Report | Description | Default Window | Budget Tracker |
|---|---|---|---|
| Executive Summary | KPIs, Top Services, Account Movers, Notable Changes, Account Detail, 13-Month Trend | Full month | Yes |
| Executive Owners | Executive summary with owner-grouped notable changes | Full month | Yes |
| Rolling Window | Mid-month comparison of last N days vs prior window | 7 days | Yes |
| Rolling Owners | Rolling window with owner-grouped notable changes | 7 days | Yes |
| Per-Owner | Scoped rolling report with KPI cards (Annual Budget, Period Budget, Run Rate, YTD vs Budget, Annual Forecast) | 30 days | Yes |
| All Owners (batch) | One report per owner | 30 days | Yes |
| Department | Scoped rolling report aggregating owner data | 30 days | Yes |
| All Departments (batch) | One report per department | 30 days | Yes |
| Alert Owner | Screens all owners; generates and emails reports only for those exceeding thresholds | Configurable | No |
All report types support --format HTML, --format Excel, --format PDF, and combined flags such as --format HTML,Excel. PDF rendering requires WeasyPrint or wkhtmltopdf.
Anomaly Detection
On each daily run the engine compares every account × service × region trio from yesterday against the prior day. A notable change is flagged only when all of the following conditions hold simultaneously, preventing noise:
|Δ%| ≥ percentage_change|Δ USD| ≥ absolute_change- Prior cost ≥
min_cost_for_percentagefloor — waived for tiny services
Alert direction (increases only, or both increases and decreases) is configurable.
Budget Tracker
Each HTML or Excel report with a Budget Tracker section displays:
| Column | Description |
|---|---|
| Yr Budget | Annual budget in USD from owners.yaml |
| YTD Spend | Spend from fiscal year start to report end date |
| YTD % | Progress bar with a pace marker at the expected YTD % |
| Period Budget | Pro-rated share of the annual budget for the report period |
| Period Spend | Actual spend for the period |
| Forecast | Annualised forecast based on daily run rate |
| Status | ON TRACK / AT RISK / OVER BUDGET / UNBUDGETED badge |
Status thresholds are configurable; UNBUDGETED when no budget is configured.
Windows Portable Executable
For deployment on Windows servers without a Python installation, the project compiles to a self-contained cc.exe using PyInstaller. The executable bundles the entire Python 3.11 interpreter, all cloud SDKs (boto3, azure-sdk, GCP client), and all application modules — no Python required on the target machine.
Note:
--onedirmode was chosen over--onefile(single-file exe) to avoid AV heuristics triggered by self-extracting packed binaries, and to eliminate the startup overhead of extracting ~250 MB to%TEMP%on every run.