What goes in a cloud spend overview dashboard?
A cloud spend overview dashboard is the shared answer to "what are we spending and where is it going?" — total spend, the service and account breakdown, and how this month compares to plan. Build it on billing export rollups, and state whether costs are amortized or unblended.
What does this dashboard look like?
The layout runs from headline spend and forecast, through the daily and monthly trend, to the service and account breakdowns — read it at the start of the month and again when the forecast moves.

Which cards belong on this dashboard?
- Total spend month to date vs. same point last month
- Amortized spend by service, top 10
- Spend by account or project and environment
- Daily spend trend with weekly seasonality visible
- Month-over-month growth by service
- Budget burn vs. days elapsed
- New services appearing in the bill this month
- Untagged spend share
What data does this dashboard need?
- Daily cost rollups by service, account, team, and environment
- An explicit amortized vs. unblended cost convention
- Credits, refunds, and taxes modeled separately from usage cost
- Budget targets by month for the burn view
- Tag or label mappings for team attribution
How do you build it?
- Land billing exports or cost-platform data in a database and keep raw line items, tags, timestamps, and pricing models.
- Build rollup models at the grain this dashboard needs, with cost conventions (amortized, unblended, net) as explicit columns.
- Create one saved question per card and certify the shared models and definitions.
- Add dashboard filters for Date range, provider or account, service, team, environment.
- Show data freshness — billing exports lag, and every viewer should see by how much.
Example card SQL
WITH period AS (
-- Both windows cover the same number of *completed* days, so the
-- comparison isn't skewed by today's partial (and lagging) data.
SELECT
date_trunc('month', CURRENT_DATE)::date AS current_start,
(date_trunc('month', CURRENT_DATE) - INTERVAL '1 month')::date
AS prior_start,
CURRENT_DATE - date_trunc('month', CURRENT_DATE)::date AS days_elapsed
), mtd AS (
SELECT
'current' AS period,
SUM(r.amortized_cost_usd) AS cost
FROM cost_daily_rollups r
CROSS JOIN period p
WHERE r.usage_date >= p.current_start
AND r.usage_date < p.current_start + p.days_elapsed
UNION ALL
SELECT
'prior',
SUM(r.amortized_cost_usd)
FROM cost_daily_rollups r
CROSS JOIN period p
WHERE r.usage_date >= p.prior_start
AND r.usage_date < p.prior_start + p.days_elapsed
)
SELECT
MAX(cost) FILTER (WHERE period = 'current') AS mtd_spend,
MAX(cost) FILTER (WHERE period = 'prior') AS prior_mtd_spend,
ROUND(
100.0 * (MAX(cost) FILTER (WHERE period = 'current')
- MAX(cost) FILTER (WHERE period = 'prior'))
/ NULLIF(MAX(cost) FILTER (WHERE period = 'prior'), 0), 1
) AS mtd_growth_pct
FROM mtd;