Module 2: The Bedrock Cost Model
8. Project: Andes Cargo's `GENAI-COST-PROFILE.md`
Description
The previous seven lessons produced, scattered, every piece of a complete cost profile: Bedrock's five pricing models with cited figures (lesson 2), the quota limit price doesn't cover (lesson 3), the real confirmation of exactly how far Infracost reaches (lessons 4 through 6), and the custom calculator that solves what Infracost can't (lesson 7). This final project turns those scattered pieces into a single document: GENAI-COST-PROFILE.md, at the root of andes-cargo-infra/, alongside COST-PROFILE.md, which finops-and-cost-guardrails-guide already left there — a complement, never a replacement, exactly as ADR-001 promised in its Module 2 row.
Connection to the module
This document closes the module, and does something no previous lesson has done yet: it reconciles the volume this module used to test the calculator (5,000 invocations/month, in lesson 7) against the real total volume COST-PROFILE.md already declared for Andes Cargo (~400 manifests/month, in total). That reconciliation — done out loud, not hidden — is, in itself, the honesty exercise that closes this module.
Step 1 — The reconciliation this document has to do, before writing a single line
Before getting to the document, it's worth resolving a real tension an attentive reader of this guide might already have noticed: lesson 7 ran the calculator with an assumption of 5,000 invocations a month. But COST-PROFILE.md, the sibling document from finops-and-cost-guardrails-guide, already declared that Andes Cargo processes, in total, ~400 manifests a month. If extract-shipment-manifest-fields is an escalation path — a minority of the total, per ADR-001 —, how can the volume of Bedrock invocations (5,000) be more than 12 times Andes Cargo's entire manifest volume (400)?
It can't, and this lesson doesn't hide that. Lesson 7 used 5,000 as a round number, useful for testing the calculator and its pytest cases — it was never presented there as "Andes Cargo's real volume today." The project that closes this module is exactly the place where that tension gets resolved, out loud: GENAI-COST-PROFILE.md declares two scenarios, not one, each with its own justification:
TWO SCENARIOS, DECLARED SEPARATELY
REALISTIC STRESS
40 escalated manifests/month 5,000 escalated manifests/month
(10% of the ~400/month total (deliberately exaggerated --
COST-PROFILE.md already declared) more than 12x the current total --
the same kind of scenario
ADR-001 names as the signal
to reconsider the parser)
Run with this lesson's real Already run in lesson 7,
calculator reused here without repeating the command
This is the same discipline COST-PROFILE.md already established for itself: a volume assumption is a declared hypothesis, not a measurement — and when two documents in the same ecosystem use different numbers, this guide's responsibility is to reconcile them explicitly, not leave a future reader wondering which of the two is "the correct one."
Step 2 — Running the realistic scenario, this lesson's only new number
python3 bedrock_cost_estimate.py \
--model amazon.nova-lite-v1:0 \
--input-tokens 800 \
--output-tokens 150 \
--monthly-requests 40
What to expect (literal — run for real):
Model amazon.nova-lite-v1:0
Input tokens / request 800
Output tokens / request 150
Monthly requests (declared) 40
Monthly input tokens 32,000
Monthly output tokens 6,000
Input cost ($0.0600/1M tok) $0.00
Output cost ($0.2400/1M tok) $0.00
----------------------------------------------------
TOTAL MONTHLY COST $0.00
The total rounds to $0.00. This isn't a bug in the calculator — it's the real arithmetic: 40 invocations a month, at this token size, produce a fraction-of-a-cent cost that round(..., 2) correctly reports as zero dollars. This lesson doesn't hide that result or swap it for lesson 7's more "interesting" number — it presents it as is, and draws the correct conclusion from it: at today's realistic volume, this specific workload doesn't need active cost management yet. That isn't the same as "Bedrock is free" — it's a FinOps conclusion informed by a real number, exactly the discipline finops-and-cost-guardrails-guide already installed for the rest of Andes Cargo.
Step 3 — The complete document
At the root of andes-cargo-infra/, create GENAI-COST-PROFILE.md:
# GENAI-COST-PROFILE.md — Andes Cargo AI Workload Cost Model
**Status:** Active · **Owner:** Platform/FinOps · **Framework:** FinOps Foundation (Inform phase)
**Covers:** the token-based cost of `extract-shipment-manifest-fields`, the one Bedrock-backed
escalation path defined in `ADR-001-llm-as-escalation-path.md` (Module 1)
**Complements, never replaces:** `COST-PROFILE.md` (`finops-and-cost-guardrails-guide`, Module 1),
which covers the three billable AWS services already in `andes-cargo-infra/` (S3, Lambda,
DynamoDB). This document adds the fourth billable surface -- Bedrock -- with its own pricing
model, because none of the three services `COST-PROFILE.md` covers are billed per token.
**Does not cover:** infrastructure-as-code cost estimation via Infracost (attempted, not achieved
-- section 6); a cost gate as executable policy (Module 6); Provisioned Throughput as a real
decision (named with numbers in Module 6, lesson 7, not decided here).
## 1. Scope
This document declares which Bedrock model `extract-shipment-manifest-fields` uses, the volume
assumption behind that choice, the resulting monthly cost projection from
`scripts/bedrock_cost_estimate.py`, and the honest result of attempting to get that same number
from Infracost. It does not estimate infrastructure cost for `bedrock.tf` itself (the guardrail
resource has no per-existence charge) -- it estimates the cost of *invoking* the model that
resource governs, which is the number no Terraform-reading tool can produce alone (Module 2,
lesson 6).
## 2. Chosen model and rationale
**Amazon Nova Lite (`amazon.nova-lite-v1:0`), on-demand pricing tier.**
Module 1, lesson 6 named Amazon Nova Micro and Nova Lite as the starting candidates for this task,
deferring the final choice to Module 2 "with real cost numbers." Module 2, lesson 2 confirmed the
starting candidates are close in price (Nova Micro at $0.035/$0.14 per 1M tokens in/out; Nova Lite
at $0.06/$0.24), roughly 1.7x apart. Given a task with real semantic ambiguity -- free-text
manifests, unstructured, no fixed format, where a partner's phrasing varies email to email -- Nova
Lite is chosen over Nova Micro as the starting point: the price difference at Andes Cargo's
current volume (section 4) is negligible in absolute terms, and Nova Lite's larger capacity gives
more headroom for reliable extraction on a task Nova Micro was not specifically evaluated against
in this guide. **This is a judgment call, not a measurement** -- no real invocation happens in
this guide (the honesty ledger in Module 8, lesson 5 restates this without hedging). The smoke
test harness Module 7 builds is the mechanism that would validate or overturn this choice with
real evidence, once a real account runs it.
## 3. Pricing reference (on-demand, `us-east-1`, verified Aug 2026)
| Model | Input ($/1M tokens) | Output ($/1M tokens) | Source |
|---|---:|---:|---|
| Amazon Nova Micro | $0.035 | $0.14 | AWS Price List API, `AmazonBedrock` offer |
| **Amazon Nova Lite (chosen)** | **$0.06** | **$0.24** | AWS Price List API, `AmazonBedrock` offer |
| Amazon Nova Pro | $0.80 | $3.20 | AWS Price List API, `AmazonBedrock` offer |
| Amazon Nova Premier | $2.50 | $12.50 | AWS Price List API, `AmazonBedrock` offer |
**All prices above are marked VARIABLE, not permanent literals** -- see Module 2, lesson 2. What
is stable is the *shape* of the model: input and output priced separately, output consistently
several times more expensive than input, across every model in the catalog.
## 4. Volume assumptions -- two scenarios, declared explicitly
`COST-PROFILE.md` (`finops-and-cost-guardrails-guide`, section 4) already declares Andes Cargo's
total manifest volume: **~400 manifests/month**, a starting hypothesis, not a measurement, for a
small logistics operation. `ADR-001` defines the escalation path as a minority of that total,
triggered only when the deterministic `key=value` parser fails. This document declares two
scenarios against that baseline, both fed through `scripts/bedrock_cost_estimate.py`:
| Scenario | Escalated manifests/month | Rationale |
|---|---:|---|
| **Realistic** | 40 (10% of the 400/month total) | A conservative starting estimate of how often free-text manifests arrive, until Module 7's escalation-rate SLI measures the real number from live events |
| **Stress** | 5,000 | Deliberately pessimistic: an order-of-magnitude larger Andes Cargo, or a pathological scenario where a large partner permanently switches to free-text format overnight -- the scenario `ADR-001`'s Consequences section names as the trigger to reconsider the deterministic parser's coverage |
Both scenarios share the same per-invocation size assumption: **800 input tokens, 150 output
tokens** -- a free-text manifest roughly the length of a short email, and a structured response of
five extracted fields (`shipmentId`, origin, destination, weight, confidence). This size assumption
has the same status as the volume assumption: a starting hypothesis, not a measurement.
## 5. Monthly cost projection (`scripts/bedrock_cost_estimate.py`, run for real)
```
$ python3 bedrock_cost_estimate.py --model amazon.nova-lite-v1:0 --input-tokens 800 --output-tokens 150 --monthly-requests 40
...
TOTAL MONTHLY COST $0.00
$ python3 bedrock_cost_estimate.py --model amazon.nova-lite-v1:0 --input-tokens 800 --output-tokens 150 --monthly-requests 5000
...
TOTAL MONTHLY COST $0.42
```
**At today's realistic volume, the projected monthly cost rounds to $0.00.** This is not a bug in
the calculator -- it is the honest answer: 40 invocations/month of a cheap model, at this token
size, produce a fractional-cent cost that Python's `round(..., 2)` correctly reports as zero
dollars. Even at the deliberately pessimistic stress scenario -- 12.5x the entire current manifest
volume, all of it escalated -- the projected cost is $0.42/month. **The conclusion this document
draws is not "Bedrock is free," it is "at Andes Cargo's current scale, this specific workload does
not need active cost management yet"** -- a FinOps judgment, informed by a real number, not an
assumption that AI cost is automatically significant. This conclusion is revisited the moment
Module 7's real escalation-rate measurement, or real production volume, changes section 4's
assumption -- see section 7.
## 6. Infracost attempt result (Module 2, lessons 4-6)
`infracost --version` confirmed `2.16.1`, the same version `finops-and-cost-guardrails-guide`
already fixed -- zero reinstallation. `infracost scan andes-cargo-infra/`, run for real against a
project containing a draft `aws_bedrock_guardrail` resource, never reached the point of analyzing
that resource: Infracost's authentication gate blocked first, falling back to device-flow login in
this environment. Independently, `infracost.io/docs/supported_resources/aws/` was checked directly
and confirmed no `aws_bedrock_*` resource is listed in Infracost's catalog as of this writing --
so even with a completed login, a dollar figure for this specific resource is unlikely with the
current version. Structurally, this would remain true even with full catalog support: no
Terraform resource represents a single `InvokeModel` call, so no plan-reading tool can derive a
per-invocation cost from HCL alone (Module 2, lesson 6). Section 5's number comes from
`scripts/bedrock_cost_estimate.py`, not from Infracost, for this exact reason.
## 7. Document maintenance
This document's two most important numbers -- the escalation rate (section 4) and the per-invocation
token size (section 4) -- are both hypotheses, not measurements, exactly like `COST-PROFILE.md`
declares for its own volume assumptions. Module 7, lesson 4 of this guide computes a real
escalation rate from a fixed, deterministic set of test events, without invoking any model -- the
first real data point against which section 4's "10%" guess should be checked. This document is
reviewed, not rewritten from scratch, the moment that real number exists, or the moment Andes
Cargo's total manifest volume (the `COST-PROFILE.md` baseline this document builds on) changes.
Step 4 — Verifying the document
wc -l GENAI-COST-PROFILE.md
grep -c '^## ' GENAI-COST-PROFILE.md
What to expect (literal — you wrote the content, so its shape is deterministic):
117 GENAI-COST-PROFILE.md
7
One hundred seventeen lines, seven sections — scope, chosen model, prices, volume, projection, Infracost result, maintenance. If your count doesn't come out to 7, check that you haven't merged or omitted any of Step 3's seven ## headers.
Why this reconciliation matters more than the final number
This lesson's most important point isn't that extract-shipment-manifest-fields's cost is low — lesson 7 already showed that. It's that this document didn't hide the tension between two numbers from two sibling guides, and instead of quietly picking one, it declared both, each with its own justification. It's the same honesty discipline that carried every representative attempt in this module: when two sources of truth in this ecosystem don't line up exactly, the right answer is never to pick one and pretend the other doesn't exist — it's to explain, with evidence, why both have their place.
Common mistakes
Presenting only the stress scenario ($0.42) and omitting the realistic one ($0.00), because "it's the number already calculated in lesson 7" (reconciliation-laziness mistake). What happens: someone, writing their own document, directly reuses lesson 7's number without rerunning the calculator with COST-PROFILE.md's real volume. How to spot it: if your GENAI-COST-PROFILE.md doesn't mention the sibling guide's ~400/month number anywhere. How to fix it: this lesson's Step 1 exists exactly to force that reconciliation — without it, your document silently contradicts COST-PROFILE.md, the same kind of undeclared divergence that document's maintenance section warned about as the worst-case scenario.
Interpreting a $0.00 total as "there's never a need to think about this workload's cost" (over-generalization mistake). What happens: someone, seeing Step 2's result, concludes Module 6 (FinOps for tokens) is unnecessary for Andes Cargo. How to spot it: if your reaction to the $0.00 is "so we don't need a budget for this." How to fix it: the document's section 5 is explicit — the conclusion isn't "free forever," it's "doesn't need active management yet, at this specific volume." Module 6 still exists because volume can change, and the budget that module builds is exactly the mechanism that catches that change before it becomes a real problem — not a response to a problem that already exists today.
Treating section 3's prices as final, without the "VARIABLE" note (expectation mistake, the same one already named in lesson 2). What happens: someone cites this document months later as if Nova Lite's price were a permanent fact. How to spot it: if you're making a real budget decision based on a price from this document without having checked it again. How to fix it: section 3 says so explicitly, with the same discipline COST-PROFILE.md already established for S3/Lambda/DynamoDB — check against aws.amazon.com/bedrock/pricing/ on the day you need the real number.
Exercises
Exercise 1 — Verify the document didn't lose any data from previous lessons. Compare, section by section, Step 3 against this module's lessons 2, 5, 6, and 7. Do the five pricing models, the Infracost attempt result, and the cost projection match exactly what those lessons already showed?
See solution
They should match exactly: the four models cited in section 3 (Nova Micro, Nova Lite, Nova Pro, Nova Premier) with the same prices from lesson 2; the Infracost attempt result in section 6 (authentication block, confirmed no aws_bedrock_* in the public catalog) with the real finding from lessons 5 and 6; and the $0.42/month stress-scenario projection in section 5 with lesson 7's literal output. If you found any difference, check that no invented number got introduced while transcribing — the same discipline COST-PROFILE.md already required of itself.
Exercise 2 — Explain why section 2 explicitly says "This is a judgment call, not a measurement" about choosing Nova Lite. Why doesn't the document simply state "Nova Lite is the right model" without that caveat?
See solution
Because no real invocation of any model happens in this guide — choosing Nova Lite over Nova Micro is based on relative-capability reasoning (a task with more semantic ambiguity probably benefits from a model with more capacity), not on a success rate measured against real data. Stating "Nova Lite is the right model" without that caveat would present a judgment call as if it were a verified fact — exactly the kind of broken honesty this entire guide avoids, the same discipline that labels every model output "(representative)" whenever it appears in any other lesson in this guide.
Exercise 3 — Predict what would change in this document if, in Module 7, the real measured escalation rate turned out to be 25% instead of the 10% assumed in section 4. Based on section 7 ("Document maintenance"), what steps would you follow?
See solution
Per section 7, this document gets reviewed — not rewritten from scratch — the first time a real escalation-rate number exists. With a real 25% instead of the assumed 10%, section 4's "Realistic" scenario would go from 40 to 100 escalated manifests/month (25% of 400), and scripts/bedrock_cost_estimate.py would need to be rerun with that new volume to update section 5 with the corresponding real total. The rest of the document — the chosen model, the cited prices, the Infracost attempt result — wouldn't need to change, because none of those three depend on the escalation rate's specific value.
Summary and next step
This Module 2 final project wrote GENAI-COST-PROFILE.md: seven sections declaring the chosen model (Nova Lite, with its explicit justification as a judgment call, not a measurement), the cited, verified price, two volume scenarios reconciled against the sibling guide's COST-PROFILE.md ($0.00/month realistic, $0.42/month stress), and the honest result of the Infracost attempt (blocked by authentication, and structurally outside its catalog either way). You verified the document with wc and a section count, and confirmed that reconciling numbers between sibling guides — not hiding a real tension — is, in itself, this lesson's most important work.
Before moving on you should be able to: explain the purpose of each of the document's seven sections; recite why Nova Lite was chosen over Nova Micro, without looking at the document; and explain why a $0.00 total doesn't mean "never think about this again."
With GENAI-COST-PROFILE.md closed, the complete Module 2 — eight lessons, from the "price per token" intuition to this document — is behind you. Module 3 opens with the ADR-001 row that corresponds to it: declaring the AI workload's complete infrastructure as real code, actually validated and planned, with no need for LocalStack or an AWS account to do it — the module with the most executed weight in this entire guide.
Resources
finops-and-cost-guardrails-guide, Module 1, lesson 7 (07-hands-on-writing-the-cost-profile-document.md) — the source ofCOST-PROFILE.md, the sibling document this lesson explicitly reconciles, never replaces.ADR-001-llm-as-escalation-path.md(Module 1, lesson 8, this same guide) — the source of the row assigning this module the responsibility of fixing the escalation path's cost.- This module, lessons 2, 5, 6, and 7 — the complete source for every piece of data in this document: prices, the Infracost result, and the calculator.
- FinOps Foundation — FinOps Framework — the source for the Inform phase, cited in this lesson's document header, the same one
COST-PROFILE.mdalready cited.