The question this answers
Which service is responsible for which part of the bill, and who can act on it?
Six teams deploy into shared infrastructure. The bill grew 40% last quarter and the only artifact anyone can point at is a total. Each team believes their part is small. Until spend can be attributed to the service that caused it, no engineer can act and the conversation stays with finance.
A per-service breakdown with an agreed treatment of shared costs, so each team sees a number they recognize, can influence, and are accountable for.
A breakdown someone can argue with
The point of per-service cost is behavioural, not accounting. A total tells an engineer nothing they can act on. "The search service is 31% of the bill, and 60% of that is the vector index instance running at 8% utilization" tells them exactly what to do on Monday. The precision required is much lower than people assume — you need the ranking and the rough proportions to be right, not the last percent.
The panel below is a conceptual breakdown of a platform, split the way an engineering organization would want to read it. Every value is simulated to demonstrate the shape. Two features of it are worth naming. First, the observability line is charged to the platform rather than distributed, because no team can influence it individually and charging it out produces arguments instead of changes. Second, there is an explicit unattributed bucket, and it is not small. Pretending it is zero is the most common way these reports lose credibility.
Notice also what the breakdown reveals that a total conceals: the cache costs more than the API it accelerates. That is not automatically wrong — it may be preventing a much larger database — but it is a question worth asking, and it is a question that only exists once the bill is split.
Bars are relative weights, not currency. Real rates depend on provider, region, commitment and volume.
Tagging is the mechanism, and it only works at creation time
Attribution is mechanically simple: every resource carries tags, the provider's cost dataset groups by tag, and the report writes itself. The difficulty is entirely organizational. Tags applied by hand are applied inconsistently and then not at all; retroactive tagging campaigns never complete because the untagged resources are the ones nobody remembers creating. The only approach that holds is enforcement at creation, in the infrastructure-as-code module, so an untagged resource is impossible rather than discouraged — see Modules: Reuse Without Hiding.
Keep the tag set small and mandatory. Four keys cover nearly everything: environment, service, team and cost-centre. Every additional key halves the chance the whole set is applied. And decide the vocabulary centrally, because service: checkout, service: checkout-api and Service: Checkout are three services as far as the cost dataset is concerned.
Some resources cannot be tagged meaningfully no matter how disciplined you are, and this is where honest reporting is won or lost. A NAT gateway serves every workload in its zone. A cluster control plane serves every namespace. A shared load balancer fronts several services. Cross-zone traffic is billed at the account level with no service attribution available at all. For each of these, pick an allocation rule, publish it, and re-derive it when the shape changes. An agreed approximation everyone understands is worth far more than a precise number nobody believes.
| Cost | Attribution mechanism | Confidence | When it cannot be attributed |
|---|---|---|---|
| Instances and containers | Tag at creation; enforce in the IaC module | High | Untagged legacy resources — sweep weekly and assign an owner |
| Managed database | One database per service, or tag the instance | High | Shared database: allocate by schema size or measured query share |
| Object storage | Bucket-level tags, or prefix-level usage reports | Medium | A shared bucket needs prefix reporting, which is not always available |
| Load balancer | Dedicated balancer per service | Medium | A shared balancer: allocate by request count or GB processed per target group |
| Cross-zone and cross-region transfer | Rarely attributable — billed at account level | Low | Allocate by measured traffic share from your own telemetry, not from the bill |
| NAT gateway | Not attributable by the provider | Low | Allocate by outbound bytes per workload from flow logs, or split evenly and say so |
| Cluster control plane | Not attributable | None | Charge to the platform; distributing it produces arguments, not savings |
| Observability pipeline | Log volume per source is measurable | Medium | Charge to the platform but publish per-service volume, which is what changes behaviour |
The shared components that resist attribution
Draw the topology and the unattributable costs are exactly the boxes with many arrows pointing at them. That is not a coincidence — a resource is shared precisely because several services depend on it, and shared is what makes attribution hard. The topology below flags the four usual suspects, and the useful observation is that they are also the four components teams most often forget exist at all when estimating their own cost.
There is a structural alternative to allocation rules, and for organizations past a certain size it is the better answer: give each team its own account or project. Attribution then becomes a boundary rather than a report, since the bill arrives already separated. It costs duplicated shared components — each account needs its own NAT, its own load balancers, possibly its own cluster — which is a genuine increase in total spend traded for perfect attribution and much better blast-radius containment. Whether that trade is worth it depends on how much the arguments are costing you.
Whichever route you take, the deliverable that changes behaviour is not the absolute number. It is cost per unit of business value — per thousand requests, per active tenant, per job processed. That is the only framing that distinguishes "we cost more because we grew" from "we cost more because we got less efficient", and it is the number worth putting on a dashboard that engineers see weekly.
Key points
- Per-service cost exists to change engineering behaviour, so the ranking and rough proportions matter far more than precision.
- Tagging only works when enforced at resource creation in the IaC module; retroactive tagging campaigns never finish.
- Keep the mandatory tag set to about four keys with a centrally-defined vocabulary, or the values fragment and the report becomes noise.
- Shared components — NAT, control plane, shared balancers, cross-zone transfer — cannot be attributed by the provider. Publish the allocation rule instead of hiding the gap.
- Report an explicit unattributed bucket. Reporting it as zero is how the whole exercise loses credibility.
- Account-per-team turns attribution into a boundary rather than a report, at the cost of duplicating shared infrastructure.
- Cost per thousand requests or per active tenant is the number that separates growth from decay in efficiency.
The loop, answered
Every field is required, which is why no lesson here can recommend something without saying what it costs and what simpler thing to consider first.
- • Tags are key-value pairs attached to resources at creation and propagated into the provider's detailed cost and usage dataset.
- • The cost dataset can be grouped by tag, service, region and account, typically with a one-to-two-day delay.
- • Untaggable shared costs appear in the dataset at account scope with no service dimension, which is where allocation rules take over.
- • Allocation rules apply a proportional split derived from a measurable proxy: request counts, storage share, outbound bytes from flow logs, log volume per source.
- • Unit economics divide the allocated cost by a business metric the team already tracks, producing a number that is comparable over time.
- • Define the tag schema once, enforce it in shared IaC modules, and reject resource creation without it — a policy that blocks is worth ten that report.
- • Publish the allocation rules for shared costs alongside the report. A rule people can argue with is a rule people accept.
- • Sweep untagged resources weekly and assign an owner; the untagged set grows silently and is disproportionately made of forgotten things.
- • Report monthly to the teams, not only to finance. The report that changes spend is the one an engineer reads.
- • Track cost per unit of business value, not only absolute cost, so growth and inefficiency are distinguishable.
- • Re-derive allocation rules when the architecture changes; a split agreed two years ago describes an older system.
- • Tag drift: three spellings of the same service name, so the report shows three services and none of them look large.
- • A large unattributed bucket that grows over time, quietly making every per-service number an underestimate.
- • Attribution used as blame, after which teams optimize for a smaller reported number rather than a smaller total — moving costs into shared buckets is the usual method.
- • Allocation rules that were reasonable once and now describe a system that no longer exists.
- • Reports produced for finance and never seen by engineers, so the data exists and nothing changes.
- • Precision theatre: months spent building exact allocation when the ranking was already clear and the top item was obvious.
- • Attribution difficulty grows with sharing, not with size: a large estate of independent services is easier to attribute than a small, tightly shared one.
- • The unattributed fraction grows with the number of shared components, which is one of the quieter costs of a service mesh or a shared cluster.
- • Account-per-team scales attribution perfectly and multiplies the fixed shared components each account needs.
- • The dimension that runs out first is agreement: past a handful of teams, the argument about the allocation rule costs more than the allocation.
- • Cost reports describe architecture — service names, sizes, regions, dependencies. Treat them as internal production information.
- • Tags are useful for security too: the same environment and service labels drive policy conditions and incident scoping.
- • A service whose cost jumps without a traffic change is a security signal as often as a cost one — compromised compute and exfiltration both show up here first.
- • The attribution machinery itself costs little; detailed cost datasets are usually free, and third-party platforms are priced as a share of the spend they analyse.
- • The real expense is engineering discipline: tagging enforcement, rule maintenance and the meetings where allocation is argued.
- • Account separation for perfect attribution duplicates NAT gateways, load balancers and control planes, which is a genuine increase in total spend.
- • Every value in this lesson is simulated. Real proportions vary enormously by workload shape.
- • Percentage of spend that is attributable, tracked over time as the health metric of the tagging discipline.
- • Cost per service per month with the unattributed bucket shown explicitly beside it.
- • Cost per thousand requests or per active tenant, which is the only view that separates growth from inefficiency.
- • Month-over-month change per service, which surfaces a step change faster than any absolute number.
- • The signal that lies: a service whose reported cost fell because its dependencies moved into a shared, unattributed component.
- • For one team and one product, skip attribution entirely. The total is the number, and splitting it is pure overhead.
- • Account or project per team gives exact attribution with no tagging discipline at all, paid for in duplicated shared infrastructure.
- • Report only the top five line items rather than a full allocation. It takes an hour, it is accurate, and it drives most of the same decisions.
- • Showback before chargeback: showing teams their cost changes behaviour almost as much as billing them, without the internal accounting apparatus.
- • If the bill is small relative to salaries, the honest answer is to stop here and spend the time on the product.
- • Buys accountability and engineer-visible cost signals; costs tagging discipline, allocation arguments and a report somebody maintains.
- • Precise allocation of shared costs consumes effort disproportionate to the decisions it changes — approximate and publish the rule.
- • Chargeback creates strong incentives and rewards gaming, especially the strategy of pushing costs into shared buckets.
- • Account separation is the cleanest attribution and the most expensive one, because every account needs its own copy of the shared plumbing.
What people believe, and what is true
Tagging solves attribution.
It solves attribution for taggable resources. NAT gateways, control planes, shared balancers and cross-zone transfer need agreed allocation rules, and that bucket is not small.
We need exact numbers before we can act.
The ranking and rough proportions are what change decisions. Chasing the last few percent costs more than it ever saves.
Chargeback makes teams cost-conscious.
It makes teams conscious of their reported number. Without shared-cost rules everyone accepts, the reliable optimization is moving costs into shared buckets.
Total spend is the metric.
Total spend rises with growth. Cost per request or per tenant is what tells you whether efficiency improved or decayed underneath the growth.