The cloud budget report your CFO actually reads

Every month the bill is diffed against the budget you set, every movement is attributed to the team, service or decision behind it, and the result is written up for a finance partner to read without an engineer beside them.

Request access See how it works
Shape
monthly subscription, per billing account
Grows from
cost-diff, idle-hunter, k8s-rightsizer-report
Cloudledger · Statement of variance acme-prod · September 2026 amounts in EUR
Budget 48 000 declared once, per account
Actual 53 660 billing export, period closed
Variance +11.8% 5 660 over the line
Movements ranked by amount, September 2026 against August 2026, amounts in EUR.
Rank Movement Line Attributed to
1 +3 120 NAT gateway, eu-west-1 cross-zone traffic since the 04 Sep deploy of svc-media
2 +1 940 EC2 on demand, m6i.2xlarge reserved capacity expired 31 Aug, not renewed
3 +870 RDS storage autoscaling storage on analytics-replica, no ceiling set
4 -610 S3 standard lifecycle rule moved 40 TB to infrequent access
Unowned spend 7 510 · 14% across 61 resources with no team tag. Nothing attributes it: that is the finding.
Year to date 447 900 spent against 432 000 budgeted 3.7% over the line
Forecast, unchanged 56 900 in October budget breached by week two
Ranked by amount recovered
  1. Renew the reservation.
  2. Cap analytics-replica storage.
  3. Delete three environments idle 40+ days (idle-hunter).
Example output. The written report says the same thing in paragraphs, for the reader who does not open a table.
variance=+11.8%
this month against the budget line, before anyone asked
top_mover=nat-gateway/eu-west-1
the single line that explains most of the movement
unowned_spend=14%
resources no tag, team or ticket accounts for

Readings from the last run.

01The problem

The bill arrives with numbers and without reasons

Cost Explorer, the billing exports and the FinOps dashboards all answer the same question: how much, by which service, over which period. Finance asks a different one: why did it move, who owns the movement, and is it inside the number agreed in January. That answer is assembled by hand, by an engineer, once a quarter, in a spreadsheet nobody trusts a month later.

Budgets are set once a year and checked when the invoice hurts. By then the NAT gateway has been routing cross-zone traffic for three months, the environment nobody deleted has been running since the demo, and the reserved capacity that expired in March has been billed on demand since April. Each is visible in the export. None of it is visible as a sentence.

cost-diff produces the ranked diff of two periods. Around it sit the schedule, the budget to compare against, the attribution to a team or a decision, and the writing. That is the hosted layer.

02The deliverable

What lands in the inbox every month

A written account of the month with the figures inside the sentences, addressed to the reader who signs off the number rather than to the one who runs the console.

Cloudledger · Monthly report acme-prod · September 2026 amounts in EUR

Cloud spend in September was 53 660, 11.8% above the monthly budget of 48 000. Year to date the account has spent 447 900 against 432 000 budgeted, so the annual number is still recoverable and this month is the one that decides it.

Most of the movement is a single line. The NAT gateway in eu-west-1 added 3 120 after the deploy of svc-media on 04 September began routing traffic across zones. A VPC endpoint for the two buckets it reads removes the charge without touching the service.

Reserved capacity on the m6i.2xlarge fleet expired on 31 August and was not renewed, so 1 940 of steady-state compute was billed on demand. Renewing on the same term returns the line to budget from the first of next month and changes nothing that is running.

Storage on analytics-replica autoscales with no ceiling set and added 870; a ceiling at its current size holds the line. Against that, the lifecycle rule applied in August moved 40 TB to infrequent access and took 610 off S3, the first month that saving is visible in the bill.

Unowned spend is 7 510, 14% of the bill, spread across 61 resources carrying no team tag. That share of the bill cannot be attributed to anyone, and it will appear in every report until the tags exist.

Left alone, October forecasts at 56 900 and breaches the budget in week two. The three actions named above recover 5 930 between them and none of them needs a code change.

Prepared for acme-prod · period closed 30 September 2026

Example output. The same month as the statement above, written out for the reader who does not open a table.

03What it does

The annual number in an hour, then every month against it

Budget season is one hour of it. The rest is the twelve reports that hold the number afterwards.

Budget season

An annual budget in an hour

Twelve months of billing history is read, per-service growth is separated from seasonality, and the line items come out in the shape finance asks for. The spreadsheet that used to take a fortnight.

Every month

Budget against actual, in writing

Each closed period is compared with the budget line and with the period before it: the variance, the cause of it, and where the year lands if nothing changes. Forwarded as it arrives, with nothing to translate first.

Inside the month

Overage alerts in week one

A service trending past its budget line is flagged while the period is still open, by email, Slack or webhook, rather than confirmed by the invoice four weeks later.

On demand

Scenario modelling

Three more GPU instances in the second quarter, or Postgres moved off RDS: the change is entered against the current run rate and the revised forecast and budget impact come back with it.

Attribution

Cost by team and service

Tags, account structure and Kubernetes labels allocate the bill, so each team reads its own budget and its own actuals without learning a FinOps vocabulary. What none of them accounts for is reported as unowned.

Recommendations

Every action costed

Not a count of idle resources: what to change, what it recovers, and whether it takes a deploy or a setting, ranked by the amount recovered and carried forward until it is done or dismissed.

04How it works

Up and running in fifteen minutes

A read-only role, no agent to install, and nothing but cost data read from the account. Four steps: connect, compare, attribute, write.

01

Connect

Billing exports from AWS, GCP or Azure, read-only, plus the tags and the Kubernetes labels that carry ownership. A budget per account or team is declared once.

02

Compare

Every period is diffed against the previous one and against the budget line, with cost-diff's ranking of the movers.

03

Attribute

Each movement is tied to a team, a service or a dated change where the data allows. Where it does not, the spend is reported as unowned, which is itself the finding.

04

Write

A monthly report in plain language: what moved, why, who owns it, what the forecast says, and which of idle-hunter's and k8s-rightsizer-report's suggestions would close the gap. Sent to the people who asked for it, with the numbers attached for anyone who wants to check.

05Who it is for

Whoever agreed a number and finds out in the invoice

The engineering lead who owns a budget

A cloud number was agreed with finance in January. The first sign it is off arrives with the invoice, three months of drift later, with an afternoon of spreadsheet work to explain it.

The finance partner without an engineer

Reads the report monthly, forwards it, and never has to open a console or ask what a NAT gateway is to know whether the number holds.

06What it costs

Priced per billing account, on a monthly subscription

One price per billing account, with the report and every reader included.

Charging per seat would keep the report away from exactly the people it is written for.

07Request access

Say which bill you would point it at

Requests decide which provider's export is read first.

Free for the whole beta. The first twenty-five teams keep 50% off for twelve months after launch, locked in at signup.

Your address is used for this request and nothing else. One email when there is something to show.

08Objections

Reasonable objections

A FinOps platform already does this.
Vantage, CloudZero and the rest answer how much, by which dimension, with excellent dashboards. Cloudledger is aimed at the reader who will not open one: a written monthly account against a budget, with the movers attributed. It sits beside a dashboard, and it is the thing that gets forwarded.
The tags are a mess.
Then the first report says so in one number, unowned spend, and that number is usually the argument that gets the tags fixed. Kubernetes labels, account structure and naming conventions are used to attribute what tags do not.
cost-diff is open source and can be run by hand.
It can, and the diff is the same one. What is paid for is the schedule, the budget line, the attribution and the writing, kept month after month so the reports compare.