Module 5: AWS Services for AI (S3, Lambda, SageMaker Basics)

7. Cost Estimation for AI on AWS

Overview

In this capsule you'll learn to estimate AWS costs for an AI system before deploying. No vague estimates — concrete numbers with a calculator using real AWS prices. We cover S3 (storage + requests), Lambda (invocations + duration + memory), SageMaker (endpoint uptime), and the LLM APIs (OpenAI/Anthropic). By the end, you'll be able to answer precisely: "My AI service will cost $X/month at Y daily invocations."

Context: One of the most common mistakes in the cloud is deploying first and being surprised by the bill later. With AI, the problem is amplified: LLM invocations have a per-token cost, SageMaker endpoints charge by the hour even if they receive no traffic, and Lambda with long invocations (5-30s) accumulates compute cost quickly. This capsule gives you the tools to estimate BEFORE deploying.


AWS Pricing Model

The three services and their cost dimensions

S3 (Storage):
├── Storage:       $/GB/month
├── PUT requests:  $/1000 requests
├── GET requests:  $/1000 requests
├── Data transfer: $/GB (outbound from AWS)
└── Free tier:     5GB, 20K GETs, 2K PUTs

Lambda (Compute):
├── Invocations:   $/invocation
├── Duration:      $/GB-second
├── Free tier:     1M invocations, 400K GB-s
└── Key factors:   memory × duration × invocations

SageMaker Endpoints (ML Hosting):
├── Instance:      $/hour (always on)
├── Data processed: $/GB
├── Free tier:     250 hours of ml.t3.medium (first 2 months)
└── Key factor:    hours on × instance type

S3: Cost Calculator

S3 Standard pricing (us-east-1, March 2026)

Storage:
├── First 50 TB:        $0.023/GB/month
├── 50-500 TB:          $0.022/GB/month
└── 500+ TB:            $0.021/GB/month

Requests:
├── PUT, COPY, POST:    $0.005/1,000 requests
├── GET, SELECT:        $0.0004/1,000 requests
├── DELETE:             Free
└── LIST:               $0.005/1,000 requests

Data Transfer:
├── Inbound:            Free
├── Outbound (first 100GB/month): Free (free tier)
├── Outbound (10TB+):   $0.09/GB
└── Within region:      Free (S3 → Lambda same region)

Python calculator for S3

def estimate_s3_costs(
    storage_gb: float,
    monthly_puts: int,
    monthly_gets: int,
    outbound_gb: float = 0,
) -> dict:
    """Estimates monthly S3 costs for an AI system."""
    storage_cost = storage_gb * 0.023

    put_cost = (monthly_puts / 1000) * 0.005
    get_cost = (monthly_gets / 1000) * 0.0004

    outbound_cost = max(0, outbound_gb - 100) * 0.09

    total = storage_cost + put_cost + get_cost + outbound_cost

    return {
        "storage": {"gb": storage_gb, "cost": round(storage_cost, 4)},
        "puts": {"count": monthly_puts, "cost": round(put_cost, 4)},
        "gets": {"count": monthly_gets, "cost": round(get_cost, 4)},
        "outbound": {"gb": outbound_gb, "cost": round(outbound_cost, 4)},
        "total_monthly": round(total, 2),
    }


# Example: RAG system with 10GB of documents
rag_s3 = estimate_s3_costs(
    storage_gb=10,
    monthly_puts=5_000,
    monthly_gets=500_000,
    outbound_gb=5,
)

print("S3 Costs for RAG System:")
print(f"  Storage (10GB):      ${rag_s3['storage']['cost']}")
print(f"  PUTs (5K):           ${rag_s3['puts']['cost']}")
print(f"  GETs (500K):         ${rag_s3['gets']['cost']}")
print(f"  Outbound (5GB):      ${rag_s3['outbound']['cost']}")
print(f"  TOTAL:               ${rag_s3['total_monthly']}/month")

Typical AI scenarios for S3

