← Agent Frameworks 🕐 17 min read
Agent Frameworks

Bedrock Fine-Tuning and Custom Model Cost Patterns (2026)

AWS Bedrock model customization spans four distinct mechanisms — supervised fine-tuning (SFT), continued pre-training (CPT), model distillation, and reinforcement fine-tuning (RFT) — each with differe

AWS Bedrock model customization spans four distinct mechanisms — supervised fine-tuning (SFT), continued pre-training (CPT), model distillation, and reinforcement fine-tuning (RFT) — each with different billing models, CUR signatures, and FinOps implications. The decision between these and alternatives like RAG or prompt engineering is primarily economic: training is a one-time capital cost; inference is recurring operating cost. Getting the break-even math wrong by even one order of magnitude is the single most common source of customization project overruns.

This note covers the full cost stack: training, storage, inference deployment, observability overhead, and amortization.


1. Bedrock Fine-Tuning Pricing by Model

1.1 Per-Token Training Costs

Fine-tuning and continued pre-training are billed on total tokens processed, which equals dataset_tokens × epoch_count. The table below reflects current AWS pricing as of June 2026.

Model Family Model Training Cost per 1K Tokens Notes
Amazon Titan Titan Text Lite $0.00100 Smallest, fastest to converge
Amazon Titan Titan Text Express $0.00800 Mid-tier; most common for enterprise SFT
Meta Llama Llama 2 13B $0.00149 Legacy; prefer Llama 3 via CMI
Meta Llama Llama 2 70B $0.00799 ~$8/M tokens; requires large dataset to justify
Cohere Command $0.00400 Solid RAG + instruction tuning baseline
Amazon Nova Nova Micro/Lite/Pro On-demand rate (varies) See §1.2 — SFT billed at standard token rate

Nova SFT pricing anomaly. Amazon Nova custom models are billed at the same on-demand inference rate as base models — there is no training surcharge listed as a separate SKU. In practice, the training compute is embedded in the job duration. A Nova Micro SFT run on ~1.75M tokens (4,978 examples × 3 epochs) completed in ~1.5 hours and cost $2.18. This implies an effective training rate of approximately $1.25/M tokens for Nova Micro, well below Llama 2 70B.

Reinforcement Fine-Tuning (RFT). RFT on Bedrock is billed hourly, not per token. Current rates:

Model RFT Hourly Rate
OpenAI gpt-oss-20b $80.00/hr
Qwen3 32B $80.00/hr
Amazon Nova 2 Lite Not published; billed per token at customization rate

RFT jobs are typically 2–8 hours for a few thousand prompts. A 4-hour gpt-oss-20b RFT run costs $320 in compute before storage or inference. For Nova RFT, the token-based billing means costs scale linearly with dataset size and trainingSamplePerPrompt (default 4), which multiplies effective token consumption by that factor.

1.2 Storage Costs

Every custom model — SFT, CPT, distilled, or RFT — incurs a flat monthly storage fee:

  • $1.95 per model per month (standard; applies per Custom Model Unit for CMI)
  • For Custom Model Import: $1.95 per CMU per month

Storing 10 fine-tuned model versions costs $19.50/month. At scale, version proliferation becomes a non-trivial line item. See §8 on version governance.

1.3 GPU-Hour Charges

Bedrock abstracts GPU scheduling; customers do not choose instance types. The per-token rates subsume GPU cost. The exception is RFT (hourly billing) and, implicitly, Custom Model Import, which exposes compute via Custom Model Units (CMUs). One CMU maps to a discrete amount of GPU VRAM. A Llama 3.1 8B model with 128K context requires 2 CMUs; at $0.05718/CMU/minute in us-east-1, a single active copy costs $0.11436/minute or $6.86/hour.


2. How Fine-Tuning Costs Appear in CUR

2.1 CUR 2.0 Architecture

Bedrock billing uses CUR 2.0 (AWS Data Exports). The line_item_usage_type field encodes model, token type, service tier, and routing in a structured pattern:

{region}-{model}-{token-type}                         # standard tier, in-region
{region}-{model}-{token-type}-{tier}                  # priority or flex tier
{region}-{model}-mantle-{token-type}-standard         # bedrock-mantle endpoint
{region}-{model}-{token-type}-cross-region-global     # cross-region routing

Example inference line items:

usage_type Model Service Tier Token Type
USE1-Claude4.6Sonnet-input-tokens Claude Sonnet 4.6 Standard Input
USE1-Nova2.0Lite-input-tokens-flex Amazon Nova 2 Lite Flex Input
USE1-Claude4.6Sonnet-cache-read-input-token-count Claude Sonnet 4.6 Standard Cache Read

