Serverless Cost Estimation Template
Template for estimating serverless costs per workload: invocation pricing, GB-second math, data transfer, and the hidden line items that blow up estimates.
Overview
Nobody gets a surprise AWS bill because Lambda was expensive. They get one because they never ran the numbers in the first place. This template gives you a repeatable way to price a serverless workload before you deploy it, and to check the estimate against the real invoice every month after that. Run it alongside the serverless deployment checklist so cost lands in the same review as the launch criteria.
Serverless billing has four moving parts: invocations, execution duration, memory allocation, and data transfer. Each provider weighs them differently, and each one hides a second tier of charges (logs, tracing, queue requests, NAT) that doesn’t show up in the headline pricing. An estimate that only covers invocations and GB-seconds will undershoot by 20-40% on a real workload.
1. Pricing Model Reference
Prices below are us-east-1 / equivalent regions as of mid-2026. Verify against the official pages before presenting an estimate to finance; providers adjust these numbers without warning.
1.1 AWS Lambda Pricing
| Component | Free tier | Price after free tier |
|---|---|---|
| Requests | 1M/month free | $0.20 per 1M requests |
| Compute (GB-second) | 400K/month free | $0.0000166667 per GB-second (x86) / $0.0000133334 (arm64) |
| PC capacity (GB-second) | None | $0.0000041667 per GB-second (x86) |
| PC duration (GB-second) | None | $0.0000097222 per GB-second (x86) |
| Data transfer (in) | Always free | $0.00 per GB |
| Data transfer (out) | 100GB/month free | $0.09 per GB |
Provisioned concurrency has no free tier: once enabled, the function’s requests and duration bill at full rates, and the reserved capacity bills around the clock whether or not it serves traffic.
1.2 Azure Functions Pricing
| Component | Free tier | Price after free tier |
|---|---|---|
| Executions | 1M/month free | $0.20 per 1M executions |
| GB-seconds | 400K/month free | $0.000016 per GB-second |
| Premium plan (vCPU) | None | $0.192/hour per vCPU |
| Premium plan (memory) | None | $0.0139/hour per GB |
1.3 GCP Cloud Functions Pricing (gen2)
Gen2 functions bill on Cloud Run’s model: vCPU-seconds and GiB-seconds instead of the old GHz-second pricing used by gen1.
| Component | Free tier | Price after free tier |
|---|---|---|
| Invocations | 2M/month free | $0.40 per 1M invocations |
| vCPU-seconds | 180K/month free | $0.0000240 per vCPU-second |
| GiB-seconds | 360K/month free | $0.0000025 per GiB-second |
| Data transfer (out) | 1GB/month free | $0.12 per GB (premium tier) |
2. Cost Calculation Formula
2.1 Lambda Compute Cost
Monthly compute cost = (invocations × duration_seconds × memory_GB) × price_per_GB_second
Example:
Invocations: 10M/month
Duration: 200ms average (0.2 seconds)
Memory: 512MB (0.5 GB)
GB-seconds = 10,000,000 × 0.2 × 0.5 = 1,000,000 GB-seconds
Billable = 1,000,000 - 400,000 free tier = 600,000 GB-seconds
Cost = 600,000 × $0.0000166667 = $10.00/month
The free tier is account-wide, not per-function. When estimating several functions, deduct it once against the biggest workload (or skip it for a conservative number); subtracting 400K GB-seconds from every function understates the bill.
2.2 Lambda Request Cost
Monthly request cost = (invocations - free_tier) × price_per_million / 1,000,000
Example:
Invocations: 10M/month
Free tier: 1M
Billable = 10,000,000 - 1,000,000 = 9,000,000
Cost = 9 × $0.20 = $1.80/month
2.3 Total Lambda Cost
def estimate_lambda_cost(
invocations: int,
avg_duration_ms: float,
memory_mb: int,
provisioned_concurrency_gb_seconds: int = 0,
data_transfer_out_gb: float = 0,
) -> dict:
"""Estimate monthly AWS Lambda cost."""
duration_s = avg_duration_ms / 1000
memory_gb = memory_mb / 1024
gb_seconds = invocations * duration_s * memory_gb
# With provisioned concurrency enabled the free tier doesn't apply,
# and execution duration bills at the lower PC rate.
has_pc = provisioned_concurrency_gb_seconds > 0
duration_rate = 0.0000097222 if has_pc else 0.0000166667
free_gb_seconds = 0 if has_pc else 400_000
free_requests = 0 if has_pc else 1_000_000
compute_cost = max(gb_seconds - free_gb_seconds, 0) * duration_rate
request_cost = (max(invocations - free_requests, 0) / 1_000_000) * 0.20
# Provisioned concurrency capacity: billed 24/7 for the configured amount
pc_cost = provisioned_concurrency_gb_seconds * 0.0000041667
# Data transfer cost
free_tier_data = 100
billable_data = max(data_transfer_out_gb - free_tier_data, 0)
data_cost = billable_data * 0.09
total = compute_cost + request_cost + pc_cost + data_cost
return {
"compute_cost": round(compute_cost, 2),
"request_cost": round(request_cost, 2),
"provisioned_concurrency_cost": round(pc_cost, 2),
"data_transfer_cost": round(data_cost, 2),
"total_monthly_cost": round(total, 2),
"gb_seconds": int(gb_seconds),
}
# Example usage
cost = estimate_lambda_cost(
invocations=10_000_000,
avg_duration_ms=200,
memory_mb=512,
)
print(f"Total monthly cost: ${cost['total_monthly_cost']}")
3. Workload Estimation Template
3.1 Per-Function Estimation
Function: processOrder
──────────────────────────────────────────────────
Metric | Value | Source
───────────────────────┼────────────────┼──────────────────
Expected invocations | 10M/month | Traffic forecast
Average duration | 200ms | Load testing
Memory allocation | 512MB | Power Tuning
p99 duration | 500ms | Load testing
Data transfer out | 5GB/month | Payload size × invocations
Provisioned concurrency| 10 concurrent | Latency requirement
Estimated monthly cost (PC enabled: no free tier, PC duration rate):
Compute: $9.72 (1,000,000 GB-s × $0.0000097222)
Requests: $2.00 (10M × $0.20/1M, no free tier with PC)
PC: $54.00 (10 × 0.5GB × 30 days × 24h × 3600s × $0.0000041667)
Data: $0.00 (under 100GB free tier)
Total: $65.72/month
Same function without provisioned concurrency: $10.00 compute + $1.80 requests = $11.80/month. The latency guarantee costs $54/month in reserved capacity alone, and that number belongs in the estimate so the trade-off is explicit.
3.2 Multi-Function Estimation
workloads = [
{"name": "processOrder", "invocations": 10_000_000, "duration_ms": 200, "memory_mb": 512},
{"name": "sendEmail", "invocations": 5_000_000, "duration_ms": 100, "memory_mb": 256},
{"name": "generateReport", "invocations": 100_000, "duration_ms": 5000, "memory_mb": 2048},
{"name": "webhookHandler", "invocations": 50_000_000, "duration_ms": 50, "memory_mb": 128},
]
total_cost = 0
for w in workloads:
cost = estimate_lambda_cost(w["invocations"], w["duration_ms"], w["memory_mb"])
print(f"{w['name']}: ${cost['total_monthly_cost']}/month")
total_cost += cost["total_monthly_cost"]
print(f"\nTotal monthly cost: ${total_cost:.2f}")
3.3 Event-Driven Workload Example
Not every workload is invocation-dominated. An event-driven pipeline triggered by S3 events shows a different cost shape, where the orchestration layer outweighs compute:
| Metric | Value | Source |
|---|---|---|
| S3 events | 500K/month | Traffic forecast |
| Lambda invocations | 500K/month (one per event) | Trigger mapping |
| Avg duration | 3s | Load testing |
| Memory | 1024MB | Power Tuning |
| Step Functions transitions | 6 per document | Workflow definition |
| SQS messages | 500K/month, batched by 10 | Buffer before processing |
Lambda compute: 500K × 3s × 1GB = 1.5M GB-s − 400K free tier = 1.1M × $0.0000166667 = $18.33
Lambda requests: 500K (under the 1M free tier) = $0.00
Step Functions: 500K docs × 6 transitions = 3M transitions × $0.025/1K = $75.00
SQS requests: 50K batches × ~3 API calls = 150K requests × $0.40/1M = $0.06
Total: ≈ $93.40/month
Step Functions costs 4x the Lambda compute here. An estimate that only priced the function would report $18/month and miss 80% of the bill. Fill in the section 4 hidden-cost table before trusting the function math.
4. Hidden Costs
The line items below routinely account for a third of a serverless bill. Estimate them explicitly. A “cheap” function with verbose logging can cost more in CloudWatch ingestion than in compute.
4.1 API Gateway Costs
| Component | Free tier | Price |
|---|---|---|
| Requests (HTTP API) | 300M/month | $1.00 per 1M |
| Requests (REST API) | 1M/month (12mo) | $3.50 per 1M |
| Data transfer out | 100GB/month | $0.09 per GB |
| WebSocket connections | 1M/month (12mo) | $0.80 per 1M |
4.2 Step Functions Costs
| Type | Free tier | Price |
|---|---|---|
| Standard workflow | 4K/month (12mo) | $0.025 per 1,000 transitions |
| Express workflow | 4K/month (12mo) | $1.00 per 1M invocations + $0.03 per 1K GB-seconds |
4.3 Common Hidden Costs
| Hidden cost | Impact | Mitigation |
|---|---|---|
| CloudWatch Logs ingestion | $0.50 per GB | Set log retention, use sampling |
| CloudWatch Logs storage | $0.03 per GB | Set TTL on log groups |
| X-Ray tracing | $0.50 per 1M | Sample traces (not 100%) |
| SQS requests | $0.40 per 1M | Batch messages |
| S3 PUT/GET requests | $0.005 per 1K | Batch S3 operations |
| Secrets Manager | $0.40 per secret | Use SSM Parameter Store (free) |
| DynamoDB read/write units | Per-request | Use on-demand capacity |
| NAT Gateway | $0.045 per GB | Use VPC endpoints where possible |
5. Cost Optimization Strategies
5.1 Memory Tuning
| Memory | CPU share | Cost per 1M invocations (200ms) |
|---|---|---|
| 128MB | 1/10 vCPU | $0.21 |
| 256MB | 1/5 vCPU | $0.43 |
| 512MB | 2/5 vCPU | $0.85 |
| 1024MB | 1 vCPU | $1.71 |
| 2048MB | 2 vCPU | $3.41 |
Optimal is the memory where cost × duration is minimized: more memory means faster execution and fewer GB-seconds per invocation.
The cheapest configuration on paper is rarely cheapest in production. A 128MB function that takes 2 seconds often costs more than a 1GB function that finishes in 300ms. Run AWS Lambda Power Tuning against real payloads before locking the estimate.
5.2 Optimization Checklist
- Profile memory with AWS Lambda Power Tuning on real payloads, not synthetic ones
- Reserve provisioned concurrency for the few functions with hard latency SLAs
- Batch SQS messages to cut invocation count
- Filter events in EventBridge so handlers don’t fire on noise
- Cap log retention at 7-30 days and drop DEBUG logging in production
- Move non-secret config to SSM Parameter Store instead of Secrets Manager
- Add VPC endpoints where NAT Gateway egress is the driver
- Strip dev dependencies and test fixtures from the deployment package
- Share common dependencies through Lambda Layers
- Reconcile the estimate against Cost Explorer monthly
Adopting This Template
- Estimate before the first deploy, not after the first bill. Run the numbers in the design review so cost becomes an input to architecture decisions (memory size, sync vs async, polling vs events) rather than a surprise.
- Feed it real data. Traffic forecasts and load-test durations beat guesses. If you’ve got neither, model three scenarios (expected, 3x, 10x) and budget for the middle one.
- Reconcile monthly. Pull the actual per-function cost from Cost Explorer, compare it to the estimate, and update the inputs when drift exceeds ~15%. The template only stays honest if someone owns this loop. The cloud cost optimization guide covers the tagging and chargeback setup that makes per-function actuals possible.
- Version the estimate with the code. Commit the filled-in template next to the infrastructure definition so cost assumptions are visible in review, and stale numbers get caught in diffs.
Companion files: the serverless-cost-estimation-template companion repo has this worksheet as a standalone Markdown file plus an estimate-costs.py calculator that prices one function from CLI flags or a whole workload list from JSON, with x86 and arm64 rates.
Validating the Estimate
An estimate nobody checks turns into fiction within a quarter. Keep the loop small enough that someone actually runs it:
- Pull actuals per function. In Cost Explorer, filter by service and group by resource. This only works if functions carry cost-allocation tags, so enable them before launch or the per-function numbers are estimates of their own.
- Compute drift.
drift = (actual − estimate) / estimate. Inside ±15% the model is fine; beyond it, find which input moved. - Localize the gap. If compute drifted, invocations or duration moved, so compare p50/p99 in CloudWatch against the load-test numbers. If the gap sits outside Lambda, the section 4 hidden-cost table is the place to look.
- Update inputs, not the rate card. Provider prices rarely move mid-quarter; your traffic shape does. Fix the forecast first, then the unit prices.
- Log every round. The worksheet’s validation log keeps each monthly comparison, so the next estimate starts from measured inputs rather than the original guess.
Worked example: the template estimated $65.72/month for processOrder; the bill shows $84.10 (+28% drift). CloudWatch shows p99 duration doubled after a downstream API slowed down. Update the duration input, re-run the calculator, and the new estimate lands within 5% of the next bill. The model was fine; the input went stale.
Troubleshooting
- Actual bill runs 30%+ over estimate: check the hidden-cost table first. CloudWatch Logs ingestion and NAT Gateway egress are the usual suspects, followed by retry storms multiplying invocations.
- Estimate drifts every month: your inputs went stale. Traffic grows, durations creep up as payloads get bigger, and free tiers get consumed by new services. Re-run load tests quarterly and refresh the numbers.
- A function’s real cost doesn’t match its calculated cost: duration is probably skewed. Look at p50 vs p99: a function that averages 200ms but spikes to 5s on cold starts or downstream timeouts bills far more GB-seconds than the average suggests.
- Provisioned concurrency costs more than expected: it’s billed around the clock, not per invocation. Ten units of PC on a 512MB function is ~$54/month in reserved capacity even if the function never runs, and the free tier stops applying to that function entirely. Audit PC allocations monthly.
- Cost spike with no traffic change: check for retry loops, a cron expression that fires more often than intended, or an event source mapping that re-triggers on partial batch failures.
- Estimate was right but the bill is still surprising: you priced the function, not the system. Add API Gateway, Step Functions transitions, DynamoDB/S3 request costs, and cross-AZ transfer to the model.
See Also
- Serverless Cold Start Runbook
- Complete Guide to AWS Lambda in Production
- Cloud Cost Optimization Guide
- Minimize Cold Start Latency in Serverless Functions
- Build Event-Driven Serverless Architectures
References
- AWS Lambda Pricing: official per-GB-second and per-request rates
- Azure Functions Pricing: consumption and premium plan rates
- Cloud Functions Pricing: gen1 GHz-second and gen2 vCPU/GiB-second models
- AWS Cost Anomaly Detection: alerting for unexpected spend
Frequently Asked Questions
How accurate are serverless cost estimates?
Within 10-20% when you feed them load-test data instead of guesses. The number one error source is invocation count. Production traffic routinely doubles or triples the forecast during launches and peak events. Model a worst-case scenario at 3x expected traffic, set billing alarms at 50%, 75%, and 100% of budget, and reconcile estimates against the real bill monthly.
When does serverless become more expensive than EC2?
For low or bursty traffic (under ~40% utilization), serverless wins easily. Past ~70% sustained utilization, EC2 or Fargate gets cheaper because you pay for capacity instead of per-invocation. Rough rule of thumb: a function running continuously every second costs 2-3x an equivalent EC2 instance. Run your actual numbers through the calculator. The break-even point moves with memory, duration, and volume.
How do I reduce CloudWatch Logs costs?
Cap retention at 7-30 days instead of "never expire," keep production logging at INFO, strip verbose logging from hot paths, and sample high-volume logs. For long-term retention, ship to S3 and archive to Glacier at $0.004/GB versus CloudWatch's $0.03/GB. One function writing 1KB of logs per invocation at 10M invocations/month pays $5/month in ingestion alone.
What is the cost impact of provisioned concurrency?
PC bills you for reserved capacity around the clock, whether or not it's used: ten concurrent executions at 512MB come to 10 × 0.5GB × 30 days × 24h × 3600s × $0.0000041667 ≈ $54/month. On top of that, executions on provisioned environments bill duration at $0.0000097222/GB-s and the free tier stops applying to the function entirely. Keep PC for functions with strict latency SLAs where cold starts aren't acceptable, and never enable it in dev or staging.
How do I set up billing alerts for serverless workloads?
Create an AWS Budget with alerts at 50%, 75%, and 100% of monthly spend, tag functions with cost-allocation tags, and filter them in Cost Explorer. Turn on AWS Cost Anomaly Detection for unexpected spikes. For finer granularity, emit an estimated-cost custom metric per invocation and alarm on it in CloudWatch.
How do I estimate costs for Step Functions workflows?
Standard workflows bill $0.025 per 1,000 state transitions; Express bills $1.00 per 1M invocations plus $0.03 per 1K GB-seconds. A 5-step workflow running 100K times/month costs $12.50 on Standard versus about $0.10 on Express plus compute. Pick Standard for long-running orchestrations (over ~5 minutes) and Express for short, high-volume flows.
How do I estimate a function that doesn't exist yet?
Use the closest analog: same runtime, similar payload size, similar downstream calls. Write a minimal prototype that stubs the dependencies, run a 1K-invocation load test to get p50/p99 duration, and feed those numbers into the calculator. Mark the estimate as provisional in the worksheet and re-measure after the first week in production; prototype numbers typically run 10-20% optimistic because real dependencies add latency.
Is data transfer between AWS services always charged?
No. Same-region traffic between Lambda and S3, DynamoDB, or SQS is free inbound and mostly free outbound. You pay for cross-region traffic, cross-AZ traffic in some configurations, and everything leaving to the internet at the EC2 data-out rate. The mistake to avoid is assuming "AWS to AWS" means free; NAT gateway processing fees and cross-region replication are where that assumption breaks.
Related Resources
Serverless Function Deployment Checklist
Pre-deploy and post-deploy checklist for serverless functions (AWS Lambda, Azure Functions, GCP Cloud Functions): IAM roles, environment variables, memory sizing, timeout config, logging, alarms, and rollback procedures.
DocServerless Cold Start Runbook
Runbook for diagnosing and mitigating serverless cold starts: causes, measurement, optimization strategies (provisioned concurrency, warmers, initialization tuning), and monitoring with code examples for AWS Lambda, Azure, and GCP.
DocServerless Security Checklist
Security hardening checklist for serverless functions: IAM least privilege, secret management, input validation, dependency scanning, network isolation, logging, and compliance with code examples for AWS Lambda, Azure, and GCP.
GuideComplete Guide to AWS Lambda in Production
Run AWS Lambda in production with confidence. Covers cold start optimization, layers, deployment patterns, observability with X-Ray, security hardening, connection pooling, and cost tuning for production workloads.
GuideCloud Cost Optimization Guide
A practical guide to cloud cost optimization: right-sizing, reserved instances, spot instances, tagging strategies, and FinOps practices that reduce spend while maintaining performance.