Scenario A: RAG startup (10GB docs, 500K reads/month)
├── Storage: 10GB × $0.023 = $0.23
├── PUTs: 5K × $0.005/1K = $0.025
├── GETs: 500K × $0.0004/1K = $0.20
└── TOTAL S3: ~$0.46/month

Scenario B: AI Service with models (100GB models + embeddings)
├── Storage: 100GB × $0.023 = $2.30
├── PUTs: 1K × $0.005/1K = $0.005
├── GETs: 50K × $0.0004/1K = $0.02
└── TOTAL S3: ~$2.33/month

Scenario C: High-volume logging (1M responses/month, 1KB each)
├── Storage: ~1GB × $0.023 = $0.023
├── PUTs: 1M × $0.005/1K = $5.00
├── GETs: 100K × $0.0004/1K = $0.04
└── TOTAL S3: ~$5.06/month

Conclusion: S3 is extremely cheap for storage.
The real S3 cost is in the requests (PUT), not in the storage.

Lambda: Cost Calculator

Lambda pricing (us-east-1, March 2026)

Invocations:
├── Price: $0.20/1M invocations
├── Free tier: 1M invocations/month (always)
└── Each invocation: $0.0000002

Duration (GB-seconds):
├── Price: $0.0000166667/GB-second
├── Free tier: 400,000 GB-s/month (always)
├── arm64: 20% discount ($0.0000133334/GB-s)
└── Formula: (memoryMB / 1024) × durationSeconds × invocations

Provisioned Concurrency (optional):
├── $0.0000041667/GB-second (provisioned)
└── Charged 24/7 even if there are no invocations

Python calculator for Lambda

def estimate_lambda_costs(
    daily_invocations: int,
    avg_duration_ms: int,
    memory_mb: int,
    arm64: bool = True,
) -> dict:
    """Estimates monthly Lambda costs for an AI service."""
    monthly_invocations = daily_invocations * 30

    # Cost per invocation
    billable_invocations = max(0, monthly_invocations - 1_000_000)
    invocation_cost = billable_invocations * 0.0000002

    # Cost per duration
    memory_gb = memory_mb / 1024
    duration_s = avg_duration_ms / 1000
    total_gb_s = monthly_invocations * memory_gb * duration_s

    free_tier_gb_s = 400_000
    billable_gb_s = max(0, total_gb_s - free_tier_gb_s)

    price_per_gb_s = 0.0000133334 if arm64 else 0.0000166667
    duration_cost = billable_gb_s * price_per_gb_s

    total = invocation_cost + duration_cost

    return {
        "monthly_invocations": monthly_invocations,
        "invocation_cost": round(invocation_cost, 4),
        "total_gb_seconds": round(total_gb_s, 2),
        "billable_gb_seconds": round(billable_gb_s, 2),
        "duration_cost": round(duration_cost, 4),
        "total_monthly": round(total, 2),
        "architecture": "arm64" if arm64 else "x86_64",
        "cost_per_invocation": round(total / max(monthly_invocations, 1), 6),
    }


# Example: AI Lambda with 5K invocations/day
ai_lambda = estimate_lambda_costs(
    daily_invocations=5_000,
    avg_duration_ms=5000,
    memory_mb=512,
    arm64=True,
)

print("Lambda Costs for AI Service:")
print(f"  Invocations: {ai_lambda['monthly_invocations']:,}/month")
print(f"  Invocation cost:  ${ai_lambda['invocation_cost']}")
print(f"  GB-seconds:       {ai_lambda['total_gb_seconds']:,.0f} (billable: {ai_lambda['billable_gb_seconds']:,.0f})")
print(f"  Duration cost:    ${ai_lambda['duration_cost']}")
print(f"  TOTAL:            ${ai_lambda['total_monthly']}/month")
print(f"  Per invocation:   ${ai_lambda['cost_per_invocation']}")

Typical AI scenarios for Lambda

Scenario A: Development/Testing (50 inv/day, 512MB, 4s avg)
├── Invocations: 1,500/month → Free tier → $0.00
├── GB-seconds: 3,000 → Free tier → $0.00
└── TOTAL Lambda: $0.00/month

