Exam Room · Advanced Solutions Architect

Cost Visibility and Allocation Across an Organisation

· 40 min read

Advanced Cloud Architecture · part of The Exam Room

The situation

We run an AWS Organization with sixty-odd member accounts: two per product line for prod and non-prod, a shared-services account, a security account, a handful of sandboxes, and the sprawl that accumulates when every team gets an account. Consolidated billing is on, so one invoice lands each month. Last month it was AUD$480,000, up from AUD$390,000, and the first question in the finance review was “up because of what?”

Nobody could answer cleanly. The bill rolls up by account and by service, not by what the business cares about: product line, team, environment, customer. Finance wants a monthly showback report split by product line, to talk about margin. Engineering leads want an alert when a team crosses its allocation, and an earlier one when a runaway batch job starts burning money at 3am. The CFO wants that AUD$90,000 jump explained without a two-day spreadsheet exercise.

None of it is answerable until the spend carries the dimensions we want to slice by, and those dimensions land somewhere we can query. Today maybe a third of resources are tagged, the tags that exist disagree on spelling (team, Team, owner-team), and the one report anyone trusts is a spreadsheet the platform lead rebuilds every month.

What actually matters

Attribution accuracy is a tag-hygiene problem before it is a tooling problem. Cost Explorer, the Cost and Usage Report and a Budget scoped by tag can only group spend by dimensions present on the resources. If half the fleet is untagged, the pipeline produces a large unallocated bucket and a finance team that stops trusting the numbers. So the first decisions are how tags get applied consistently, and how untagged resources stop being created. Governance comes before reporting, or the reporting is fiction.

The split between showback and chargeback sets how precise the numbers have to be. Showback means each team sees what it spent, with no money moving; a little unallocated spend is survivable. Chargeback means the spend is billed to a cost centre, journal entries get raised, and a team that believes it has been over-charged will litigate every dollar. That needs near-total tag coverage, a defensible rule for splitting shared costs (the NAT gateways, the observability platform, the support charge), and an audit trail. Which one finance needs sets the accuracy bar for everything below it.

Timeliness splits in two. Tracking against a monthly allocation is a slow signal, and a daily refresh suits the slow decision it drives: this team is tracking 15% over, have a conversation. Catching a runaway job is fast, and by the time a monthly budget notices, the job has run for days. Cost data lags usage by hours in the billing pipeline, so real-time cost alerting has a floor no tool goes below, and the question is how close to that floor each mechanism gets.

Finding the savings is a different question from attributing the spend. Attribution says where the money went. Optimisation says where it did not need to go, through rightsizing findings, idle resources and commitment advice. One org-scale wrinkle shapes the chargeback model: a Savings Plan or Reserved Instance bought in one account discounts the whole organisation by default, so the account that commits is not the account that benefits.

What we’ll filter on

  1. What question does it answer? Attribution, alerting, anomaly-catching and optimisation are four different jobs.
  2. Granularity: can it slice by tag, account, Cost Category, service, resource, hour?
  3. Latency: how fresh is the data, and how fast does the signal fire?
  4. Automation: does it only notify, or can it act (stop the resource, apply an SCP, block the launch)?
  5. Org scope: does it cover the whole Organization, and from where: the management account, a delegated administrator, or one account at a time?
  6. Effort to stand up: a checkbox, a rule set, or a pipeline you own.

The landscape

Consolidated billing. The foundation. For billing, AWS treats every account in the organisation as one, so volume pricing tiers and free-tier limits apply to the combined usage and commitments float across accounts. It answers what the whole org cost and supplies the raw material every other tool reads. Past the account boundary it cannot say which team spent what.

Cost allocation tags. The dimension system. AWS-generated tags carry the reserved aws: prefix (aws:createdBy); user-defined tags are the ones you put on resources (team, product, environment, cost-centre). A tag does nothing for billing until it is activated on the Cost Allocation Tags page, and only the management account can do that. Allow up to 24 hours for a new key to appear there and up to another 24 for activation to take. Activation applies forward, but that is no longer permanent: the management account can backfill activation status across up to the previous twelve months, one request every 24 hours, and the values land only where the tag was already on the resource at the time.

Cost Categories. Rule-based grouping that sits above tags and accounts. Define a category (Product Line) with rules that map spend into buckets: accounts 111 and 222, or anything tagged product=greenbox, to Greenbox; these three accounts to Platform; everything else to a default. Rules evaluate top down and can reference tags, accounts, charge types and other categories. You choose an effective start date on any of the previous twelve billing months, so a category can cover history from the day you define it. Categories surface in Cost Explorer, Budgets, Data Exports and Anomaly Detection. Split charge rules (proportional, fixed or even split, ten per category) spread a shared bucket across targets, with one limit: the results appear only on the cost category details page and do not reach Cost Explorer or the CUR.

