The Serverless Myth: "You Only Pay For What You Use"

The promise of serverless computing is seductive: no servers to manage, infinite scalability on demand, and a billing model that charges you only when your code is actually running. For small projects and experimental workloads, that promise holds up remarkably well. But as teams move production traffic onto serverless infrastructure, a more complicated financial reality starts to emerge. Serverless is, at its core, a deployment model — not a cost-reduction strategy — and conflating the two is where engineering teams begin to run into trouble.

Understanding where the costs accumulate requires a closer look at each individual pricing dimension. The sticker price on any single serverless service rarely tells the full story. It is the interaction between services, and the volume at which modern applications operate, that turns reasonable unit economics into surprising monthly invoices.

Lambda: The Duration Billing Trap

AWS Lambda charges on two axes: the number of invocations and the duration of each execution, measured in GB-seconds (the amount of memory allocated multiplied by the time the function runs, rounded up to the nearest millisecond). On the surface, this seems fair and granular. In practice, the math has a few wrinkles that teams routinely underestimate.

Memory allocation in Lambda is a lever that affects both performance and cost simultaneously. A function allocated 128 MB of memory runs slower than the same function allocated 1024 MB, because Lambda also scales CPU proportionally with memory. A function that takes 800ms at 128 MB might complete in 90ms at 1024 MB. Depending on the workload, bumping memory can actually reduce cost even though the per-GB-second rate is the same — simply because the duration drops dramatically. Teams that never profile their Lambda memory settings often leave money on the table, or worse, overpay for slow, under-resourced functions.

Cold starts compound this further. Initialisation code that runs outside the handler — database connection pools, SDK clients, large configuration objects — executes on every cold start and contributes to billed duration. In high-churn environments where functions scale up and down frequently, cold start billing can represent a non-trivial fraction of total Lambda spend, even though it produces no useful work for the end user.

DynamoDB On-Demand: Affordable Until It Isn't

DynamoDB's on-demand pricing mode is a natural companion to Lambda workloads. There are no capacity units to pre-provision, no utilisation forecasts to get right, and no idle-capacity waste. For unpredictable or spiky traffic, it is genuinely the right choice. But at sustained, high-throughput scale, the economics invert sharply.

On-demand pricing charges per read and write request unit. At low volumes, the per-request cost is essentially invisible. At millions of requests per hour — which is not an unusual figure for a production API — the cost per request accumulates into something that dwarfs what a provisioned capacity configuration with auto-scaling would cost for the same workload. The crossover point varies by access pattern, but teams that start with on-demand and never revisit the decision as traffic grows are often surprised when they finally run the comparison.

There is also the matter of item size. DynamoDB rounds reads and writes up to the nearest read or write request unit boundary. A read of a 0.5 KB item still consumes a full read request unit. Storing wide, denormalised items — a common pattern in document-style DynamoDB design — means paying for capacity you are not fully using on every individual read. At scale, this overhead is meaningful.

API Gateway vs. ALB: A $3.50-Per-Million-Request Decision

API Gateway is the default front door for Lambda-backed APIs, and it earns that position: it offers request validation, usage plans, API keys, authorisers, and a mature deployment model. It is also, per request, significantly more expensive than an Application Load Balancer used as a Lambda trigger.

The pricing gap between API Gateway and ALB becomes relevant at volume. API Gateway charges per API call, with additional charges for data transfer, caching, and WebSocket messages. ALB charges based on Load Balancer Capacity Units, which account for new connections, active connections, and processed bytes — a model that tends to be far cheaper for high-request-rate workloads that do not need the full feature set of API Gateway.

The decision is not simply about cost. API Gateway provides capabilities that ALB cannot replicate without additional engineering effort. But teams that default to API Gateway for every Lambda integration, without evaluating whether those features are actually needed, are paying a premium that compounds with every request. For internal microservice communication, high-frequency event processing, or workloads where the API management layer adds nothing, ALB deserves serious consideration.

Step Functions: Counting State Transitions at Cents Per Thousand

AWS Step Functions is an elegant solution for orchestrating complex, multi-step workflows. It removes the need to manage retry logic, branching, error handling, and long-running coordination in application code. The cost model, however, is charged per state transition — and "state transition" is defined more broadly than most teams initially assume.

Every task execution, every choice branch evaluation, every wait state, every catch, and every retry all count as state transitions. A workflow that looks simple in a diagram — five or six steps — may involve twelve to twenty state transitions per execution once error-handling paths are accounted for. Multiply that by the number of workflow executions per day for a busy system, and state transition costs can reach surprising levels.

The Express Workflows pricing tier, introduced for high-volume short-duration workflows, uses a different model based on execution duration rather than per-transition billing. For the right use case, it is substantially cheaper than Standard Workflows. But the two workflow types have different execution semantics — Express Workflows offer at-least-once execution rather than exactly-once — and selecting the wrong type for a use case that requires exactly-once guarantees introduces correctness problems that no pricing optimisation is worth.

The Hidden Multiplier: Service Interaction Costs

One of the most overlooked cost vectors in serverless architectures is the way individual service costs compound when services call each other. A single user-facing API request might trigger a Lambda function, which writes to DynamoDB, publishes to SNS, invokes a Step Functions workflow, and reads from S3. Each of those interactions carries its own billing dimension.

In a traditionally deployed monolith or even a containerised microservice, many of these operations happen in-process or over internal networking with no per-call cost. In a serverless architecture, every hop is a billable event. Teams that model costs at the individual service level — "Lambda is cheap, DynamoDB is cheap" — often fail to model the aggregate cost of a complete transaction path. Distributed tracing tools and cost-per-request breakdowns are essential for surfacing this reality before it appears on a bill.

Designing With Cost as a First-Class Concern

None of this means serverless is the wrong choice. For variable workloads, event-driven architectures, and teams that want to minimise operational overhead, it remains a compelling option. But the decision to go serverless should be made with clear eyes about the economic model.

The organisations that get the most out of serverless are those that treat cost as an architectural concern from the beginning — profiling Lambda memory allocations, revisiting DynamoDB capacity modes as traffic matures, selecting API Gateway only when its features are genuinely needed, and modelling Step Functions workflows to understand their true transition count. Pay-per-use billing is transparent, but only if you know exactly what you are paying per use of each service in your stack.

Serverless shifts the cost structure, not the cost itself. Understanding that distinction is what separates teams that benefit from the model from those who end up migrating workloads back to containers after an unexpectedly large cloud bill.