Scenario B: Light production (5K inv/day, 512MB, 5s avg, arm64)
├── Invocations: 150K/month → Free tier → $0.00
├── GB-seconds: 375,000 → Free tier → $0.00
└── TOTAL Lambda: $0.00/month (still within free tier!)

Scenario C: Medium production (50K inv/day, 768MB, 8s avg, arm64)
├── Invocations: 1.5M/month → Billable: 500K → $0.10
├── GB-seconds: 9,000,000 → Billable: 8,600,000 → $114.67
└── TOTAL Lambda: ~$114.77/month

Scenario D: High production (200K inv/day, 1024MB, 10s avg, arm64)
├── Invocations: 6M/month → Billable: 5M → $1.00
├── GB-seconds: 60,000,000 → Billable: 59,600,000 → $794.67
└── TOTAL Lambda: ~$795.67/month

Insight: Lambda is free or very cheap at low volume.
At high volume, the cost is dominated by duration × memory.

LLM APIs: The Dominant Cost

OpenAI pricing (March 2026)

GPT-4o-mini:
├── Input:  $0.15/1M tokens
├── Output: $0.60/1M tokens
└── Example: 100 tokens in + 300 tokens out = $0.000195/invocation

GPT-4o:
├── Input:  $2.50/1M tokens
├── Output: $10.00/1M tokens
└── Example: 100 tokens in + 300 tokens out = $0.003250/invocation

Calculator for LLM costs

def estimate_llm_costs(
    daily_invocations: int,
    avg_input_tokens: int,
    avg_output_tokens: int,
    model: str = "gpt-4o-mini",
) -> dict:
    """Estimates monthly LLM API costs."""
    pricing = {
        "gpt-4o-mini": {"input": 0.15, "output": 0.60},
        "gpt-4o": {"input": 2.50, "output": 10.00},
        "claude-3-haiku": {"input": 0.25, "output": 1.25},
        "claude-3.5-sonnet": {"input": 3.00, "output": 15.00},
    }

    if model not in pricing:
        raise ValueError(f"Model {model} not in pricing table")

    prices = pricing[model]
    monthly_invocations = daily_invocations * 30

    input_cost = (monthly_invocations * avg_input_tokens / 1_000_000) * prices["input"]
    output_cost = (monthly_invocations * avg_output_tokens / 1_000_000) * prices["output"]
    total = input_cost + output_cost

    return {
        "model": model,
        "monthly_invocations": monthly_invocations,
        "input_tokens_total": monthly_invocations * avg_input_tokens,
        "output_tokens_total": monthly_invocations * avg_output_tokens,
        "input_cost": round(input_cost, 2),
        "output_cost": round(output_cost, 2),
        "total_monthly": round(total, 2),
        "cost_per_invocation": round(total / monthly_invocations, 6),
    }


llm_cost = estimate_llm_costs(
    daily_invocations=5_000,
    avg_input_tokens=200,
    avg_output_tokens=400,
    model="gpt-4o-mini",
)

print(f"LLM API Costs ({llm_cost['model']}):")
print(f"  Input tokens:  {llm_cost['input_tokens_total']:,} → ${llm_cost['input_cost']}")
print(f"  Output tokens: {llm_cost['output_tokens_total']:,} → ${llm_cost['output_cost']}")
print(f"  TOTAL:         ${llm_cost['total_monthly']}/month")
print(f"  Per invocation: ${llm_cost['cost_per_invocation']}")

SageMaker: Cost Calculator