AWS Cost Explorer. The interactive analysis surface. Group and filter thirteen months of history by service, account, tag, Cost Category or usage type at daily or monthly granularity, with an eighteen-month forecast, commitment utilisation and coverage reports, and rightsizing recommendations. The management account can extend history to 38 months at monthly granularity, and can switch on granular data separately: resource-level daily, all-services hourly, and EC2 resource-level hourly, each covering the previous fourteen days only. The console is free; each paginated API request is charged at USD$0.01 (an AWS list price). It answers where spend is concentrated and why it moved, with nothing to build. It is not a warehouse, and will not join against your contract data.

The Cost and Usage Report. The source of truth for anyone building their own reporting. Delivered as CUR 2.0 through Data Exports, it drops line-item detail into an S3 bucket (one row per resource per hour per line item, with every activated tag and Cost Category as a column) and updates at least once a day. Split cost allocation data adds per-task and per-pod rows for ECS and EKS, which is how a shared cluster reaches a cost centre. Point Athena at it and chargeback becomes SQL: spend by product line joined to your contract table, unblended against amortised cost, shared costs divided by a rule you wrote. Data Exports also emits FOCUS tables and a Cost Optimization Hub recommendations export. You own the pipeline: the table, the partitions, the dashboards, the SQL.

AWS Budgets. The tracking-and-alerting tool. Create a cost, usage, RI or Savings Plans budget scoped by account, service, tag or Cost Category, over a daily, monthly, quarterly, annual or custom period, alerting at thresholds of actual or forecast spend. Budgets update up to three times a day. Budget actions turn a threshold into a control: apply an IAM policy or an SCP, or stop named EC2 or RDS instances, either automatically or after approval. Two org-scale limits matter. From the management account an SCP action can target another account, but the instance actions cannot reach outside the budget’s own account, and a budget is visible only from the account that created it.

AWS Cost Anomaly Detection. The runaway-job catcher, at no additional charge. It models normal spend and alerts on deviation past a threshold you set, ranking root causes by service, account, Region and usage type. At org scale take an AWS managed monitor on the linked account, cost allocation tag or cost category dimension: one monitor evaluates every value of that dimension independently and picks up accounts opened later, instead of one customer managed monitor per team. It runs about three times a day over Cost Explorer data that lags usage by up to 24 hours, and a newly used service needs ten days of history first. It notifies through SNS, email or chat; acting on an alert means wiring SNS or EventBridge to something that acts.

AWS Compute Optimizer. Rightsizing and idle-resource findings from CloudWatch metrics over a 14-day lookback (93 days with enhanced infrastructure metrics, which is charged). It covers EC2, Auto Scaling groups, EBS, Lambda, ECS on Fargate, RDS and Aurora, NAT gateways, DynamoDB, ElastiCache, MemoryDB, DocumentDB, WorkSpaces and SageMaker, with projected savings and the performance risk of each option. Opt in from the management account, or hand it to one delegated administrator, and it reaches every member account.

Cost Optimization Hub. The org-wide aggregator. It consolidates and deduplicates rightsizing, idle-resource, Savings Plans and Reserved Instance recommendations across every account and Region, estimating savings at your negotiated rates so two recommendations can be ranked against each other. The rightsizing and idle findings come from Compute Optimizer underneath. One delegated administrator can run it without management-account access, and the recommendations export through Data Exports.

AWS Trusted Advisor. The broad checklist, cost checks included: idle load balancers, underutilised EBS volumes, idle RDS instances, low-utilisation EC2, unassociated Elastic IPs. The full check set needs Business Support+, Enterprise Support or Unified Operations. Organisational view aggregates results in the management account, and each member account’s support plan decides which checks it runs.

Savings Plans and Reserved Instances. The commitment layer, with recommendations in Cost Explorer and Cost Optimization Hub. By default a commitment bought in any account applies across the organisation: it covers the owner account’s eligible usage first, then floats to the highest-discount usage elsewhere, recalculated every hour. The management account controls that. Sharing can be deactivated per account, or confined to groups of accounts defined by a Cost Category on the Accounts dimension, prioritised (the group first, then the rest of the org) or restricted (the group only).