2.2 Training Job Line Items

Fine-tuning training jobs appear under the bedrock service with a distinct line_item_operation value. Based on AWS documentation and community observation:

  • Operation column: CreateModelCustomizationJob or ModelCustomization
  • Usage type pattern: {region}-{model}-customization-tokens or {region}-ModelCustomization
  • Resource ID: The ARN of the customization job

For RFT (hourly billing models), the operation is ReinforcementFineTuning and the usage type reflects compute-hours rather than tokens.

Critical reconciliation gap: CUR aggregates by usage type per hour or per day — it does not emit per-job line items. To reconcile a training job’s cost, you must join CUR on the job’s start/end timestamps and sum line_item_unblended_cost over that window for the model’s customization usage type.

2.3 Custom Model Import Line Items

CMI inference billing appears as:

  • Service: AmazonBedrock
  • Usage type: {region}-CustomModelImport-CMU-Minutes (inferred from pricing model)
  • Operation: InvokeModel or InvokeModelWithResponseStream
  • Billing granularity: 5-minute windows, even for sub-minute invocations

Idle CMI cost — a model copy loaded but not receiving traffic — is the primary cost leak. An idle 2-CMU model costs $6.86/hour. AWS added real-time cost transparency to CMI in March 2025, surfacing estimated CMU-minute charges in the Bedrock console before invocation.

2.4 Four Token Types — All Must Be Captured

A frequent CUR reconciliation error is summing only input and output tokens. Bedrock charges four distinct token types:

Token Type CUR Pattern Relative Cost
Input *-input-tokens Baseline
Output *-output-tokens 3–5× input rate
Cache Read *-cache-read-input-token-count ~10% of input rate
Cache Write *-cache-write-input-token-count ~125% of input rate

Workloads using prompt caching heavily will show reconciliation gaps of 15–30% if cache tokens are excluded from cost rollups.


3. Continued Pre-Training vs Fine-Tuning vs Distillation

3.1 Method Comparison

Dimension Continued Pre-Training (CPT) Supervised Fine-Tuning (SFT) Model Distillation Reinforcement Fine-Tuning (RFT)
Data format Raw unlabeled text Input/output pairs Teacher-generated completions Prompts + reward function
Primary use Domain vocabulary injection Task format adaptation Capability compression Reasoning/alignment tuning
Token cost Lowest (no labels needed) Medium Teacher inference + student training Highest (GRPO sampling ×N)
Dataset scale Billions of tokens Thousands to millions Tens of thousands Hundreds to thousands
Billing model Per token Per token Teacher on-demand rate + student customization Per GPU-hour (some models) or per token
Quality ceiling Adds knowledge; no behavioral change Strong task-specific gains Matches teacher on target tasks ± 2–3% Best for objective verifiable tasks

3.2 Distillation Cost Model

Model distillation has two cost stages:

  1. Synthetic data generation (teacher model, on-demand rates): Nova Premier or Claude 3.5 Sonnet v2 generates completions for your prompt set. At $0.024/1K output tokens for Nova Premier, generating 50K examples of 500 tokens each costs $600.

  2. Student model training (customization rate): Training a Nova Micro student on those 50K examples × 3 epochs = 150M × student_token_rate ≈ $188 at $1.25/M effective rate.

Total distillation cost: ~$788 for 50K examples versus $188 for SFT alone. The premium pays for higher quality training signal. Reported quality: <2% accuracy loss on target tasks, up to 75% inference cost reduction, and ~5× throughput improvement by moving from a large teacher to a small distilled model.

Distillation paths available as of 2026:

  • Nova Premier → Nova Pro
  • Claude 3.5 Sonnet v2 → Llama 3.2 1B / 3B

3.3 When Each Method Is Economical

Use Case Recommended Approach Rationale
Domain jargon (medical, legal, financial) the model misrecognizes CPT Cheapest; no labeled data required
Consistent output format (JSON schema, structured reports) SFT High ROI per labeled example
Production cost reduction while maintaining quality Distillation 75% inference savings at modest upfront cost
Math/code/logic tasks with verifiable outputs RFT Verifiable reward functions; measurable gain
Low-volume, infrequent tasks None (prompt engineer + RAG) Provisioned throughput overhead kills ROI

4. Custom Model Import (CMI) Billing

4.1 CMI Architecture

CMI imports externally trained or LoRA-adapted models (Llama, Mistral, Falcon families) into Bedrock’s managed inference plane. There is no import fee; billing applies only when inference copies are active.

