The Runtime Theory
Cloud & Infrastructure

Serverless Pricing Is a Latency Multiplier

How GB-seconds billing, per-invocation fees, and the cold-start tax make every millisecond of function duration a line item — with real Lambda pricing math.

The Runtime Theory Team4 min read#serverless#lambda#pricing#gb-seconds#costs
On this page

Serverless billing is the only pricing model in cloud computing where latency is literally the invoice. A Lambda function is billed by duration, so every millisecond your handler spends waiting — on a slow dependency, a cold start, a misconfigured timeout — is a millisecond you pay for. The platform converts your runtime performance directly into dollars, per invocation, at a rate you can compute in your head.

The billing primitive: GB-seconds

AWS Lambda's price is a product of three factors: requests, duration, and memory. The unit is the GB-second:

text
price per request          $0.20 per 1,000,000 invocations
price per GB-second        $0.0000166667 (1/60,000 of a dollar)
billing granularity        per-millisecond (was 100 ms before 2023)
billing multiplier         configured memory / 1024 MB

The formula for one invocation:

text
cost = (memory_GB × duration_seconds × $0.0000166667) + ($0.20 / 1,000,000)
 
example: 512 MB function, 200 ms average duration
  memory_GB        = 0.5
  duration_cost    = 0.5 × 0.2 s × $0.0000166667 ≈ $0.000001667
  request_cost     = $0.0000002
  per-invocation   ≈ $0.000001867
  10M invocations  ≈ $18.67

The multiplier structure is the whole design: memory sets your CPU share, so choosing 1024 MB over 512 MB typically halves your duration (more CPU) while doubling the rate — and doubling memory is only a win when the workload actually scales with CPU. The cheapest function is the one that uses just enough memory to finish the fastest, and you can find that point empirically:

bash
# sweep memory and measure the resulting duration, then compute cost per call
for mb in 256 512 1024 2048; do
  aws lambda update-function-configuration --function-name worker \
    --memory-size $mb >/dev/null
  d=$(curl -s -o /dev/null -w "%{time_total}" \
    -H "x-api-key: $KEY" https://api.example.com/prod/worker)
  echo "memory=${mb}MB duration=${d}s cost=$(python3 -c "
    m=$mb/1024; t=float('$d')
    print(f'{(m*t*0.0000166667 + 0.0000002)*1e6:.4f} usd/M')
  ")"
done

Duration is billed in 1 ms increments, so the pricing works like a stopwatch with a currency conversion — and it is precisely the variance in that stopwatch that determines your monthly bill.

The per-invocation overhead

Every invocation carries fixed platform overhead that is inside your billed duration but outside your code:

text
1. request transport       — the frontend accepts the event, ~1–5 ms
2. runtime dispatch        — your handler is located and invoked
3. response transport      — the result is serialized and returned
4. logging/observability   — CloudWatch log shipping, tracing

None of that is in your code, and all of it is on your bill. The practical consequence: a function whose handlers do 10 ms of work will not bill 10 ms — it will bill whatever the platform's full invoke path measures. The gap is where "serverless is cheap for idle workloads" breaks down: for latency-critical workloads the overhead is a floor, and for chatty workloads (fans of many small invocations — a webhook fanout that calls 20 downstream functions) the request fees and per-invocation duration add up across every hop.

The cold-start tax

Here is the multiplier that most people miss: the cold start is billed at full rate. The 2 seconds your JVM function spends booting a microVM, initializing the SDK, and loading classes is billed at the same per-GB-second rate as the 50 ms of actual work. For a function that cold-starts once per day per user, the math:

text
512 MB function:
  warm call      150 ms  → ~$0.0000015 per call
  cold call      2,300 ms → ~$0.000023 per call   (~15x the warm cost)
 
1M cold calls/month → $23 in cold-start duration alone
  vs. 1M warm calls → $1.50

The cold start is a 15x price multiplier on the same work. Every optimization that reduces cold-start frequency or duration — provisioned concurrency, SnapStart, smaller runtimes, less init work — is a pricing optimization as much as a latency one. And the platforms know it: provisioned concurrency exists precisely to let you pre-pay for warmth, at an hourly rate per provisioned instance (roughly $0.00000417–$0.00000834 per GB-hour depending on region), which only pays off when the functions it keeps warm are actually exercised — otherwise you are paying for idle heat.

Timeouts, retries, and the tax on sloppy engineering

Because billing is per-request and per-duration, the failure modes that cost money are the ones that add time:

  • Timeouts. A function configured for 30 s that usually finishes in 300 ms means a single slow dependency (a database query that blocks for 20 s during a stall) bills 20 s of duration. The timeout is a budget — set it to the p99 plus a margin, not to the maximum the platform allows.
  • Retries. Event-source retries (SQS, SNS, EventBridge) re-invoke the same function with the same payload. If the first attempt fails because of a slow dependency, every retry pays the full duration again — a failing function is a compounding bill, not a flat one.
  • Per-invocation fan-out. "Call 20 functions per request" bills 20 request fees and 20 durations. The aggregation that reduces invocations (batch events, batch records from SQS) is a direct cost reducer — SQS batch size 10 turns 10 invocations into 1.

What the numbers actually decide

The bill is a diagnostic. Run it backwards:

  • Duration per invocation tells you where your code waits — and the cloud charges you for waiting.
  • Memory sweep tells you the cost-optimal CPU share — the cheapest function is the one that finishes fastest per dollar, not the one that uses the least memory.
  • Cold-start frequency tells you whether the workload needs warmth, and provisioned concurrency is only worth it when the kept-warm instances serve real traffic.
  • Timeout and retry behavior tells you how much of the bill is failure amplification rather than work.

The runtime view

  • Serverless pricing = memory × duration × rate, plus a per-invocation fee — latency is a line item, billed per millisecond.
  • Cold starts are billed at full rate; they are a 10–20x multiplier on the same work, which makes cold-start reduction a cost optimization.
  • Timeouts, retries, and fan-out amplify the bill; they are failure modes with a dollar sign attached.
  • If the bill is dominated by overhead rather than work, the pricing model is telling you to leave serverless — the invoice is the benchmark.