Tag governance: Tag Policies and SCPs. The enforcement layer, from AWS Organizations. A tag policy declares the allowed keys and values, reports non-compliant resources, and in enforcement mode blocks create operations that supply the wrong value or the wrong capitalisation, for the resource types it supports. What it cannot do is require a tag that is absent. An SCP does that: deny ec2:RunInstances, rds:CreateDBInstance and the other create actions when aws:RequestTag/cost-centre is null, and an untagged resource never gets made. SCPs do not restrict the management account or service-linked roles, so neither falls under the mandate.

Evaluation

Side by side

Tool Question it answers Granularity Latency Acts or notifies Best for
Consolidated billing What did the whole org cost Account, service Daily usage, monthly bill Neither The foundation everything reads
Cost allocation tags Which dimension owns this spend Per tag Up to 48h to activate Neither The dimensions you slice by
Cost Categories Which business bucket owns this Rule-based Start date up to 12 mo back Neither A stable dimension over messy tags
Cost Explorer Why did spend move, where is it Service, account, tag, hourly Up to ~24h Neither Fast interactive analysis, no pipeline
Cost and Usage Report Anything, joined to your data Resource, hourly line items At least once a day Neither Custom showback and chargeback
Budgets (+ actions) Are we over an allocation Account, service, tag, category Up to 3x a day Acts (IAM, SCP, stop) Guardrails against a monthly overrun
Cost Anomaly Detection Did spend deviate from normal Service, account, tag, category ~3x a day, 24h data lag Notifies Catching runaway jobs and surprises
Compute Optimizer What is over-provisioned Per resource 14-day lookback Recommends Rightsizing with utilisation evidence
Cost Optimization Hub Which saving is worth most Per recommendation Imports within 24h Recommends Ranking savings across the whole org
Trusted Advisor Where is the obvious waste Per check Weekly refresh Recommends Broad sweep outside the other tools
Tag Policies + SCP Are resources correctly tagged Org-wide At create time SCP blocks, TP blocks bad values Making tags reliable enough to bill on

How the pieces stack

1. Governance make tags reliable Tag Policies standardise, block bad values SCP: deny untagged create hard stop at launch 2. Dimensions give spend meaning Cost allocation tags activate, backfill 12 mo Cost Categories rules, start 12 mo back 3. Data where you query it Consolidated billing one bill, shared discounts Cost + Usage Report S3, then Athena Cost Explorer interactive, no pipeline 4. Action alert and optimise Budgets plus budget actions Anomaly Detection deviation alerts Compute Optimizer rightsizing Cost Optimization Hub ranked savings
Four layers, each one only as useful as the layer beneath it. The reports and alerts at the top are fiction if the tags at the bottom are not enforced.

The solution

Agree a small tag set, then enforce it. Four mandatory keys is plenty: cost-centre, product, environment, team. A twelve-tag standard nobody can remember gets ignored. Make it real in two moves. A tag policy from the management account declares the allowed keys and values, enforces capitalisation so Team and team stop being separate dimensions, and reports what is non-compliant across every account. An SCP supplies the mandate a tag policy cannot: deny the create actions when aws:RequestTag/cost-centre is null. Mind what the SCP does not reach. The management account is exempt and so is every service-linked role, so anything a service launches on your behalf needs its own arrangement. Activate those keys as cost allocation tags the same day, from the management account, allowing 48 hours for activation to land.

Backfill the history you already tagged. Activation applies forward, which used to mean a tag activated in March left February unallocated permanently. Not any more: the management account can backfill activation status across the previous twelve months, one request a day. The catch is that backfill restores the activation, not the tags. Where a resource genuinely carried cost-centre last October, October’s spend comes back tagged; where it did not, nothing appears. Sweep the untagged backlog with Tag Editor first, or the backfill is not worth running.

Cost Categories give you a business dimension that outlives the tag mess. You still inherit half-tagged resources and accounts that predate the standard. A Product Line Cost Category covers that with rules evaluated in order: an account-list rule for accounts wholly one product, a tag rule (product=greenbox to Greenbox) for shared accounts, and a default bucket for the rest. Set the effective start date twelve months back and the whole year reads in product terms on day one, which is what “why did last month jump” needs. Split charge rules are the part that does not carry: their allocation shows on the cost category details page and never reaches Cost Explorer or the CUR, so a shared-services split that has to appear in the showback report belongs in SQL instead.