Billing mechanics:

  • Unit: Custom Model Unit (CMU) — a fixed amount of GPU VRAM
  • Rate: $0.05718 per CMU per minute (us-east-1)
  • Billing window: 5-minute minimum, regardless of actual traffic
  • Europe (Frankfurt): $0.07144/CMU/minute (~25% premium)
  • OpenAI custom models via CMI: $0.1433/CMU/minute (~2.5× standard)

4.2 CMU Requirements by Model Size

AWS determines CMU count automatically based on model architecture, context length, and quantization. Observed baselines:

Model Context CMUs Required Cost/Minute (us-east-1) Cost/Hour
Llama 3.1 8B 128K 2 $0.11436 $6.86
Llama 3.1 70B 128K ~8 ~$0.457 ~$27.43
Llama 3.1 405B 128K ~32 ~$1.829 ~$109.74
Custom LoRA adapter on 8B 128K 2 (same as base) $0.11436 $6.86

LoRA adapters do not reduce CMU requirements because the inference server loads the merged weights. CMI billing reflects base model size, not adapter size.

4.3 Idle Cost — The Primary CMI Leak

A CMI model copy loaded and waiting costs identically to one serving traffic. The minimum active window is 5 minutes, meaning a single invocation to a cold CMI model costs at least $0.11436 × 2 CMU × 1 window = $0.229 for the cold-start billing window alone.

For low-traffic use cases, CMI is economically dominated by Provisioned Throughput (PT) only when traffic volume exceeds the PT commitment floor. The inflection point:

CMI_monthly_cost = CMU_count × $0.05718/min × active_minutes/month
PT_monthly_cost  = model_units × PT_hourly_rate × 730 hours/month

CMI wins when: active_minutes/month < (PT_units × PT_rate × 730) / (CMU × 0.05718)

For a 2-CMU model vs. 1-MU Provisioned Throughput at $21.18/hour (Llama 2 13B 1-month commitment):

  • PT monthly: $21.18 × 730 = $15,461
  • CMI break-even: $15,461 / ($0.11436/min) = 135,225 active minutes/month = ~2,254 hours/month

At fewer than ~2,254 active hours per month (93% utilization), CMI is cheaper than the 1-month PT commitment. CMI is almost always the right default unless traffic is continuous.

4.4 CMI vs Provisioned Throughput Decision Matrix

Signal Use CMI Use Provisioned Throughput
Traffic pattern Spiky, bursty Flat, predictable
Utilization <80% >85% sustained
Model commitment None required 1-month or 6-month
LoRA/quantized weights Yes (CMI native) No (PT requires Bedrock-native models)
Cost attribution CMU-minute granularity Hourly lump sum

5. Break-Even Analysis: Fine-Tuning vs Prompt Engineering vs RAG

5.1 The Three-Strategy Cost Model

Strategy A: Prompt Engineering Only

Cost = inference_calls/month × avg_tokens/call × on_demand_rate

For Claude Sonnet 4.6 ($3/$15 per 1M in/out) with a 2K-token system prompt + 500-token user input + 300-token output:

Monthly tokens = calls × (2500 input + 300 output)
Monthly cost   = calls × (2500 × $0.003/1K + 300 × $0.015/1K)
               = calls × ($0.0075 + $0.0045)
               = calls × $0.012

At 100K calls/month: $1,200/month. The 2K system prompt is the primary cost driver — it is repeated on every call.

Strategy B: RAG (Bedrock Knowledge Bases)

Cost = retrieval_queries × $0.01 + inference_cost_with_shorter_context + Knowledge_Base_storage

RAG reduces prompt length by replacing the full context window with retrieved chunks (typically 3–5 × 500-token chunks = 1,500 tokens vs. a 2K static prompt). Net token savings: ~500 tokens/call in this example.

Savings at 100K calls: 500 × 100K × $0.003/1K = $150/month in token savings RAG query cost: 100K × $0.01 = $1,000/month Knowledge Base overhead via OpenSearch Serverless: minimum ~$700/month (4 OCUs at $0.24/OCU-hour × 730)

RAG net cost at 100K calls/month: ($1,200 - $150) + $1,000 + $700 = $2,750/month. RAG is more expensive than pure prompting at this volume, unless retrieval replaces a much larger context window (>5K tokens).

Note: Amazon S3 Vectors (GA December 2025) reduces Knowledge Base backend cost by ~90% vs OpenSearch Serverless. At $70/month storage floor, RAG economics improve substantially for new deployments.

Strategy C: Fine-Tuned Model on CMI