def estimate_sagemaker_costs(
    instance_type: str,
    instance_count: int = 1,
    hours_per_day: float = 24,
) -> dict:
    """Estimates monthly SageMaker endpoint costs."""
    instance_pricing = {
        "ml.t3.medium": 0.05,
        "ml.m5.large": 0.115,
        "ml.m5.xlarge": 0.23,
        "ml.c5.xlarge": 0.204,
        "ml.g4dn.xlarge": 0.736,
        "ml.g5.xlarge": 1.408,
        "ml.p3.2xlarge": 3.825,
    }

    if instance_type not in instance_pricing:
        raise ValueError(f"Instance {instance_type} not in pricing table")

    hourly_rate = instance_pricing[instance_type]
    monthly_hours = hours_per_day * 30
    monthly_cost = hourly_rate * monthly_hours * instance_count

    return {
        "instance_type": instance_type,
        "instance_count": instance_count,
        "hourly_rate": hourly_rate,
        "hours_per_day": hours_per_day,
        "monthly_hours": monthly_hours,
        "total_monthly": round(monthly_cost, 2),
    }


# Endpoint 24/7
sm_247 = estimate_sagemaker_costs("ml.m5.large", instance_count=1, hours_per_day=24)
print(f"SageMaker 24/7: ${sm_247['total_monthly']}/month")

# Endpoint only during business hours (10h/day)
sm_business = estimate_sagemaker_costs("ml.m5.large", instance_count=1, hours_per_day=10)
print(f"SageMaker business hours: ${sm_business['total_monthly']}/month")

Integrated Calculator: Total Cost of Ownership

TCO for a complete AI service

def estimate_total_cost(
    name: str,
    s3_storage_gb: float,
    s3_monthly_puts: int,
    s3_monthly_gets: int,
    lambda_daily_inv: int,
    lambda_duration_ms: int,
    lambda_memory_mb: int,
    llm_model: str,
    llm_avg_input_tokens: int,
    llm_avg_output_tokens: int,
    sagemaker_instance: str = None,
    sagemaker_hours_per_day: float = 0,
    api_gateway_monthly_requests: int = 0,
) -> dict:
    """Calculates the total monthly cost of an AI service on AWS."""
    s3_cost = estimate_s3_costs(s3_storage_gb, s3_monthly_puts, s3_monthly_gets)
    lambda_cost = estimate_lambda_costs(lambda_daily_inv, lambda_duration_ms, lambda_memory_mb)
    llm_cost = estimate_llm_costs(lambda_daily_inv, llm_avg_input_tokens, llm_avg_output_tokens, llm_model)

    sm_cost = {"total_monthly": 0}
    if sagemaker_instance and sagemaker_hours_per_day > 0:
        sm_cost = estimate_sagemaker_costs(sagemaker_instance, 1, sagemaker_hours_per_day)

    api_gw_cost = (api_gateway_monthly_requests / 1_000_000) * 1.00 if api_gateway_monthly_requests else 0

    cloudwatch_cost = 0.50 + (lambda_daily_inv * 30 * 0.5 / 1_000_000) * 0.50

    total = (
        s3_cost["total_monthly"]
        + lambda_cost["total_monthly"]
        + llm_cost["total_monthly"]
        + sm_cost["total_monthly"]
        + api_gw_cost
        + cloudwatch_cost
    )

    breakdown = {
        "name": name,
        "s3": s3_cost["total_monthly"],
        "lambda": lambda_cost["total_monthly"],
        "llm_api": llm_cost["total_monthly"],
        "sagemaker": sm_cost["total_monthly"],
        "api_gateway": round(api_gw_cost, 2),
        "cloudwatch": round(cloudwatch_cost, 2),
        "total_monthly": round(total, 2),
        "total_annual": round(total * 12, 2),
    }

    return breakdown