The CUR is how real chargeback gets built. Cost Explorer answers most showback questions in the console, and for awareness that is often enough. Chargeback needs line-item detail, your own business data joined in, and a rule for shared costs you can defend in a meeting. Export CUR 2.0 through Data Exports into an S3 bucket in a dedicated billing account, with resource IDs, hourly granularity and split cost allocation data for the shared clusters. Point Athena at it, partition by billing period, and chargeback is SQL: sum line_item_unblended_cost grouped by the cost-centre column, join to a contracts table by customer, allocate the platform account across product lines by their share of compute. Amazon Quick Suite, formerly QuickSight, sits on top for the finance dashboard. Present amortised cost rather than unblended, so an up-front Savings Plan spreads over the months it covers; unblended makes one team look wildly over budget in the month a three-year commitment lands.

Budgets and Anomaly Detection are alarms for different failures. A Budget scoped to a team tag or a Cost Category, alerting at 80% actual and 100% forecast, is the guardrail against a slow overrun. On the sandboxes, wire a budget action so that 100% applies a restrictive SCP, the one action that reaches another account from the management account; stopping instances works only inside the budget’s own account, so that variant belongs to a budget the sandbox owns. A fixed threshold is blind to the fast failure. A job that starts scanning all of S3 at 3am produces a spike a monthly budget notices near month-end, when the damage is done. Cover that with one AWS managed anomaly monitor on the linked account dimension and another on the Cost Category dimension, rather than a monitor per team: each evaluates every value independently and picks up new accounts without anyone adding them. Neither tool is fast, and about a day is the floor rather than a failing.

Commitment sharing decides who benefits, so settle it before finance asks. Commit centrally against the organisation’s aggregate baseline, which the Cost Explorer and Cost Optimization Hub recommendations compute for you, and let the discount float to whichever account runs the matching usage. Utilisation stays high that way. Attribution is where it gets awkward: the platform account shows a commitment charge with no matching usage, while a product team’s net cost drops without them doing anything. For showback that is a footnote. For chargeback, take one of three rules. Re-allocate the benefit by each account’s share of covered usage, which the CUR’s Savings Plans columns make computable. Deactivate sharing for a named account, so a team that commits keeps its own discount. Or group accounts with a Cost Category and set prioritised or restricted sharing, keeping a division’s commitment inside that division while the rest of the org stays pooled.

Worked example

The AUD$480k month lands, AUD$90k above the one before it. The CUR has been flowing into S3 for a year and the Product Line Cost Category was defined months ago with a start date that covers the history, so the platform lead does not open a spreadsheet. Group by Product Line in Cost Explorer and compare month over month: three product lines move by a few thousand each, and Greenbox is up AUD$85k, which is nearly the whole jump. Drill into Greenbox by service and it is EC2-Other and data transfer, not compute. Group by usage type: NAT gateway data-processing charges, tripled.

That names a behaviour rather than a mystery. Cost Anomaly Detection had fired eleven days earlier, root cause pointing at the Greenbox prod account and NAT gateway usage, and the alert went to a channel nobody owned. A new service was pulling large objects from S3 over the public path. A gateway endpoint for S3 carries no charge and takes that traffic off the NAT gateway entirely, which drops the charge back to baseline for the price of a route table entry per subnet.

Three things made the answer an afternoon’s work. The CUR held line-item detail to drill into. The Cost Category gave a product view of the whole year without anyone retagging history. Anomaly Detection had already caught it, and the failure was the alert routing. So the process fix is an owner for that channel; the tooling fix is a managed monitor on the linked account dimension, so nobody has to remember to add a team. Finance got its answer the same afternoon, and the showback report now carries a Product Line split every team recognises.

What’s worth remembering

  1. Attribution is a tag-hygiene problem before a tooling problem, so a tag policy for the shape and an SCP denying untagged creates come before any report, and that SCP reaches neither the management account nor service-linked roles.
  2. Cost allocation tags only activate from the management account and take up to 48 hours, and the twelve-month backfill restores the activation, not the tags, so history is only recoverable where the tag was already on the resource.
  3. Cost Categories carry an effective start date up to twelve months back, which is what “why did last month jump” needs, but split charge rules stop at the details page and never reach Cost Explorer or the CUR.
  4. Cost Explorer answers showback in the console with no pipeline; CUR 2.0 through Data Exports, with resource IDs and split cost allocation data, is how chargeback joins spend to your own business data.
  5. Budgets catch the overrun you can set a threshold for and can apply an SCP across accounts; one AWS managed anomaly monitor per dimension catches the spike you cannot, covering accounts opened later.
  6. A commitment bought anywhere in the org covers its owner account first and then the highest-discount usage elsewhere, so settle sharing (org-wide, per-account off, or grouped by Cost Category) before chargeback starts.

These posts are LLM-aided. Backbone, original writing, and structure by Craig. Research and editing by Craig + LLM. Proof-reading by Craig.