One-time training cost + monthly (storage + inference)

Training:   dataset_tokens × epochs × training_rate
            e.g., 10M tokens × 3 epochs = 30M × $0.004/1K = $120

Storage:    $1.95/month

Inference:  calls × shorter_avg_tokens × rate
            (SFT bakes context into weights → shorter prompts)
            e.g., 500-token average (system prompt eliminated)
            100K calls × 500 tokens × $0.003/1K = $150/month

CMI inference for a Llama 3.1 8B fine-tuned model at 100K calls/month (assuming 10 calls/minute peak, 8 active hours/day):

Active minutes/month = 8 hrs × 60 min × 22 days = 10,560 min
CMI cost = 10,560 min × 2 CMU × $0.05718 = $1,207/month

Fine-tuned model total: $120 (amortized over 12 months = $10) + $1.95 + $1,207 = $1,219/month

5.2 Break-Even Table

Monthly Call Volume Prompt Engineering RAG (S3 Vectors) Fine-Tuned (CMI 8B) Winner
10K $120 $270 $185 Prompt Engineering
50K $600 $670 $650 Prompt Engineering
100K $1,200 $870 $1,219 RAG
500K $6,000 $3,550 $3,800 RAG
1M $12,000 $6,600 $5,500 Fine-Tuned
5M $60,000 $31,500 $18,000 Fine-Tuned

Assumptions: Claude Sonnet 4.6 base; 2K system prompt replaced by SFT; 3 retrieved chunks at 500 tokens each; CMI 8B at 2 CMUs; 40% active hours/month for CMI; S3 Vectors backend at $70/month fixed.

The key threshold: fine-tuning becomes economically favorable above ~750K calls/month when a substantial system prompt can be eliminated through model weight encoding. Below that threshold, RAG with S3 Vectors is the dominant strategy.

5.3 When Fine-Tuning Clears the Bar Regardless of Volume

Volume thresholds are not the only decision criterion. Fine-tuning is mandatory when:

  1. Latency is the constraint. SFT on a small model (Nova Micro) may be the only way to hit <200ms p95 while maintaining quality. RAG adds retrieval latency; long prompts add prefill latency.
  2. The base model fails the task structurally. Some output formats (domain-specific structured schemas, specialized code dialects) are not achievable via prompting alone.
  3. Data cannot leave the context window for compliance reasons. SFT can encode regulatory or legal knowledge into weights, avoiding retrieval of sensitive reference material at inference time.
  4. The model is used as a tool-use router. SFT for function-calling classification can reduce routing errors below the prompt engineering baseline at any volume.

6. Model Evaluation Costs for Fine-Tuned Models

6.1 Bedrock Model Evaluation Pricing

Bedrock Model Evaluation supports two evaluation modes:

Mode Cost Notes
Automatic (algorithmic) Free Uses built-in metrics; no human review
Human-based (via Mechanical Turk or private workforce) $0.21 per completed task Plus inference costs for generating model outputs

For a standard evaluation setup (50 prompts, 2 human workers per prompt):

Human tasks:     50 prompts × 2 workers × $0.21 = $21.00
Inference cost:  50 prompts × avg_tokens × model_rate
                 e.g., 50 × 1,000 tokens × $0.003/1K = $0.15

Total evaluation: ~$21.15

At 1,000 prompts with 2 workers: $420 in human evaluation fees + inference costs.

6.2 Evaluation Cadence and Amortization

A typical fine-tuning workflow involves:

  • Initial evaluation: Full benchmark suite after first training run
  • Regression evaluation: Subset (200–500 prompts) after each data update
  • Production monitoring: Continuous sample (1–5% of live traffic) with algorithmic scoring

For monthly regression evaluations at 500 prompts, 2 workers: $210/month in human evaluation overhead. This is often overlooked in TCO models and can add 10–20% to the cost of maintaining a fine-tuned model in production.


7. Multi-Turn Fine-Tuning Dataset Costs

7.1 S3 Storage for Training Data

Training datasets for Bedrock SFT are stored in S3 in JSONL format (one example per line). Storage costs are negligible at typical dataset sizes:

Dataset size estimate:
  10K examples × avg 2,000 tokens × 4 bytes/token ≈ 80 MB
  100K examples ≈ 800 MB
  1M examples ≈ 8 GB

S3 Standard cost: $0.023/GB/month
  10K examples: ~$0.002/month
  1M examples: ~$0.184/month

S3 storage is not a meaningful cost line for training data. It becomes relevant only for distillation workflows where large teacher-generated synthetic datasets are retained across multiple training runs.