def print_cost_report(cost: dict):
    """Prints a formatted cost report."""
    print(f"\n{'='*55}")
    print(f"  Cost Estimation: {cost['name']}")
    print(f"{'='*55}")
    print(f"  S3 Storage + Requests:    ${cost['s3']:>10.2f}/month")
    print(f"  Lambda Compute:           ${cost['lambda']:>10.2f}/month")
    print(f"  LLM API (tokens):         ${cost['llm_api']:>10.2f}/month")
    print(f"  SageMaker Endpoints:      ${cost['sagemaker']:>10.2f}/month")
    print(f"  API Gateway:              ${cost['api_gateway']:>10.2f}/month")
    print(f"  CloudWatch Logs:          ${cost['cloudwatch']:>10.2f}/month")
    print(f"{'─'*55}")
    print(f"  TOTAL MONTHLY:            ${cost['total_monthly']:>10.2f}/month")
    print(f"  TOTAL ANNUAL:             ${cost['total_annual']:>10.2f}/year")
    print(f"{'='*55}")

    components = {k: v for k, v in cost.items()
                  if k not in ("name", "total_monthly", "total_annual") and v > 0}
    if components:
        print(f"\n  Distribution:")
        total = cost["total_monthly"]
        for component, value in sorted(components.items(), key=lambda x: x[1], reverse=True):
            pct = (value / total * 100) if total > 0 else 0
            print(f"    {component:<25} {pct:>5.1f}%")

Reference scenarios

# Scenario 1: Startup — AI chatbot MVP
mvp = estimate_total_cost(
    name="Startup MVP — Chatbot AI",
    s3_storage_gb=2,
    s3_monthly_puts=1_000,
    s3_monthly_gets=50_000,
    lambda_daily_inv=500,
    lambda_duration_ms=5000,
    lambda_memory_mb=512,
    llm_model="gpt-4o-mini",
    llm_avg_input_tokens=150,
    llm_avg_output_tokens=300,
    api_gateway_monthly_requests=15_000,
)
print_cost_report(mvp)

# Scenario 2: Production — RAG Service
production = estimate_total_cost(
    name="Production — RAG Service",
    s3_storage_gb=50,
    s3_monthly_puts=50_000,
    s3_monthly_gets=2_000_000,
    lambda_daily_inv=10_000,
    lambda_duration_ms=8000,
    lambda_memory_mb=768,
    llm_model="gpt-4o-mini",
    llm_avg_input_tokens=500,
    llm_avg_output_tokens=600,
    api_gateway_monthly_requests=300_000,
)
print_cost_report(production)

# Scenario 3: Enterprise — With SageMaker
enterprise = estimate_total_cost(
    name="Enterprise — Custom Model + LLM API",
    s3_storage_gb=200,
    s3_monthly_puts=100_000,
    s3_monthly_gets=5_000_000,
    lambda_daily_inv=50_000,
    lambda_duration_ms=6000,
    lambda_memory_mb=768,
    llm_model="gpt-4o",
    llm_avg_input_tokens=300,
    llm_avg_output_tokens=500,
    sagemaker_instance="ml.g4dn.xlarge",
    sagemaker_hours_per_day=24,
    api_gateway_monthly_requests=1_500_000,
)
print_cost_report(enterprise)

Expected output:

=======================================================
  Cost Estimation: Startup MVP — Chatbot AI
=======================================================
  S3 Storage + Requests:    $      0.07/month
  Lambda Compute:           $      0.00/month
  LLM API (tokens):         $      3.04/month
  SageMaker Endpoints:      $      0.00/month
  API Gateway:              $      0.01/month
  CloudWatch Logs:          $      0.50/month
───────────────────────────────────────────────────────
  TOTAL MONTHLY:            $      3.63/month
  TOTAL ANNUAL:             $     43.55/year
=======================================================

=======================================================
  Cost Estimation: Production — RAG Service
=======================================================
  S3 Storage + Requests:    $      2.20/month
  Lambda Compute:           $     18.67/month
  LLM API (tokens):         $    130.50/month
  SageMaker Endpoints:      $      0.00/month
  API Gateway:              $      0.30/month
  CloudWatch Logs:          $      0.57/month
───────────────────────────────────────────────────────
  TOTAL MONTHLY:            $    152.25/month
  TOTAL ANNUAL:             $   1826.94/year
=======================================================

Cost Optimization

Reduction strategies

1. Cheaper model
   ├── GPT-4o → GPT-4o-mini: ~17x cheaper per token
   ├── Claude 3.5 Sonnet → Claude 3 Haiku: ~12x cheaper
   └── Evaluate whether the expensive model is really necessary

