Skip to main content
Multi-Cloud · lesson 7 of 8
Multi-Cloud advanced Lesson 7 of 8

Serverless Cost Comparison: Lambda vs Azure Functions vs Cloud Run

1M invocations/month, 200ms duration, 256MB memory — the actual monthly bill computed on Lambda, Azure Functions, and Cloud Run, with the math shown.

By SkillByExample · Published

cloud aws azure gcp serverless cost

A features comparison can’t be checked. A cost comparison can — run the numbers for a concrete workload and the arithmetic either holds up or it doesn’t.

The workload

1,000,000 invocations/month, 200ms average execution time, 256 MB memory allocated, HTTP request-triggered, one request roughly one instance-second (low concurrency — traffic doesn’t cluster enough for one instance to serve many requests at once).

AWS Lambda

Published list pricing (x86, per-request and per-GB-second), with the always-on free tier applied:

# lambda_cost.py
invocations = 1_000_000
duration_s = 0.2
memory_gb = 256 / 1024

gb_seconds = invocations * duration_s * memory_gb
print(f"GB-seconds: {gb_seconds:,.0f}")

# List price, no free tier
request_cost = invocations / 1_000_000 * 0.20
duration_cost = gb_seconds * 0.0000166667
print(f"List price:  ${request_cost + duration_cost:.2f}/month "
      f"(requests ${request_cost:.2f} + duration ${duration_cost:.2f})")

# Permanent free tier: 1M requests + 400,000 GB-seconds/month
billable_requests = max(0, invocations - 1_000_000)
billable_gb_s = max(0, gb_seconds - 400_000)
free_tier_cost = billable_requests / 1_000_000 * 0.20 + billable_gb_s * 0.0000166667
print(f"With free tier: ${free_tier_cost:.2f}/month")
$ python lambda_cost.py
GB-seconds: 50,000
List price:  $1.03/month (requests $0.20 + duration $0.83)
With free tier: $0.00/month

50,000 GB-seconds is well under the 400,000 GB-second free allowance, and 1,000,000 requests exactly matches the free request allowance — this specific workload costs $0/month on Lambda, not as a rounding artifact but because it genuinely fits inside a permanent (not trial) free tier.

Azure Functions (Consumption plan)

Same shape of pricing — per-execution plus per-GB-second — with a matching free grant.

# functions_cost.py
executions = 1_000_000
duration_s = 0.2
memory_gb = 256 / 1024

gb_seconds = executions * duration_s * memory_gb

execution_cost = executions / 1_000_000 * 0.20
duration_cost = gb_seconds * 0.000016
print(f"List price:  ${execution_cost + duration_cost:.2f}/month "
      f"(executions ${execution_cost:.2f} + duration ${duration_cost:.2f})")

billable_executions = max(0, executions - 1_000_000)
billable_gb_s = max(0, gb_seconds - 400_000)
free_tier_cost = billable_executions / 1_000_000 * 0.20 + billable_gb_s * 0.000016
print(f"With free tier: ${free_tier_cost:.2f}/month")
$ python functions_cost.py
List price:  $1.00/month (executions $0.20 + duration $0.80)
With free tier: $0.00/month

Same result, same reason: Azure’s Consumption plan free grant is structured almost identically to Lambda’s (1M executions, 400,000 GB-seconds), so this workload is free there too.

Cloud Run

Cloud Run’s pricing model is structurally different: CPU-seconds and memory-seconds are billed separately rather than combined into one GB-second figure, and the free tier is split the same way.

# cloudrun_cost.py
requests = 1_000_000
duration_s = 0.2
vcpu = 1
memory_gib = 256 / 1024

vcpu_seconds = requests * duration_s * vcpu
gib_seconds = requests * duration_s * memory_gib
print(f"vCPU-seconds: {vcpu_seconds:,.0f}  GiB-seconds: {gib_seconds:,.0f}")

cpu_cost = vcpu_seconds * 0.000024
mem_cost = gib_seconds * 0.0000025
req_cost = requests / 1_000_000 * 0.40
print(f"List price:  ${cpu_cost + mem_cost + req_cost:.2f}/month "
      f"(cpu ${cpu_cost:.2f} + memory ${mem_cost:.2f} + requests ${req_cost:.2f})")

# Free tier: 180,000 vCPU-s, 360,000 GiB-s, 2,000,000 requests
billable_cpu = max(0, vcpu_seconds - 180_000)
billable_mem = max(0, gib_seconds - 360_000)
billable_req = max(0, requests - 2_000_000)
free_tier_cost = billable_cpu * 0.000024 + billable_mem * 0.0000025 + billable_req / 1_000_000 * 0.40
print(f"With free tier: ${free_tier_cost:.2f}/month")
$ python cloudrun_cost.py
vCPU-seconds: 200,000  GiB-seconds: 50,000
List price:  $5.33/month (cpu $4.80 + memory $0.13 + requests $0.40)
With free tier: $0.48/month