7.2 Data Preprocessing Lambda Costs

For automated data pipeline workflows (cleaning, formatting, validation), Lambda charges apply:

Lambda cost model:
  Duration: $0.0000166667 per GB-second
  Requests: $0.20 per 1M requests

Typical preprocessing job (1M examples):
  Duration: 10 min × 2 GB memory = 1,200 GB-seconds = $0.02
  Requests: minimal

Data validation pass: <$0.10 per million examples

Lambda preprocessing is negligible. The real preprocessing cost is human time for data curation. For labeled SFT datasets, data labeling via Amazon SageMaker Ground Truth or Mechanical Turk typically runs $0.01–$0.50 per labeled example depending on complexity. 10K high-quality labeled examples from human annotators may cost $5,000–$50,000 — dwarfing all AWS compute costs for the training job itself.

7.3 Multi-Turn Conversation Format

Bedrock SFT and RFT both accept the OpenAI Chat Completions format (JSONL with messages arrays). Multi-turn examples are priced identically to single-turn — total tokens across all turns count toward the training token total. A 5-turn conversation averaging 300 tokens per turn (1,500 tokens total) costs:

1,500 tokens × $0.004/1K (Cohere Command rate) = $0.006 per example

For 10K multi-turn examples: $60 training cost. Data preparation is the dominant cost.


8. Versioning and Rollback Costs

8.1 Storage Cost Scaling

Each saved model version costs $1.95/month. There is no differential versioning (delta storage) — each model version is stored as full weights. Version proliferation is therefore a linear cost:

Active Versions Monthly Storage Cost
1 $1.95
5 $9.75
10 $19.50
20 $39.00
50 $97.50

At typical enterprise deployment cadences (weekly retraining for 12 months = 52 versions), storage reaches $101.40/month. Version retention policy is the primary governance lever.

8.2 Rollback Cost Implications

Rolling back to a prior fine-tuned model version requires no re-training cost — the version is already stored. However, if the rollback version is served via CMI, it must be loaded into a new CMU allocation (billing starts on load). For Provisioned Throughput, switching to a prior version requires creating a new PT commitment (minimum 1-month).

Recommended pattern: Maintain at most 3 active versions: current production, prior production (immediate rollback target), and staging (next candidate). Archive older versions to S3 directly (model weights exported) and delete from Bedrock to avoid storage fees. Re-import via CMI if needed.

8.3 Version Tagging for CUR Attribution

Tag each model version in Bedrock with cost allocation tags at creation:

bedrock.create_model_customization_job(
    ...
    customModelTags=[
        {"key": "model-version", "value": "v4"},
        {"key": "team", "value": "fraud-detection"},
        {"key": "cost-center", "value": "CC-1234"},
    ]
)

Tags flow to CUR under resourceTags/model-version, enabling per-version cost queries without manual timestamp correlation.


9. LoRA/QLoRA via CMI vs Full Fine-Tuning on Bedrock

9.1 Mechanism Differences

Dimension Full Fine-Tuning (Bedrock Native) LoRA/QLoRA via CMI
Weight update scope All parameters Low-rank adapter matrices only (~0.1–1% of params)
Training infrastructure AWS-managed Customer-managed (SageMaker, EC2, local)
Training cost location Bedrock API (per token) SageMaker/EC2 GPU hours
Model import cost N/A Free (no import fee)
Inference CMU requirement Provisioned Throughput CMI: same CMU as base model
Quality vs full fine-tuning Reference baseline 90–95% task quality retention
Memory efficiency N/A 10–20× reduction during training

9.2 LoRA Training Cost (Self-Managed)

LoRA training on SageMaker for a Llama 3.1 8B model:

Instance: ml.g5.2xlarge (1× A10G 24GB) @ $1.515/hour
Duration: ~2 hours for 10K examples, 3 epochs
Total:    $3.03 for training compute

vs. Bedrock native SFT on Llama 2 70B:
  10K examples × avg 500 tokens × 3 epochs = 15M tokens
  15M × $0.00799/1K = $119.85

For smaller models, LoRA + CMI is 40× cheaper to train than Bedrock native SFT on comparable parameter-count models. The tradeoff is operational complexity: managing SageMaker training pipelines, model merging, and CMI import workflows.

9.3 QLoRA Memory-Cost Tradeoff

QLoRA (4-bit quantization during training) reduces GPU memory 33% vs full-precision LoRA. Trade-off: 39% longer training duration, which increases SageMaker instance-hours proportionally.

