Serverless computing was supposed to be the end of infrastructure management. Deploy a function, pay only for what you use, never think about servers again. The reality, five years into widespread adoption, is more complicated — and more interesting.
What serverless actually means
When you deploy an AWS Lambda function or a Vercel Edge Function, there are absolutely servers running your code — you just don't manage them. The "serverless" label means you don't provision, patch, or scale servers. You pay per-invocation rather than for always-on capacity. The operational burden genuinely shifts: you're not managing infrastructure, but you are managing a very different kind of complexity.
Where serverless genuinely shines
Event-driven workloads — image processing triggered by uploads, webhook handlers, scheduled jobs, API backends with spiky traffic — are natural fits. For these, serverless delivers on its promise: near-zero idle costs, automatic scaling, and dramatically reduced ops overhead.
The cold start problem
Serverless functions that haven't been invoked recently need to "spin up" — loading your runtime, dependencies, and code. This cold start latency (anywhere from 100ms to several seconds depending on the runtime and function size) is unacceptable for user-facing applications requiring consistent sub-100ms responses. Workarounds exist (provisioned concurrency on Lambda, keeping functions warm), but they erode the cost benefits.
The hidden complexity
Distributed tracing, observability, managing shared state without a persistent server, and debugging production functions are genuinely harder in serverless environments. The operational complexity doesn't disappear — it shifts from infrastructure management to application architecture. Teams without strong software engineering foundations often find this trade worse, not better.