Cloud Run comes out most expensive here even after its free tier: $0.48/month against $0.00 on the other two. The reason is the CPU free-tier allowance (180,000 vCPU-seconds) is smaller relative to this workload’s 200,000 vCPU-seconds than Lambda’s and Azure’s compute allowances are relative to their 50,000 GB-seconds — this workload clears the memory-seconds free tier comfortably (50,000 of 360,000) but slightly exceeds the CPU one.

The number that matters more than the ranking

$0.48/month is not a meaningful cost difference at this volume — the real lesson is in why Cloud Run’s number moves at all: it’s billing CPU-seconds at a materially higher per-second rate than the other two bill GB-seconds, on the assumption that concurrency will bring the effective cost down. This calculation assumed one request keeps one instance busy for its whole duration — no sharing. Cloud Run’s default concurrency is 80 requests per instance; if real traffic overlaps enough that one instance serves even 4-5 requests at once instead of 1, the same 200,000 vCPU-seconds of request-processing time gets served by a fraction of the wall-clock instance-seconds Cloud Run actually bills for, and the ranking in this lesson reverses. Compute your own workload’s expected concurrency before trusting this result at a different traffic shape.

Practice

1. Recompute all three at 10x the volume (10M invocations/month) and see which free tiers get exceeded.
Lambda:     GB-seconds 500,000 -> exceeds 400,000 free -> billable cost ~$3.47/month
Functions:  GB-seconds 500,000 -> exceeds 400,000 free -> billable cost ~$3.40/month
Cloud Run:  vCPU-s 2,000,000, GiB-s 500,000 -> both exceed free tiers -> ~$47.23/month

At 10x volume Cloud Run’s gap widens rather than narrows, because its rate-per-unit disadvantage doesn’t change with volume — only concurrency changes it.

2. Recompute Cloud Run's cost assuming average concurrency of 8 requests per instance instead of 1.
concurrency = 8
vcpu_seconds = requests * duration_s * vcpu / concurrency
gib_seconds = requests * duration_s * memory_gib / concurrency
vCPU-seconds: 25,000  GiB-seconds: 6,250
With free tier: $0.00/month

Both figures now clear their free-tier thresholds easily, and Cloud Run becomes free too — concurrency, not the platform, decided the outcome.

3. Increase memory to 512MB on all three (duration held constant) and recompute.

Doubling memory roughly doubles GB-seconds/GiB-seconds on all three, since it’s a direct multiplier. Lambda and Azure Functions both stay within their free tiers (100,000 GB-seconds, still under 400,000); Cloud Run’s memory-seconds figure doubles to 100,000 GiB-s, still under its 360,000 free allowance, so only the CPU-driven cost (unaffected by the memory change) continues to apply.

4. A workload runs 50ms average duration instead of 200ms, same 1M invocations and 256MB. Recompute all three.
GB-seconds / vCPU-seconds / GiB-seconds all drop to 1/4 of the original figures.
Lambda: $0.00 (well within free tier)
Functions: $0.00 (well within free tier)
Cloud Run: vCPU-s 50,000 — now under the 180,000 free allowance — $0.00

At a quarter of the duration, Cloud Run’s CPU usage drops below its free-tier threshold too and all three platforms land at $0 — confirming the earlier result was specifically about this workload’s duration, not a fixed platform ranking.

Next: a single Terraform root module structure that provisions the same conceptual resource across all three provider blocks.

Frequently Asked Questions

Is Cloud Run always more expensive than Lambda?
Not always — this comparison's result is specific to a low-concurrency workload where each instance handles roughly one request at a time. Cloud Run bills per-instance CPU-second, so if your traffic lets one instance serve many concurrent requests (Cloud Run's default concurrency is 80 requests per instance), the CPU cost is shared across all of them and the effective per-request cost drops sharply. Lambda has no equivalent lever — each concurrent invocation gets its own full billed duration regardless of what else is running.
Why did Lambda and Azure Functions come out to roughly $0 in this comparison?
Both providers have a permanent monthly free tier — not a 12-month trial — covering 1M requests/executions and 400,000 GB-seconds of compute. This workload's 1M invocations and 50,000 GB-seconds both land inside that free allowance, so the bill is genuinely $0 at this volume, not an approximation. Scale past roughly 8x this workload and the free tier stops covering it.
Does memory size matter more than duration for serverless cost?
They multiply together, so neither dominates on its own — GB-seconds (or vCPU-seconds) is memory times duration times invocation count. Doubling either duration or memory alone roughly doubles the compute portion of the bill; the two only trade off against each other if increasing memory (which also increases CPU proportionally on Lambda) reduces duration enough to offset the higher rate.
Should I pick a serverless platform based on this cost comparison?
Not by itself. This comparison holds only for this specific low-concurrency workload shape at this specific size; a CPU-light, high-concurrency, high-volume workload can flip the ranking entirely, especially for Cloud Run. Run the same arithmetic against your own invocation count, duration, memory, and expected concurrency before trusting any general ranking, including this one.