LoRA training:  2 hours × $1.515 = $3.03
QLoRA training: 2.78 hours × $1.515 = $4.21 (39% longer)
QLoRA savings:  Can use ml.g5.xlarge (1× A10G 24GB) instead of larger instance
                Enables 13B–34B models on single-GPU hardware

For models up to 13B parameters, QLoRA on a single ml.g5.2xlarge is the cost-optimal training path. Above 34B parameters, full Bedrock SFT or multi-GPU LoRA becomes more practical unless the team has GPU cluster access.

9.4 CMI Inference for LoRA Adapters

Once a LoRA adapter is merged into base model weights and imported via CMI, inference billing is identical to any other CMI model — per CMU per minute. There is no LoRA-specific discount or surcharge. The primary inference advantage is smaller model footprint if a distilled or smaller base was used.


10. LiteLLM Routing for Fine-Tuned Models: A/B Testing Cost Attribution

10.1 LiteLLM + Bedrock Setup

LiteLLM proxies Bedrock custom models using the model ARN or custom endpoint alias:

import litellm

# Base model
response_base = litellm.completion(
    model="bedrock/anthropic.claude-3-5-sonnet-20241022-v2:0",
    messages=[{"role": "user", "content": prompt}]
)

# Fine-tuned model via CMI
response_ft = litellm.completion(
    model="bedrock/arn:aws:bedrock:us-east-1:123456789012:imported-model/my-ft-model",
    messages=[{"role": "user", "content": prompt}]
)

LiteLLM’s spend tracking records input_tokens, output_tokens, and cost per request using registered model rates. For CMI models, the per-token cost is not intrinsically known to LiteLLM — it must be configured via a custom pricing override, because CMI billing is per CMU-minute (capacity-based), not per token (consumption-based).

10.2 A/B Testing Cost Attribution Pattern

For controlled fine-tuned vs. base model comparison:

# litellm_config.yaml
model_list:
  - model_name: "inference-router"
    litellm_params:
      model: "bedrock/claude-sonnet-4-6"
      weight: 90  # 90% traffic to base

  - model_name: "inference-router"
    litellm_params:
      model: "bedrock/arn:aws:bedrock:us-east-1:123456789012:imported-model/ft-v4"
      weight: 10  # 10% traffic to fine-tuned

router_settings:
  routing_strategy: "weighted-pick"
  
# Add metadata tags for cost attribution
metadata:
  variant: "ft-v4"
  experiment_id: "exp-fraud-2026-06"

LiteLLM logs are emitted to your observability backend (Langfuse, Heliconia, CloudWatch) with the metadata tags. Query by variant to compare:

  • Token consumption per request (base vs. fine-tuned — expect shorter output if SFT improved format compliance)
  • Cost per request (LiteLLM estimate for base; CMU-minute allocation for fine-tuned must be computed externally)
  • Latency distribution (fine-tuned smaller model typically shows lower p50 and p99)

Critical gap: LiteLLM cannot accurately estimate CMI cost in real time because CMI charges are capacity-based (CMU-minutes), not consumption-based (tokens). The correct approach is to log all CMI invocations with timestamps, then join against CloudWatch CMU-minute metrics or CUR line items to compute actual cost per call post-hoc.

10.3 Bedrock Application Inference Profiles for A/B Attribution

For production-grade A/B attribution without LiteLLM overhead, create separate Application Inference Profiles (AIPs) per variant:

bedrock.create_inference_profile(
    inferenceProfileName="ft-v4-fraud-detection",
    description="Fine-tuned Llama 8B for fraud classification - v4",
    modelSource={
        "copyFrom": "arn:aws:bedrock:us-east-1:123456789012:imported-model/ft-v4"
    },
    tags=[
        {"key": "variant", "value": "ft-v4"},
        {"key": "experiment", "value": "fraud-2026-06"},
    ]
)

Use the profile ARN in your inference calls. Profile tags flow to CUR resourceTags/variant and resourceTags/experiment, enabling direct Cost Explorer filtering by variant. No LiteLLM proxy required.


11. CUR Athena Queries for Fine-Tuned Model TCO

11.1 Schema Assumptions

Queries assume CUR 2.0 exported to S3 and crawled by Glue. Table name: cur_database.bedrock_costs. Partitioned by year and month.

11.2 Query 1: Training Job Cost Isolation

-- Isolate all model customization spend by job name
SELECT
    line_item_resource_id                                   AS job_arn,
    resource_tags_model_version                             AS model_version,
    resource_tags_team                                      AS team,
    SUM(line_item_unblended_cost)                           AS training_cost_usd,
    SUM(line_item_usage_amount)                             AS total_tokens_thousands,
    MIN(line_item_usage_start_date)                         AS job_start,
    MAX(line_item_usage_end_date)                           AS job_end