2. Reduce tokens
   ├── Shorter prompts (no redundant instructions)
   ├── Tighter max_tokens (don't ask for 2000 if you need 200)
   └── Cache responses for repeated queries

3. Lambda arm64
   ├── 20% cheaper than x86_64
   ├── Equivalent performance for AI workloads (I/O bound)
   └── A single flag in template.yaml

4. Right-size Lambda memory
   ├── 512MB vs 1024MB = ~50% less compute cost
   ├── Measure first, adjust later (Lambda Power Tuning)
   └── For AI (I/O bound), more memory doesn't always = faster

5. S3 Lifecycle rules
   ├── Old responses → Standard-IA (46% less storage)
   ├── Very old responses → Glacier (83% less storage)
   └── Delete temp files automatically

6. SageMaker: Turn off when not in use
   ├── Development endpoints: shut down at night
   ├── Auto-scaling: scale to 0 outside hours
   └── Serverless Inference for sporadic traffic

Savings calculator

def calculate_optimization_savings(current_cost: dict) -> dict:
    """Calculates potential savings from optimizations."""
    savings = {}

    if current_cost.get("llm_api", 0) > 0:
        savings["switch_to_mini"] = {
            "description": "Switch GPT-4o → GPT-4o-mini",
            "current": current_cost["llm_api"],
            "optimized": round(current_cost["llm_api"] * 0.06, 2),
            "savings": round(current_cost["llm_api"] * 0.94, 2),
        }

    if current_cost.get("lambda", 0) > 0:
        savings["arm64"] = {
            "description": "Switch to arm64 architecture",
            "current": current_cost["lambda"],
            "optimized": round(current_cost["lambda"] * 0.80, 2),
            "savings": round(current_cost["lambda"] * 0.20, 2),
        }

    if current_cost.get("sagemaker", 0) > 0:
        savings["business_hours"] = {
            "description": "SageMaker only business hours (10h/day)",
            "current": current_cost["sagemaker"],
            "optimized": round(current_cost["sagemaker"] * (10 / 24), 2),
            "savings": round(current_cost["sagemaker"] * (14 / 24), 2),
        }

    total_savings = sum(s["savings"] for s in savings.values())

    print(f"\nOptimization Opportunities:")
    for name, info in savings.items():
        print(f"  {info['description']}")
        print(f"    Current: ${info['current']:.2f} → Optimized: ${info['optimized']:.2f}")
        print(f"    Savings: ${info['savings']:.2f}/month")
    print(f"\n  Total potential savings: ${total_savings:.2f}/month")

    return savings

Troubleshooting

Problem 1: Higher-than-expected Lambda bill

Check the average duration and memory. The cost is memory × duration × invocations.

# Check the real duration in CloudWatch
# In CloudWatch Insights:
# fields @timestamp, @duration
# | filter @type = "REPORT"
# | stats avg(@duration), max(@duration), p99(@duration)

# If the average duration is 15s instead of the estimated 5s,
# the cost triples.

Problem 2: Forgotten SageMaker endpoint

An endpoint you stopped using keeps charging.

import boto3

sm = boto3.client("sagemaker")
endpoints = sm.list_endpoints(StatusEquals="InService")
for ep in endpoints["Endpoints"]:
    print(f"⚠️  Active: {ep['EndpointName']} since {ep['CreationTime']}")

Problem 3: More expensive S3 requests than expected

If your Lambda calls list_objects frequently (on every invocation), the LIST requests add up.

# list_objects_v2 costs $0.005/1000 requests
# If Lambda lists objects 10K times/day = 300K/month
# Cost: 300 × $0.005 = $1.50/month just in LIST

# Solution: Cache the object list in the Lambda's memory (warm start)

Problem 4: Unexpected data transfer costs

S3 → Lambda in the same region is free. But S3 → Internet (presigned URLs downloaded by users) charges.

Within the same region: FREE
├── S3 → Lambda (us-east-1 → us-east-1): $0
├── Lambda → S3 (same region): $0
└── S3 → EC2 (same region): $0

Cross-region or to the Internet: CHARGES
├── S3 → Internet: $0.09/GB (after 100GB free)
├── S3 us-east-1 → Lambda eu-west-1: $0.02/GB
└── Downloaded presigned URLs: $0.09/GB

Practical Exercises

Exercise 1: Estimate the cost for your project

Using the integrated calculator, estimate the monthly cost of a RAG system that: stores 20GB of documents, receives 2K requests/day, uses gpt-4o-mini with an average of 300 input + 500 output tokens, and has a Lambda with 512MB and 6s avg.

See solution
my_rag = estimate_total_cost(
    name="My RAG System",
    s3_storage_gb=20,
    s3_monthly_puts=10_000,
    s3_monthly_gets=200_000,
    lambda_daily_inv=2_000,
    lambda_duration_ms=6000,
    lambda_memory_mb=512,
    llm_model="gpt-4o-mini",
    llm_avg_input_tokens=300,
    llm_avg_output_tokens=500,
    api_gateway_monthly_requests=60_000,
)
print_cost_report(my_rag)

# Expected:
# S3:       ~$0.59 (20GB storage + requests)
# Lambda:   ~$0.00 (within free tier at 2K/day)
# LLM API:  ~$20.70 (dominant cost)
# Total:    ~$21.86/month

Exercise 2: Compare GPT-4o vs GPT-4o-mini

Calculate the annual cost difference between using GPT-4o and GPT-4o-mini for a service with 10K invocations/day.

See solution
gpt4o_cost = estimate_llm_costs(
    daily_invocations=10_000,
    avg_input_tokens=200,
    avg_output_tokens=400,
    model="gpt-4o",
)

gpt4o_mini_cost = estimate_llm_costs(
    daily_invocations=10_000,
    avg_input_tokens=200,
    avg_output_tokens=400,
    model="gpt-4o-mini",
)

print(f"GPT-4o:      ${gpt4o_cost['total_monthly']:.2f}/month  (${gpt4o_cost['total_monthly'] * 12:.2f}/year)")
print(f"GPT-4o-mini: ${gpt4o_mini_cost['total_monthly']:.2f}/month  (${gpt4o_mini_cost['total_monthly'] * 12:.2f}/year)")
print(f"Difference:  ${(gpt4o_cost['total_monthly'] - gpt4o_mini_cost['total_monthly']):.2f}/month")
print(f"Annual savings: ${(gpt4o_cost['total_monthly'] - gpt4o_mini_cost['total_monthly']) * 12:.2f}/year")
print(f"Factor:       {gpt4o_cost['total_monthly'] / max(gpt4o_mini_cost['total_monthly'], 0.01):.1f}x more expensive")

Exercise 3: Break-even SageMaker vs Lambda+API

Calculate at how many invocations/day SageMaker (ml.m5.large) becomes cheaper than Lambda + OpenAI API. Assume the SageMaker model produces results equivalent to GPT-4o-mini.

See solution
def find_breakeven():
    """Finds the break-even point between SageMaker and Lambda+API."""
    sm_monthly = estimate_sagemaker_costs("ml.m5.large")["total_monthly"]

    print(f"SageMaker ml.m5.large 24/7: ${sm_monthly:.2f}/month (fixed)")
    print()
    print(f"{'Inv/day':>10} | {'Lambda+API':>12} | {'SageMaker':>10} | {'Winner':>10}")
    print("-" * 55)

    breakeven = None
    for daily_inv in [100, 500, 1000, 5000, 10000, 25000, 50000, 100000]:
        lambda_c = estimate_lambda_costs(daily_inv, 5000, 512)["total_monthly"]
        llm_c = estimate_llm_costs(daily_inv, 200, 400, "gpt-4o-mini")["total_monthly"]
        total_lambda = lambda_c + llm_c

        winner = "SageMaker" if sm_monthly < total_lambda else "Lambda+API"
        print(f"{daily_inv:>10,} | ${total_lambda:>10.2f} | ${sm_monthly:>8.2f} | {winner:>10}")

        if breakeven is None and sm_monthly < total_lambda:
            breakeven = daily_inv

    if breakeven:
        print(f"\nBreak-even: ~{breakeven:,} invocations/day")
    else:
        print("\nLambda+API is cheaper in all evaluated scenarios")

find_breakeven()

Exercise 4: Budget alert calculator

Create a function that, given a maximum monthly budget, calculates how many daily invocations you can make with a specific model.

See solution
def max_invocations_for_budget(
    monthly_budget: float,
    model: str = "gpt-4o-mini",
    avg_input_tokens: int = 200,
    avg_output_tokens: int = 400,
    lambda_memory_mb: int = 512,
    lambda_duration_ms: int = 5000,
) -> dict:
    """Calculates the max invocations/day within a budget."""
    pricing = {
        "gpt-4o-mini": {"input": 0.15, "output": 0.60},
        "gpt-4o": {"input": 2.50, "output": 10.00},
    }

    if model not in pricing:
        raise ValueError(f"Model {model} not supported")

    prices = pricing[model]
    fixed_costs = 1.00

    available = monthly_budget - fixed_costs

    llm_cost_per_inv = (
        (avg_input_tokens / 1_000_000) * prices["input"]
        + (avg_output_tokens / 1_000_000) * prices["output"]
    )

    memory_gb = lambda_memory_mb / 1024
    duration_s = lambda_duration_ms / 1000
    lambda_cost_per_inv = memory_gb * duration_s * 0.0000133334

    total_cost_per_inv = llm_cost_per_inv + lambda_cost_per_inv
    max_monthly_inv = int(available / total_cost_per_inv)
    max_daily_inv = max_monthly_inv // 30

    print(f"Budget: ${monthly_budget}/month")
    print(f"Model: {model}")
    print(f"Cost per invocation: ${total_cost_per_inv:.6f}")
    print(f"  LLM: ${llm_cost_per_inv:.6f}")
    print(f"  Lambda: ${lambda_cost_per_inv:.6f}")
    print(f"Max invocations: {max_monthly_inv:,}/month ({max_daily_inv:,}/day)")

    return {
        "budget": monthly_budget,
        "model": model,
        "cost_per_invocation": total_cost_per_inv,
        "max_monthly": max_monthly_inv,
        "max_daily": max_daily_inv,
    }


# How many invocations fit in $50/month?
max_invocations_for_budget(50, model="gpt-4o-mini")
print()
max_invocations_for_budget(50, model="gpt-4o")

Summary

  • The cost of an AI service on AWS is dominated by the LLM APIs (OpenAI/Anthropic tokens), not by the AWS infrastructure. Lambda and S3 are cheap; GPT-4o is expensive.
  • S3 is extremely cheap: $0.023/GB/month. The real cost is in PUT requests ($0.005/1K), not in storage.
  • Lambda is free or almost free at low volume (generous free tier). At high volume, optimize with arm64 and memory right-sizing.
  • SageMaker is expensive if you leave it on. An ml.m5.large endpoint costs ~$84/month 24/7. Turn off endpoints you don't use.
  • Estimate BEFORE deploying. Use the integrated calculator with your real parameters (invocations, tokens, duration, memory).
  • Optimize the LLM model first (GPT-4o → GPT-4o-mini can save 17x), then Lambda (arm64, memory), then S3 (lifecycle).

Additional Resources

  1. AWS Pricing Calculator — Official AWS calculator
  2. S3 Pricing — S3 price details
  3. Lambda Pricing — Lambda price details
  4. SageMaker Pricing — Prices by instance type
  5. OpenAI Pricing — OpenAI model prices
  6. Anthropic Pricing — Anthropic model prices
  7. Lambda Power Tuning — Optimize memory/cost
  8. AWS Cost Explorer — Real-time cost monitoring