# Bedrock Cost Allocation: Fix Missing Logs and Inflated Totals

AWS’s tokenomics sample helps explain AI spending, but a working dashboard still needs careful checks on logging, identity and joins.

By Paras Madan | 2026-11-11


To allocate Amazon Bedrock spending by team, collect invocation usage, identify the caller and reconcile it against billing data. AWS’s November 10 tokenomics walkthrough provides a starting point, but deploying its infrastructure does not prove that every request is captured or that a cost query adds up correctly.

The useful question is whether you can explain a particular team’s bill without counting requests twice or quietly excluding a workload. That requires a few checks before the first dashboard reaches finance. This is a documentation and sample-code review, not a deployment test.

## Start with the current sample architecture

The [AWS walkthrough](https://aws.amazon.com/blogs/machine-learning/amazon-bedrock-tokenomics-data-lake/) describes centralizing invocation records for analysis. However, its architecture description and the current repository are not identical: the walkthrough describes a Lambda transformation, while the [repository’s recommended implementation](https://github.com/aws-samples/sample-bedrock-token-cost-allocation) uses Firehose’s native CloudWatch Logs processing.

Follow one reviewed revision rather than assembling steps from both. The repository sends source-account CloudWatch logs through a central destination into Firehose, then stores Parquet for Glue and Athena. Its README also warns that the source-account parameter is not currently interpolated into the destination policy. Review that policy for the accounts you actually intend to authorize.

Deploy the central resources first and pass their destination ARN to each source stack. Then enable Bedrock invocation logging in each source account. Creating the stack and enabling the service’s logging configuration are separate steps. The saved Athena query also needs execution before its convenience view exists.

## Missing requests can be an endpoint problem

The [invocation logging documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html) says logging is disabled by default and configured per account and Region. It captures supported calls through bedrock-runtime, including its OpenAI-compatible APIs. The equivalent APIs through bedrock-mantle are not currently captured.

That distinction matters when two applications both appear to be using “Bedrock.” A working CloudWatch pipeline for one does not establish coverage for the other. Inventory endpoints before interpreting an empty dataset as zero usage.

For a missing request, work downstream from the source. Check the account, Region, endpoint and logging configuration, then look for the invocation in CloudWatch. If it is there but absent from the lake, examine the subscription, destination authorization and Firehose delivery errors. If the Parquet object exists but Athena returns nothing, inspect the table, date filters and selected database.

Keep a small reconciliation sheet during setup: request identifier, approximate time, account, model and observed location at each step. This is more useful than repeatedly refreshing a dashboard because it identifies the first boundary where evidence disappears.

## A valid SQL query can still multiply the bill

The [sample SQL](https://github.com/aws-samples/sample-bedrock-token-cost-allocation/blob/main/Bedrock%20Data%20Lake%20SQL.md) includes joins between invocation rows and billing intervals. Inspect the grain of both sides before using these as chargeback queries.

Consider an illustrative hour containing 100 invocations and one matching billing row worth $10. A join that attaches that $10 row to every invocation produces 100 rows. Summing the joined cost column reports $1,000, although the bill still contains $10. Valid SQL and a plausible chart will not catch this mistake for you.

**Aggregate usage and cost to a compatible grain before joining them.** If the billing grain is account, resource and hour, first establish one usage aggregate and one cost aggregate for that combination. If multiple billing dimensions remain, preserve them or deliberately consolidate them before the join.

For team allocation within a shared billing bucket, define an explicit allocation rule. A token-weighted split is an estimate and can be misleading when requests mix models, output-heavy workloads or caching rates. Reconcile the allocated total back to the original billing bucket, and retain an unallocated category instead of forcing unmatched dollars onto a team.

## Test identity normalization with real examples

Invocation logs include the principal ARN. A shared application role, however, identifies an application boundary rather than necessarily identifying a team. Caller-supplied request metadata can provide additional context where your application supplies it.

Be especially careful when normalizing assumed-role identities. Removing a final path segment does not by itself convert an STS assumed-role ARN into an IAM role ARN. Those strings also differ in their service and resource prefixes. Validate your mapping with known examples, preserve the original value and measure unmatched identities before trusting a join.

A good acceptance test includes two teams sharing a role, one role with multiple sessions and one invocation whose identity does not match the billing data. The unmatched case should remain visible. Silently dropping it makes attribution look cleaner while making the totals less trustworthy.

## Give finance usage data without exposing prompts

Invocation logging can include request and response content. A cost dashboard usually needs counts, model identifiers, ownership and monetary allocation, not customer prompts. Create a restricted usage view and keep raw-content access separate, with an appropriate retention policy.

The first release should answer three questions reliably: how much usage was captured, how much billed cost was matched, and how much remains unexplained. A smaller dashboard that reconciles is worth more than an impressive one that turns a join error into a budget decision.

I’m Paras. I work at the intersection of AI, engineering and distribution.

I help teams turn complex AI infrastructure and product decisions into clear technical stories that developers and executives can use.

[Book a 30-minute call](https://cal.com/paras-madan/30min).