FROM cur_database.bedrock_costs
WHERE year = '2026'
  AND month IN ('05', '06')
  AND line_item_product_code = 'AmazonBedrock'
  AND line_item_operation LIKE '%ModelCustomization%'
GROUP BY 1, 2, 3
ORDER BY training_cost_usd DESC;

11.3 Query 2: Inference Cost by Model Variant (AIP tags)

-- Compare inference cost per 1K requests: base vs fine-tuned variant
SELECT
    resource_tags_variant                                   AS model_variant,
    resource_tags_experiment                                AS experiment,
    COUNT(*)                                                AS billing_records,
    SUM(line_item_usage_amount)                             AS total_tokens,
    SUM(line_item_unblended_cost)                           AS inference_cost_usd,
    SUM(line_item_unblended_cost)
        / NULLIF(SUM(line_item_usage_amount), 0) * 1000000 AS cost_per_million_tokens
FROM cur_database.bedrock_costs
WHERE year = '2026'
  AND month = '06'
  AND line_item_product_code = 'AmazonBedrock'
  AND line_item_operation IN ('InvokeModel', 'InvokeModelWithResponseStream')
  AND resource_tags_experiment IS NOT NULL
GROUP BY 1, 2
ORDER BY model_variant, experiment;

11.4 Query 3: CMI Capacity Cost (CMU-Minutes)

-- Track Custom Model Import capacity spend by imported model
SELECT
    line_item_resource_id                                   AS model_arn,
    resource_tags_model_version                             AS version,
    SUM(line_item_usage_amount)                             AS total_cmu_minutes,
    SUM(line_item_unblended_cost)                           AS cmu_cost_usd,
    SUM(line_item_unblended_cost) / 730.0                   AS avg_hourly_cmu_cost
FROM cur_database.bedrock_costs
WHERE year = '2026'
  AND month = '06'
  AND line_item_product_code = 'AmazonBedrock'
  AND line_item_usage_type LIKE '%CustomModelImport%'
GROUP BY 1, 2
ORDER BY cmu_cost_usd DESC;

11.5 Query 4: Amortized TCO — Training + Inference Over Model Lifetime

-- Full TCO: amortize training cost over N months, add ongoing inference + storage
WITH training_costs AS (
    SELECT
        resource_tags_model_version                         AS model_version,
        SUM(line_item_unblended_cost)                       AS training_cost_usd
    FROM cur_database.bedrock_costs
    WHERE line_item_operation LIKE '%ModelCustomization%'
      AND resource_tags_model_version IS NOT NULL
    GROUP BY 1
),
monthly_inference AS (
    SELECT
        resource_tags_model_version                         AS model_version,
        DATE_FORMAT(line_item_usage_start_date, '%Y-%m')   AS billing_month,
        SUM(line_item_unblended_cost)                       AS monthly_inference_usd
    FROM cur_database.bedrock_costs
    WHERE line_item_operation IN ('InvokeModel', 'InvokeModelWithResponseStream',
                                   'InvokeModelInference')
      AND resource_tags_model_version IS NOT NULL
    GROUP BY 1, 2
),
monthly_storage AS (
    SELECT
        resource_tags_model_version                         AS model_version,
        DATE_FORMAT(line_item_usage_start_date, '%Y-%m')   AS billing_month,
        SUM(line_item_unblended_cost)                       AS monthly_storage_usd
    FROM cur_database.bedrock_costs
    WHERE line_item_usage_type LIKE '%ModelStorage%'
      AND resource_tags_model_version IS NOT NULL
    GROUP BY 1, 2
),
months_active AS (
    SELECT model_version, COUNT(DISTINCT billing_month) AS months
    FROM monthly_inference GROUP BY 1
)
SELECT
    i.model_version,
    t.training_cost_usd,
    m.months                                                AS months_active,
    t.training_cost_usd / NULLIF(m.months, 0)              AS amortized_training_per_month,
    AVG(i.monthly_inference_usd)                            AS avg_monthly_inference,
    AVG(s.monthly_storage_usd)                              AS avg_monthly_storage,
    (t.training_cost_usd / NULLIF(m.months, 0))
        + AVG(i.monthly_inference_usd)
        + AVG(s.monthly_storage_usd)                        AS amortized_monthly_tco
FROM training_costs t
JOIN months_active m ON t.model_version = m.model_version
LEFT JOIN monthly_inference i ON t.model_version = i.model_version
LEFT JOIN monthly_storage s
  ON t.model_version = s.model_version
  AND i.billing_month = s.billing_month
