← FinOpsAid blog

Which dev environments are billing us for nothing? Reading the Codespaces page
Billed cost, idle and oversized flags, machine size and last-used dates — what each column on the FinOpsAid Codespaces page means, and why the org total is not a per-environment cost.
Codespaces is the shortest page in FinOpsAid and one of the most immediately actionable, because every finding on it has a named owner. It is also a page where one number does something unusual: the headline cost is an org total, not a sum of the rows beneath it. That's not a design choice — GitHub does not attribute cost per Codespace, and the page says so in the card subtitle.
The KPI row
| Tile |
What it counts |
Direction |
| Billed / month |
Org-level Codespaces spend for the month. Footnote: "org total (not per-CS)". This is billed, not modeled. |
Worse. |
| Total |
Every Codespace that exists, running or stopped. |
Neutral. |
| Active |
Currently in use. |
Neutral — active is normal. |
| Idle |
Exceeds the idle threshold, shown in the footnote as > Nd idle. |
Lower is better. These are your findings. |
| Oversized |
Exceeds the CPU threshold, shown as > N CPU. |
Lower is better. |
The two threshold footnotes matter. Idle and Oversized aren't universal truths — they're the result of thresholds, and the tile tells you which threshold produced the count. A fleet with zero idle Codespaces and a 90-day threshold is a very different fleet from one with zero at a 7-day threshold.
Why the billed figure doesn't divide by the row count
An 8-CPU Codespace last used in March is a finding without needing a price tag on it. The action — delete it — is the same whatever the exact dollar figure turns out to be.
The inventory table
| Column |
Meaning |
What to look for |
| Name |
The Codespace's generated name, with a link to GitHub's Codespaces settings. |
— |
| Repo |
The repository it was created from, linked. |
Repos that generate many long-lived environments. |
| Machine |
Machine type. |
The oversizing culprit. |
| CPUs |
Provisioned core count. |
Compare against what the work actually needs. |
| Mem |
Memory in GB. |
Scales with CPU class. |
| Last used |
Date of last use. |
The single most useful column on the page. |
| Flags |
Amber idle, red oversized, both, or a dash. |
Both flags on one row is the top of your list. |
Read Last used and CPUs together. A 2-core environment untouched for two weeks costs little. A 16-core environment untouched for two months is the row to act on first — and both are equally invisible to the developer who created them, because nothing in GitHub ever reminds you that a Codespace exists.
Idle and oversized are different problems with different fixes
Idle means nobody has used it recently. The fix is deletion, and the important subtlety is that stopping a Codespace is not deleting it — compute stops billing when the machine stops, but storage keeps billing for as long as the environment exists. That asymmetry is the reason idle Codespaces accumulate: the natural end of a task is closing a browser tab, and closing a tab deletes nothing.
Oversized means the machine is bigger than the workload needs. The fix is a smaller machine type, and it compounds — the choice was made once and multiplies every hour that environment ever runs, plus every environment cloned from the same configuration.
The lasting fix for both is org policy rather than cleanup: a retention period so unused environments are deleted rather than kept, and machine-type constraints per repository so the largest sizes require a deliberate choice. There's a full treatment in the Codespaces cost nobody owns.
What makes this page unusually easy to act on
Every Codespace belongs to a named user and a specific repository. There is no allocation rule to argue about, which puts these findings in the certain bucket rather than the modeled one — see savings you can actually defend. Send the list to owners rather than to a channel; people clean up their own forgotten environments without anyone escalating.
What people get wrong on this page
- Dividing the billed total by the row count. GitHub gives one org figure; per-environment cost doesn't exist at source.
- Assuming stopped means free. Storage bills for as long as the environment exists.
- Reading a low idle count as a healthy fleet. Check the threshold in the tile footnote first.
- Treating the snapshot as live. The card header carries a snapshot date for a reason.
- Cleaning up without setting policy. Without a retention period, you will do this again next quarter.
The 60-second read
- Idle and Oversized tiles, and the thresholds that produced them.
- Sort the inventory by Last used in your head — anything months old with a large CPU count is first.
- Rows carrying both flags: those are unambiguous.
- Note which repositories keep appearing in the Repo column. That's a template problem, not a people problem.
- Check whether a retention policy exists. If not, that's the actual deliverable.
Frequently asked questions
Does stopping a Codespace stop it costing money?
It stops the compute meter but not the storage one. A Codespace bills for storage the entire time it exists, so a stopped environment is cheap rather than free. Only deleting it stops both meters, and closing the browser tab does neither.
Why can't I see the cost of an individual Codespace?
GitHub reports Codespaces cost at organization level only — there is no per-environment, per-user or per-repository dollar figure at source. The inventory instead shows the attributes that drive cost: CPU count, memory, machine type and last-used date.
What is the difference between an idle and an oversized Codespace?
Idle means nobody has used it recently, and the fix is deletion. Oversized means the machine is larger than the workload needs, and the fix is a smaller machine type. Both counts come from configurable thresholds, shown in each tile's footnote.
Want to find your own forgotten environments? Connect your GitHub org — read-only and free during beta — or explore the demo first. Next: how to read the Storage page.