← FinOpsAid blog

Why do we only find out at month end? Setting GitHub budgets that catch overspend early — FinOpsAid blog

Why do we only find out at month end? Setting GitHub budgets that catch overspend early

A budget that tells you the money is gone isn't a control, it's a receipt. How to scope GitHub budgets to an owner and judge them on burn rate, not thresholds.

The conversation happens in the first week of every month, and it always has the same shape. The invoice lands, it's bigger than expected, and someone asks why nobody flagged it. The honest answer is usually that somebody would have, if anything had been watching — but the budget, if there was one, was a number in a spreadsheet that nobody compared against reality until the reality was fixed.

A budget that tells you the money is already gone isn't a control. It's a receipt with a target printed next to it. The difference between the two is entirely about when the comparison happens, and getting that right turns out to be more about scope and ownership than about picking the number.

A budget is a decision, not a forecast

The most common mistake is treating a budget as a prediction of what you'll spend. It isn't. A forecast says what will probably happen; a budget says what you've agreed should happen, and commits someone to doing something when the two diverge. The FinOps Foundation puts budgeting in the same capability group as forecasting for exactly this reason: one is a measurement, the other is a commitment, and confusing them is how both stop working.

That distinction matters because it changes what a breach means. If the budget is a forecast, a breach means the forecast was wrong, which is nobody's fault and prompts nothing. If the budget is a decision, a breach means either the decision needs revisiting or the spend does — and both of those are conversations with a person attached.

So before setting the number, answer the question it exists to trigger: what happens when we cross it, and who does it? A budget with no answer to that is documentation, and it will be ignored exactly as documentation is.

Scope it where someone can act

GitHub bills at the organization level, which makes an org-wide budget the obvious first move and the least useful one. An org budget tells you that collectively you're over. It doesn't tell anyone in particular to do anything, and the natural response — everyone assumes it's someone else's line item — is the same as no response at all.

Budgets earn their keep when they're scoped to something with an owner. That means a team, a department, a repository, or a product surface: Copilot seats, Actions minutes, Codespaces. The scope should be small enough that one identifiable person can change the outcome and large enough that they aren't drowning in alerts. This is the same argument as showback before chargeback, applied forward instead of backward — attribution tells you who spent it, a scoped budget tells them before they finish spending it.

GitHub has moved some way toward this itself. Alongside the shift to usage-based Copilot billing it shipped cost centers with AI credit pools, and budgets that can be set at enterprise, cost-center and per-user level — so for Copilot credits specifically you now get a native scope with a native cap. Use it. A control enforced at the source beats one enforced by a dashboard every time.

What it doesn't cover is everything else. Cost centers pool AI credits; they don't tell you what a team's Actions minutes, Codespaces hours or storage came to. For those scopes you're still budgeting against figures you attribute yourself.

Which leads to the caveat worth stating plainly: some scopes can only be budgeted against modeled figures, because GitHub doesn't attribute the underlying cost that way. That's fine for a warning band. It's a poor basis for a hard commitment, and the budget should carry the label so nobody argues about the number instead of the spend.

Units matter more than they look

Not every GitHub surface is best budgeted in dollars.

Seats are naturally budgeted in seats: "this team gets 40 Copilot licences" is enforceable, legible, and doesn't move when pricing changes. Actions is naturally budgeted in minutes for engineering and dollars for finance, which means you want both views over the same underlying number. AI credits are the awkward one, because credits are a usage signal rather than a billed amount — budget them in credits if the goal is controlling usage, and only convert to dollars when reconciling.

Picking the natural unit is what makes a budget a tool engineers will use rather than a finance artefact imposed on them. A team can reason about "we have 12,000 minutes left this month." Almost nobody can reason as quickly about the dollar equivalent.

Burn rate beats the threshold

Here's the change that actually moves the month-end problem: stop asking have we crossed the line and start asking are we on pace to.

A threshold fires when you've already spent the money. Burn rate compares spend-to-date against elapsed-time-to-date and tells you the trajectory. On the ninth of a thirty-day month, having used 42% of the budget isn't a breach and never triggers a threshold — but it's a clear signal you'll finish around 140% unless something changes. That's three weeks of warning instead of a post-mortem.

Burn rate needs one adjustment to be trustworthy: your spend isn't uniform across the month. CI is quiet at weekends, and a month with an extra Monday genuinely costs more. Compare against elapsed working days rather than calendar days, or you'll generate a false alarm every weekend and a false all-clear every holiday.

Burn rate warns three weeks before a threshold fires Spend to date plotted against elapsed working days. On day nine the budget is only 42 per cent consumed, so a threshold alert stays silent, but the trajectory already projects finishing at about 140 per cent of budget. The pace line shows what on-track consumption would look like. BUDGET CONSUMED — ONE MONTH BUDGET — 100% ON PACE DAY 9 · 42% USED no threshold has been crossed PROJECTED 140% DAY 1 WORKING DAYS ELAPSED MONTH END A threshold fires when the money is spent. Pace tells you on day nine, while it is still cheap to respond.
Nothing is "over" on day nine — that's the point. The gap between the white line and the dashed pace line is the entire warning, and it only exists if the comparison runs daily. Illustrative figures.

Warning bands, and one hard line

Give each budget three states rather than two.

Ok is on pace. Warn is a projection that lands over, or utilisation crossing a band like 80% — this is where nearly all the value is, because it's the only state where a response is still cheap. Over is the commitment actually broken. The point of separating warn from over is that they demand different responses: warn is a nudge to the owning team, over is a conversation with whoever agreed the commitment.

Only the hard commitment deserves to interrupt anyone. Everything else belongs in the same-day tier, which is the whole logic of alert tiering — and it's why the budget and the alert policy need designing together rather than separately.

Budgets that survive contact with a real month

None of this requires a big process. It requires the comparison to happen daily instead of monthly, and for the result to reach somebody who can still change the outcome.

FinOpsAid does the comparison for you: Budgets tracks spend against budgets scoped to org, team, department, repository, user or product — in dollars or AI-credit units — with ok/warn/over tone and pace built in, every figure marked billed or modeled, and each one stamped with the sync it came from.

Frequently asked questions

Why does a GitHub budget only warn me once the money is gone?

Because a dollar budget on AI spend stays at zero until the included allowance is exhausted, so the threshold trips late in the cycle. A budget denominated in AI credits climbs from day one and warns while there is still time to act.

What is the right scope for a GitHub budget?

Somewhere a named person can act. A budget on the whole organization tells you something is wrong without telling anyone what to do. Scope it to a product, a team or a cost center with an owner, and keep the total number of budgets small enough that each one still means something.

Should I judge a budget on threshold or burn rate?

Burn rate. Percent used means nothing without knowing what day of the month it is — 70% on the fifth and 70% on the twenty-fifth are opposite situations. Rate of consumption against time elapsed is what turns a budget from a receipt into an early warning.

Want to hear about the overspend on the ninth instead of the first? Connect your GitHub org — read-only and free during beta — or explore the demo dashboard first.