GROUP BY 1, 2, 3, 4
ORDER BY amortized_monthly_tco DESC;

11.6 Query 5: Cache Token Reconciliation (Prevent Undercounting)

-- All four token types must be included for accurate Bedrock cost reconciliation
SELECT
    resource_tags_team                                      AS team,
    SUM(CASE WHEN line_item_usage_type LIKE '%-input-tokens'
             THEN line_item_unblended_cost ELSE 0 END)      AS input_cost,
    SUM(CASE WHEN line_item_usage_type LIKE '%-output-tokens'
             THEN line_item_unblended_cost ELSE 0 END)      AS output_cost,
    SUM(CASE WHEN line_item_usage_type LIKE '%-cache-read-%'
             THEN line_item_unblended_cost ELSE 0 END)      AS cache_read_cost,
    SUM(CASE WHEN line_item_usage_type LIKE '%-cache-write-%'
             THEN line_item_unblended_cost ELSE 0 END)      AS cache_write_cost,
    SUM(line_item_unblended_cost)                           AS total_cost,
    -- Reconciliation check: unexplained cost not matching any of the four types
    SUM(CASE WHEN line_item_usage_type NOT LIKE '%-input-tokens'
              AND line_item_usage_type NOT LIKE '%-output-tokens'
              AND line_item_usage_type NOT LIKE '%-cache-read-%'
              AND line_item_usage_type NOT LIKE '%-cache-write-%'
             THEN line_item_unblended_cost ELSE 0 END)      AS other_cost
FROM cur_database.bedrock_costs
WHERE year = '2026'
  AND month = '06'
  AND line_item_product_code = 'AmazonBedrock'
GROUP BY 1
ORDER BY total_cost DESC;

12. FinOps Governance Checklist for Fine-Tuned Model Programs

Before Initiating a Fine-Tuning Job

  • [ ] Confirm RAG with S3 Vectors has been benchmarked; document why fine-tuning is preferred
  • [ ] Estimate training token count: dataset_rows × avg_tokens_per_row × epoch_count
  • [ ] Verify break-even is reachable within 6 months based on projected call volume
  • [ ] Tag the customization job with model-version, team, cost-center, experiment-id before submission
  • [ ] Confirm data labeling budget is included in total project cost

During Training

  • [ ] Monitor training loss convergence; stop early if loss plateau is reached before planned epochs (saves tokens)
  • [ ] For RFT, set a maximum job duration to cap GPU-hour spend
  • [ ] Confirm S3 output bucket for model artifacts has lifecycle policy (avoids perpetual storage of intermediate checkpoints)

After Training

  • [ ] Run automatic Model Evaluation before any human evaluation to filter out low-quality runs cheaply
  • [ ] Create Application Inference Profile with cost allocation tags before first production inference call
  • [ ] Set CMI idle timeout if available, or implement application-level heartbeat to minimize unused 5-minute billing windows
  • [ ] Delete superseded model versions from Bedrock after confirming S3 export (keep $1.95/month only for versions in active use)

Ongoing

  • [ ] Run monthly TCO Athena query (§11.5) to confirm amortized training cost is <20% of total monthly model cost by month 3
  • [ ] Review cache token reconciliation (§11.6) quarterly to catch cost undercounting
  • [ ] Establish version retention policy: maximum 3 active Bedrock versions per model family

13. Key Numbers Reference Card

Item Rate Notes
Titan Text Express SFT $0.008/1K tokens Most common enterprise SFT target
Llama 2 70B SFT $0.00799/1K tokens Legacy; CMI + LoRA preferred
Cohere Command SFT $0.004/1K tokens Good RAG+instruction baseline
Nova Micro SFT (effective) ~$1.25/M tokens Includes job overhead
RFT (gpt-oss-20b, Qwen3 32B) $80.00/hour Hourly, not per-token
Model storage $1.95/model/month Flat fee; version proliferation adds up
CMI (us-east-1) $0.05718/CMU/minute 5-minute minimum billing window
CMI (eu-central-1) $0.07144/CMU/minute 25% regional premium
Provisioned Throughput (Llama 2 13B, 1-month) $21.18/hour Full-month commitment
Human model evaluation $0.21/task Plus inference cost
RAG Knowledge Base floor (S3 Vectors) ~$70/month vs $700+ for OpenSearch Serverless
Fine-tuned model break-even vs RAG ~750K calls/month Assumes 2K token system prompt eliminated

Sources