Module 2: The Bedrock Cost Model
6. Why Infracost can't solve this alone, and what can
Description
Lesson 5 left a question with no observable answer: Infracost's authentication gate blocked before bedrock.tf got analyzed. This lesson answers that question through a different route — not running scan again, but reading directly from Infracost's public documentation of which resources it supports — and, with that answer in hand, explains something deeper: even if Infracost supported aws_bedrock_guardrail with a complete price, it still couldn't solve the real problem of costing extract-shipment-manifest-fields. The reason isn't a flaw in the tool — it's structural, and this lesson names it precisely.
Connection to the module
Lessons 4 and 5 confirmed, with real execution, exactly how far Infracost reaches. This lesson explains why it reaches exactly that far, with the same vocabulary finops-and-cost-guardrails-guide already installed for Lambda and DynamoDB, taken one step further. Lesson 7, immediately after, builds the piece this lesson clearly defines as missing.
First, the pending question: does Infracost support Bedrock, even without volume?
Infracost's public documentation lists, category by category, which AWS Terraform resources it has pricing support for — verified at infracost.io/docs/supported_resources/aws/ at the time of writing this guide. A specific search was made for any mention of bedrock, sagemaker, or any Machine Learning / Artificial Intelligence category on that page.
The result, verified by direct reading: no aws_bedrock_* resource appears in Infracost's list of supported resources, paid or free tier. There's no "Machine Learning" or "AI" category in the page's structure. Searching for "bedrock" in that documentation returns no results.
This answers, with evidence — not with lesson 5's blocked attempt —, the question left pending: even if the authentication gate hadn't blocked anything, aws_bedrock_guardrail would very likely have shown up unpriced, not because Infracost decided Bedrock is usage-based with no declared volume (the same pattern you already saw with Lambda and DynamoDB), but because the resource type itself isn't in its catalog yet. It's a different, more complete category of absence than finops-and-cost-guardrails-guide's lesson 5, which did find DynamoDB and Lambda listed, just with their total marked "Cost depends on usage."
THREE LEVELS OF "NO PRICE," FROM LEAST TO MOST COMPLETE
1. Supported resource, fixed price aws_instance (EC2)
-> Infracost gives a complete number, nothing more needed.
2. Supported resource, *usage-based*, no volume aws_lambda_function,
declared aws_dynamodb_table
-> Infracost knows WHICH axis bills (invocations,
read/write units), but not HOW MUCH --
"Cost depends on usage". finops-and-cost-guardrails-
guide solves this with infracost-usage.yml (M2.6).
3. Resource NOT supported in the catalog aws_bedrock_guardrail
-> Infracost doesn't even have a billing axis
to offer. There's no field to fill with a
volume assumption -- the catalog doesn't
recognize the resource type at all.
Why level 3 is different, and harder, than level 2
finops-and-cost-guardrails-guide already solved level 2 with a real mechanism, documented in its Module 2, lesson 6: infracost-usage.yml, a file where you declare, for every usage-based resource Infracost does recognize, a volume assumption — monthly_write_request_units for DynamoDB, monthly_requests for Lambda. Infracost reads that file, combines it with the per-unit price it already knows, and produces a total. It's a real mechanism, and it's worth understanding exactly what it needs to work: it needs the resource type to already be in the catalog, with its billing axes already modeled by Infracost. The usage file only fills in the missing number — it doesn't teach Infracost what a resource it's never seen before is.
aws_bedrock_guardrail fails before that stage. It's not that a usage file is missing — it's that there isn't, yet, any definition in Infracost's catalog of what billing axes that resource type has, nor of whether the aws_bedrock_guardrail resource itself even represents something billable (in fact, it isn't: a guardrail by itself doesn't generate a charge for existing — the real charge would come from a later invocation of bedrock-runtime:InvokeModel, a call that isn't even made through a Terraform resource).
The underlying problem: no invocation has a Terraform resource representing it
This is this lesson's central piece, the one no future version of Infracost's catalog — not even if it someday adds complete support for aws_bedrock_guardrail — could solve on its own. Review exactly what Terraform declares about Andes Cargo's AI workload:
WHAT IS IN andes-cargo-infra/ WHAT WILL NEVER BE THERE
aws_bedrock_guardrail Every individual call to
(one content policy, bedrock-runtime:InvokeModel
declared once) that extract-shipment-manifest-
fields makes at runtime -- one
aws_iam_role per each ManifestParseFailed
(the role that AUTHORIZES invoking, event that arrives, with
declared once) different content every time.
aws_lambda_function
(the handler that CONTAINS the
invocation logic,
declared once)
Compare this with Lambda or DynamoDB, where the infracost-usage.yml mechanism does work: aws_lambda_function is the same resource Terraform declares AND the same resource AWS bills per invocation — there's a one-to-one correspondence between "what's in the plan" and "what generates the bill." With Bedrock, that correspondence breaks: what Terraform declares (aws_bedrock_guardrail, the IAM role, the Lambda function making the call) is configuration and supporting infrastructure. What AWS bills — every InvokeModel call, with its specific count of input and output tokens — happens entirely outside Terraform, at runtime, orchestrated by Python code inside the Lambda function's handler, not by any declared resource.
No tool that reads only HCL or a tfplan.json can solve this — not because of a limitation specific to Infracost, but because the missing data (how many tokens each future invocation is going to process) doesn't live in any infrastructure-as-code artifact. It's the exact difference this module's lesson 1 already anticipated: Lambda and DynamoDB are usage-based in volume (how many times), Bedrock is usage-based in volume and in content (how many times, and how much text each time) — and that second axis never appears in a Terraform plan, no matter how complete the pricing catalog of the tool reading it is.
What CAN solve this: a declared assumption, not a smarter tool
This lesson's conclusion isn't "a better tool than Infracost is needed." It's that the missing data — average input tokens, average output tokens, monthly invocation volume — is a product decision declared by a human, not something any static analysis tool can infer by reading code. finops-and-cost-guardrails-guide already demonstrated this exact thing, at a smaller scale, with infracost-usage.yml: the file doesn't calculate Lambda's volume, someone declares it, based on a business hypothesis documented in COST-PROFILE.md.
This module's lesson 7 builds exactly that piece: a custom calculator, in Python, that takes as explicit input — never inferred, never assumed by default — the average size of an invocation and the expected monthly volume, together with the public price cited in lesson 2, and produces a deterministic cost projection. It doesn't replace Infracost — it solves the part of the problem Infracost, by design, can't touch: the volume and content assumption only a human with knowledge of Andes Cargo's business can declare.
Common mistakes
Expecting future Infracost support for aws_bedrock_* to solve the whole problem (expectation-about-the-tool, not the data, mistake). What happens: someone concludes that, if Infracost ever adds aws_bedrock_guardrail to its catalog, the problem of costing extract-shipment-manifest-fields would disappear entirely. How to spot it: if your takeaway from this lesson is "we just need to wait for Infracost to catch up." How to fix it: even if Infracost added complete aws_bedrock_guardrail support tomorrow, it would still face the same underlying problem this lesson named: no individual InvokeModel invocation has a corresponding Terraform resource. Catalog support would resolve, at best, an infracost-usage.yml with an "average input tokens" and "average output tokens" field to declare — exactly the same kind of human assumption lesson 7's calculator already builds, with or without Infracost.
Confusing "Infracost doesn't have aws_bedrock in its catalog" with "Infracost is a bad tool" (unfair scope-judgment mistake). What happens: someone, after this lesson, concludes Infracost is incomplete or poorly maintained. How to spot it: if your reaction is to dismiss Infracost as a reliable tool for the rest of this ecosystem. How to fix it: Infracost supports over a thousand Terraform resources across AWS, Azure, and Google Cloud — enormous coverage for traditional infrastructure —, and remains the right tool for everything this ecosystem has already built (S3, Lambda, DynamoDB, EC2, and dozens more). That a relatively new service with a genuinely different billing model (Bedrock, with cost per each invocation's content) isn't yet in its catalog is a specific coverage limitation, not a general flaw in the tool.
Thinking this lesson's problem is exclusive to Bedrock, and wouldn't repeat with any other generative AI service (narrow-scope mistake). What happens: someone assumes this gap is a Bedrock-specific quirk, and that another LLM provider would solve the estimation problem on its own. How to spot it: if your reasoning is "this wouldn't happen if we used a different AI service." How to fix it: the underlying problem — that cost depends on each invocation's content, not on a resource declared in infrastructure as code — is inherent to any LLM inference API billed per token, whether it's Bedrock, a model provider's direct API, or any other managed service with the same pricing model. It isn't a flaw in Bedrock or AWS — it's the nature of billing per variable content instead of per fixed infrastructure.
Exercises
Exercise 1 — Explain, in your own words, the difference between "level 2" and "level 3" in this lesson's table, using Lambda and Bedrock as an example of each. A colleague, after reading about infracost-usage.yml, asks why that same mechanism wouldn't work directly for Bedrock. Explain the difference using this lesson's example.
See solution
Lambda (level 2) is in Infracost's catalog, with its billing axes (invocations, duration) already modeled — the only thing missing is the expected number of invocations, which infracost-usage.yml provides. Bedrock (level 3), verified in this lesson, isn't even in that catalog — there are no billing axes modeled at all for aws_bedrock_guardrail, so there's no infracost-usage.yml field that could be filled in to solve it, even if someone tried. A usage file fills a gap in a model that already exists; it can't create a model Infracost doesn't have yet.
Exercise 2 — Explain why "no Bedrock invocation has a Terraform resource representing it" is a different problem from the "usage-based with no declared volume" you already saw with DynamoDB. How does it differ structurally, beyond one having a usage file available and the other not?
See solution
aws_dynamodb_table in PAY_PER_REQUEST mode is, literally, the same object AWS bills per read/write unit — there's a direct correspondence between the resource declared in HCL and the bill's line item. The only thing missing is how many of those units there are going to be. With Bedrock, there's no Terraform resource that is "an invocation" — aws_bedrock_guardrail is a configuration policy, not an object that gets invoked; the real invocation happens in Python code, inside a Lambda handler, at runtime, completely outside any .tf file. The difference isn't just "a number is missing" — it's that there's no declared resource that is, even conceptually, the object being billed.
Exercise 3 — Predict what kind of data lesson 7's calculator is going to ask for, based on this lesson's conclusion. Without having read lesson 7 yet, what kind of information do you think a human is going to have to explicitly declare for that calculator to work?
See solution
Based on this lesson's conclusion — that the problem is one of content (tokens per invocation) and volume (how many invocations), and that neither can be inferred from Terraform —, it's reasonable to predict the calculator is going to ask for, at minimum: the average number of input tokens per invocation (a typical free-text manifest's size), the average number of output tokens (the model's typical response size with the extracted fields), and the expected monthly volume of invocations (how many ManifestParseFailed events are expected per month). All three are, exactly, assumptions declared by a human with knowledge of Andes Cargo's business — never inferred from any infrastructure file.
Summary and next step
This lesson answered, with evidence from Infracost's public documentation, the question lesson 5 left pending: aws_bedrock_guardrail doesn't appear in Infracost's catalog of supported resources — no Machine Learning or AI category exists yet in that list. But it went one step further: even if that support existed, the underlying problem would remain unsolved, because no individual invocation of a Bedrock model has a Terraform resource representing it — the cost depends on each call's content at runtime, data that doesn't live in any infrastructure-as-code file, no matter how complete the pricing catalog of the tool reading it is.
Before moving on you should be able to: explain this lesson's three levels of "no price," with a real example of each; explain why infracost-usage.yml wouldn't work, even if you wanted to use it, for aws_bedrock_guardrail; and anticipate which three pieces of data, at minimum, lesson 7's calculator is going to need declared explicitly.
Lesson 7 builds that calculator — real, deterministic Python code, run with pytest against fixed cases — the piece that solves exactly what this lesson left defined as structurally out of reach for any infrastructure-as-code analysis tool.
Resources
- Infracost — Supported resources: AWS — the verified source confirming no
aws_bedrock_*resource appears in Infracost's catalog at the time of writing this guide. finops-and-cost-guardrails-guide, Module 2, lesson 6 (06-usage-based-resources-and-the-usage-file.md) — the source ofinfracost-usage.yml, the mechanism this lesson explains isn't enough for Bedrock.- AWS Docs — InvokeModel — reference for the real operation Bedrock bills, the one that never shows up as a Terraform resource.
- This module, lesson 1 — the original distinction between usage-based in volume and usage-based in content, which this lesson develops in depth.