What Is a Downside of Serverless Computing?

What Is a Downside of Serverless Computing?

A complete, beginner-to-production guide to serverless computing’s biggest trade-off — and the six other downsides every architect discovers the hard way, once real traffic, real deadlines, and real production incidents arrive. Includes Java / Spring Boot examples, architecture diagrams, and real production lessons from Netflix, iRobot, Coca-Cola, and Thomson Reuters.

01
Introduction & History

The Taxi vs the Car in Your Driveway

If you’ve ever asked a cloud engineer “what’s the catch with serverless?”, you’ve probably heard some version of the same answer: cold starts. That’s the single most talked-about downside of serverless computing — the delay that happens when your code has to “wake up” before it can handle a request. But as you’ll see in this guide, cold starts are just the headline; serverless has a whole family of trade-offs that only become visible once you run it in production at scale.

This tutorial is written for absolute beginners who have never touched a cloud console, as well as for engineers evaluating serverless for a real production system. We’ll build up from “what is serverless, really?” all the way to “how do Netflix-scale companies work around its downsides.”

A Short History

The idea of running code without managing servers isn’t new — Platform-as-a-Service (PaaS) offerings like Google App Engine (2008) and Heroku (2007) already abstracted away infrastructure. But “serverless” as we know it today began with AWS Lambda, launched in November 2014. Lambda let developers upload a function, and AWS would run it in response to events — HTTP requests, file uploads, database changes — without the developer provisioning a single virtual machine.

Azure Functions (2016) and Google Cloud Functions (2017/2018) followed, and the term “Function-as-a-Service” (FaaS) became the technical name for this model, while “serverless” became the marketing umbrella that also includes managed databases (DynamoDB), managed queues (SQS), and Backend-as-a-Service (Firebase). By the early 2020s, serverless had matured into a default option for startups, side projects, and increasingly, enterprise systems — but with that maturity came painful, well-documented lessons about where it doesn’t fit.

Real-life Analogy

Think of a traditional server as owning a car: it’s parked in your driveway 24/7, ready the instant you need it, but you pay for insurance and fuel whether you drive it or not. Serverless is like calling a taxi: you only pay when you actually travel, but if no taxi is nearby when you call, you wait a few minutes for one to arrive — that wait is the “cold start.”

The Timeline, in a Bit More Detail

It helps to see how quickly this space moved, because the downsides we’ll discuss later weren’t obvious on day one — they surfaced only after thousands of teams pushed serverless into production and hit the same walls independently.

YearMilestone
2006–2008Amazon EC2 and Google App Engine popularise “infrastructure as an API” and early PaaS abstractions.
2014AWS Lambda launches at re:Invent, introducing the modern FaaS event-driven execution model.
2016Microsoft Azure Functions launches, followed shortly by early previews of Google Cloud Functions.
2018AWS adds native support for more languages (Go, .NET Core) and introduces Lambda Layers for shared dependencies.
2019–2020Container image support for Lambda, and Provisioned Concurrency arrive — both direct engineering responses to the cold-start problem.
2022–2023AWS Lambda SnapStart for Java significantly reduces JVM cold-start times, acknowledging just how painful the problem had become for enterprise Java workloads.
TodayServerless is a mature, widely adopted option — but the industry consensus has shifted from “serverless for everything” to “serverless for the right workloads,” precisely because of the downsides this guide covers.

That last row matters. Early serverless marketing sometimes implied it could replace all traditional compute. Years of production experience across thousands of companies corrected that narrative — and this guide reflects the more realistic, battle-tested view built from real incidents, real cost overruns, and real production debugging sessions rather than launch-day marketing copy.

2014
AWS Lambda launched at re:Invent
FaaS
Technical name for the model
15 min
Typical Lambda execution cap
Right
Workloads only — not everything
02
Problem & Motivation

The Problem Serverless Was Built to Solve

Before serverless, running a backend meant provisioning servers (physical or virtual) that sat there whether or not anyone was using them. Teams had to guess capacity ahead of time — too little, and the app falls over during a traffic spike; too much, and you’re burning money on idle machines. Patching operating systems, configuring auto-scaling groups, and managing load balancers consumed engineering time that had nothing to do with the actual business problem.

Serverless promised to remove all of that: no servers to patch, automatic scaling from zero to thousands of concurrent executions, and a billing model where you pay only for the milliseconds your code actually runs. For spiky, unpredictable, or infrequent workloads, this was transformative.

i
Beginner Example

Imagine you build a small tool that resizes an image whenever someone uploads one to your website. Most days, ten people use it. Some days, ten thousand people use it because your post went viral. With a traditional server, you’d have to provision for the worst day, wasting money every other day. With serverless, the platform just spins up more copies of your resize function automatically, and you pay per invocation.

But that same elasticity — spinning functions up and down on demand — is exactly what creates the downside we’ll spend most of this guide on: when a function hasn’t been used recently, the platform has to start a brand-new execution environment from scratch before it can process a request. That delay is unavoidable in the FaaS model, and it’s the reason architects can’t treat serverless as a drop-in replacement for every workload.

Before and After: a Small Team’s Story

Consider a small team running a notification service on three always-on virtual machines behind a load balancer. Most nights and weekends, traffic drops to almost nothing, yet all three machines keep running, keep costing money, and keep needing security patches. The team migrates the notification-sending logic to a serverless function triggered by a queue. Idle-time cost disappears almost entirely, and nobody has to patch an operating system again.

Six months later, the same team notices something they didn’t anticipate during the migration: their peak-hour p99 latency got worse, not better, because a meaningful fraction of invocations during bursty traffic are now cold starts. They also notice their cloud bill, while lower on quiet days, spikes higher than expected during a marketing campaign, because the pay-per-invocation pricing doesn’t have the same economies of scale as their old reserved-instance pricing did. This is a realistic, common shape for how the downsides of serverless surface — not as an obvious flaw on day one, but as a set of trade-offs that reveal themselves under real production conditions over time.

03
Core Concepts

The Vocabulary You Need First

Before we get to downsides, we need the shared vocabulary the rest of the guide depends on. Every term below is defined once, in plain English, and then reused throughout.

What Is Serverless Computing?

Serverless computing is a cloud execution model where the cloud provider dynamically manages the allocation and provisioning of servers, and the developer only writes and deploys code — typically small, single-purpose functions — without ever touching the underlying infrastructure. “Serverless” doesn’t mean there are no servers; it means the servers are invisible to you.

Function-as-a-Service (FaaS)

FaaS is the most common form of serverless. You write a function with a defined trigger (an HTTP request, a message on a queue, a file upload, a timer). The platform — AWS Lambda, Azure Functions, Google Cloud Functions, or open-source options like OpenFaaS and Knative — handles everything else: provisioning compute, scaling instances up and down, and tearing them down when idle.

Backend-as-a-Service (BaaS)

BaaS extends the serverless idea to entire backend capabilities: authentication (Firebase Auth, AWS Cognito), databases (DynamoDB, Firestore), and storage (S3), all consumed as managed APIs rather than software you run yourself.

Cold Start vs. Warm Start

A cold start happens when the platform must create a brand-new execution environment (download your code, start a runtime like the JVM, initialise your application) before running your function. A warm start happens when a previously-initialised environment is reused for a new request — much faster, because the setup work is already done.

Statelessness

Serverless functions are designed to be stateless: nothing you store in memory between one invocation and the next is guaranteed to survive. Every execution environment can be discarded at any time, so persistent state must live in an external store (a database, a cache, object storage).

Analogy: Stateless Functions

A stateless function is like a hotel room, not your own bedroom. You can’t assume your belongings (in-memory state) will still be there next time you check in — a different guest (or a fresh, empty room) might be waiting for you. Anything important has to go in a safe deposit box (an external database) instead of the nightstand drawer.

Event-Driven Execution

Serverless functions are triggered by events rather than running continuously. An event could be an API Gateway request, a new object in an S3 bucket, a row inserted into a database, or a scheduled cron-like timer.

Execution Environment / Sandbox

Behind the scenes, a “function” isn’t magic — it’s your code running inside a tightly isolated sandbox, often a lightweight virtual machine (AWS uses a technology called Firecracker specifically built for this) or a container. This sandbox gives you strong isolation from other customers’ code running on the same physical hardware, but it’s also the exact thing that has to be created fresh during a cold start.

i
Beginner Example: Putting the Concepts Together

Say you write a function called resizeImage. The event source is “a new file lands in the uploads/ folder of an S3 bucket.” When a photo is uploaded, S3 emits an event, the platform finds or creates a sandbox, loads your resizeImage code into it, runs it (stateless — it doesn’t remember the last photo it resized), writes the resized output to another bucket, and then may freeze or eventually destroy that sandbox. If a hundred photos are uploaded simultaneously, the platform creates roughly a hundred parallel sandboxes automatically — this is the “auto-scaling” benefit in action.

Memory, CPU, and Configuration

Even though you don’t manage servers, you still configure how much memory your function gets (and on most platforms, CPU scales proportionally with memory). This single setting has an outsized effect: more memory usually means faster cold starts and shorter execution time, but also a higher per-millisecond price — a trade-off you tune explicitly rather than one the platform hides from you entirely.

04
Architecture & Components

The Managed Building Blocks

A typical serverless system is made of several managed building blocks stitched together by events, rather than a single monolithic server.

Client / BrowserHTTPS request API Gatewayauth, routing invoke FaaS Functionyour handler code read/write Managed DatabaseDynamoDB / Aurora publish event Event Bus / QueueEventBridge / SQS Downstream Functiontriggered by event cache Managed CacheElastiCache / Redis logs, metrics Observability PlatformCloudWatch / X-Ray
Fig 1 · A serverless system is a collection of managed building blocks — the “server” disappears, but the diagram it leaves behind is denser than a traditional three-tier architecture.
ComponentRoleExample Services
API GatewayRoutes HTTP requests to functions, handles auth, throttlingAWS API Gateway, Azure API Management
FaaS RuntimeExecutes your function code in a managed containerAWS Lambda, Azure Functions, Google Cloud Functions
Event Bus / QueueDecouples producers and consumers of eventsAmazon EventBridge, SQS, Kafka
Managed DatabasePersists state outside the function’s ephemeral memoryDynamoDB, Aurora Serverless, Firestore
Object StorageStores files/blobs that trigger or are produced by functionsAmazon S3, Azure Blob Storage
ObservabilityCentralised logs, metrics, tracesCloudWatch, Datadog, X-Ray
04b
Comparing Compute Models

Serverless vs. Containers vs. Virtual Machines

Before diving deeper into the downsides, it’s worth grounding serverless against the two compute models it’s most often compared to, since most of its downsides are really the flip side of trade-offs those other models make differently.

DimensionVirtual MachinesContainersServerless (FaaS)
Startup timeMinutesSecondsMilliseconds (warm) to seconds (cold)
ScalingManual or auto-scaling groups, slowerFast via orchestrators (Kubernetes)Automatic, near-instant, to zero and back
Billing granularityPer hour / instancePer second / minute typicallyPer millisecond of execution
Runtime controlFull OS accessFull control within containerMinimal — sandboxed environment only
Max execution durationUnlimitedUnlimitedCapped (e.g., 15 minutes on Lambda)
State persistence in-processYesYes, while container runsUnreliable — can be recycled anytime
Cold-start-like penaltyRare after bootRare after warm-upRecurring, whenever scaled from zero

This table explains, in one glance, why the downsides in this guide exist: every property that makes serverless attractive (millisecond billing, scale-to-zero, no runtime management) is mechanically linked to the properties that create its weaknesses (cold starts, execution caps, and no persistent in-process state). You cannot have scale-to-zero without paying an initialisation cost when scaling back up — the two are the same coin, viewed from opposite sides.

Every property that makes serverless attractive is the same property that creates one of its downsides — two sides of one coin.
05
Internal Working

What Actually Happens Inside the Platform

Understanding the downside of serverless requires understanding what the cloud provider does behind the scenes every time your function is invoked.

Step-by-Step Execution

  1. Event arrives — a request hits the API Gateway or an event lands on a queue.
  2. Environment lookup — the platform checks whether a “warm” execution environment (a lightweight container or micro-VM, e.g. AWS Firecracker) already exists for your function.
  3. If warm: the platform reuses the existing environment, and your function runs almost instantly (often single-digit milliseconds of overhead).
  4. If cold: the platform must (a) find capacity on a physical host, (b) download your deployment package or container image, (c) start the language runtime (JVM, Node.js, Python interpreter), (d) run any static initialisers or Spring/DI container startup, and only then (e) execute your handler code.
  5. Execution — your handler runs, does its work, and returns a response.
  6. Freeze or teardown — the environment is either “frozen” for potential reuse (kept warm for a period, typically 5–15 minutes of inactivity before recycling) or eventually torn down entirely.
Client API Gateway FaaS Platform Execution Environment HTTP Request Invoke Function alt — COLD START Provision new sandbox Download code, start runtime, init else — WARM START Reuse existing sandbox Execute handler logic Response HTTP Response
Fig 2 · A cold start bolts on an entire “provision + initialise” leg that a warm invocation skips completely — and everything above the handler execution is what shows up as visible latency to the end user.
!
Why JVM Languages Suffer More

Languages like Java are especially exposed to cold-start latency because starting the JVM and initialising frameworks like Spring (component scanning, dependency injection, bean creation) can take hundreds of milliseconds to several seconds — compared to tens of milliseconds for a lightweight Node.js or Python function. This is one of the most concrete, measurable downsides of serverless for enterprise Java shops.

Here’s a minimal AWS Lambda handler written in Java, and you can already see where the cold-start cost hides — in everything that happens before handleRequest is even called:

Java · AWS Lambda handler with cold-start critical-path fields
package com.utivra.lambda;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

// This class is loaded and its constructor runs during COLD START.
// Every field initialised here adds to the cold-start duration.
public class OrderLookupHandler implements RequestHandler<OrderRequest, OrderResponse> {

    // Heavy objects created once per execution environment, not per request.
    // In a cold start, this constructor call is on the critical path.
    private final DynamoDbClient dynamoDbClient = DynamoDbClient.builder().build();
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public OrderResponse handleRequest(OrderRequest input, Context context) {
        // This method body only runs AFTER the environment is ready —
        // on a warm start, this is the ONLY thing that executes.
        String orderId = input.getOrderId();
        context.getLogger().log("Looking up order: " + orderId);

        GetItemRequest request = GetItemRequest.builder()
                .tableName("Orders")
                .key(Map.of("orderId", AttributeValue.builder().s(orderId).build()))
                .build();

        GetItemResponse result = dynamoDbClient.getItem(request);
        return OrderResponse.fromDynamoItem(result.item());
    }
}

Notice the comment on dynamoDbClient — building an AWS SDK client, and in a Spring Boot app, spinning up the entire application context, all happens once per cold execution environment. In a Spring Boot Lambda, this can easily add 2–6 seconds on the first invocation.

06
Data Flow & Lifecycle

The Three Phases of Every Function

A serverless function’s lifecycle has three broad phases, and each has implications for the downsides we’ll cover next.

1. Init Phase

This is where static initialisers, Spring context loading, database connection pool setup, and SDK client creation happen. It only runs on a cold start. AWS Lambda even gives this phase its own billing treatment and timeout (10 seconds by default) precisely because it’s a known bottleneck.

2. Invoke Phase

Your handler method executes with the actual event payload. This is the part developers think of as “their code,” but it’s often a small fraction of the total latency on a cold request.

3. Shutdown Phase

Eventually, if the environment stays idle too long, the platform reclaims it. Any in-memory state, open connections, or background threads are lost — which is why relying on in-memory caching between invocations is unreliable (it works sometimes, on warm starts, and silently fails other times).

1
Init — runs only on cold starts; SDK clients, Spring context, connection pools built here.
2
Invoke — your handler receives the event payload and does real work; often a small share of cold-request latency.
3
Shutdown — environment reclaimed after idle timeout; anything held in memory is lost silently.
i
Production Example: Netflix

Netflix uses AWS Lambda extensively for operational tooling and media processing pipelines, but has published engineering commentary describing how they carefully choose which workloads go serverless versus which stay on containers, specifically because of cold-start and long-running-workload constraints — validating that even at hyperscale, serverless is a deliberate trade-off, not a default.

07
The Core Answer

The Main Downside: Cold Start Latency

If you only remember one answer to “what is a downside of serverless computing,” make it this one: cold start latency — the unpredictable delay that occurs when a function must initialise a new execution environment before it can process a request, because the platform aggressively reclaims idle capacity to keep costs low for everyone.

Why It Happens

  • Elastic-by-design infrastructure: providers scale functions to zero when idle to avoid charging you (and wasting their own capacity) for unused compute — but scaling back up isn’t instant.
  • Runtime initialisation cost: heavier runtimes (JVM, .NET) and frameworks (Spring, large dependency trees) take longer to boot than lightweight interpreted languages.
  • Network and package size: larger deployment packages or container images take longer to fetch and unpack onto the host running your function.
  • VPC networking overhead: functions attached to a Virtual Private Cloud historically had extra latency to attach an elastic network interface, though modern platforms have significantly reduced this.

How Bad Is It, Really?

RuntimeTypical cold startTypical warm start
Node.js (small function)100–400 ms1–5 ms
Python (small function)150–500 ms1–10 ms
Java / Spring Boot (typical service)2,000–6,000+ ms2–20 ms
.NET (typical service)1,000–3,000 ms2–15 ms

These are illustrative ranges based on commonly reported figures for default configurations; actual numbers vary by cloud provider, memory allocation, package size, and VPC configuration.

!
Why This Matters for Real Users

Imagine a checkout API on an e-commerce site. If the underlying Lambda function has been idle for twenty minutes and a customer clicks “Pay Now,” that customer could wait several extra seconds — long enough to notice, long enough to abandon the cart — purely because of cold-start overhead, not because anything is actually broken.

Mitigations (and Their Own Trade-offs)

  • Provisioned Concurrency (AWS) / Pre-warmed instances (Azure Premium plan): the provider keeps a set number of environments permanently warm — but you pay for that idle capacity, partially undoing serverless’s core cost benefit.
  • Smaller deployment packages: trimming dependencies and avoiding unnecessary libraries shortens init time, but constrains framework choice.
  • Lighter runtimes: choosing Go, Rust, or slim Node.js functions instead of Java/Spring reduces cold-start time but may not match your team’s existing skill set.
  • SnapStart (AWS Lambda for Java): snapshots an initialised JVM and restores it, cutting Java cold starts dramatically — but adds its own constraints (e.g., handling non-deterministic state on restore).
Java · Spring Cloud Function
// Spring Cloud Function keeps your function decoupled from
// the FaaS platform's SDK, but Spring's component scanning
// still adds meaningfully to cold-start time versus a plain handler.

@SpringBootApplication
public class OrderFunctionApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderFunctionApplication.class, args);
    }

    @Bean
    public Function<OrderRequest, OrderResponse> lookupOrder(OrderRepository repo) {
        // Every bean here is constructed during the Spring context
        // refresh that happens once per cold execution environment.
        return request -> repo.findById(request.getOrderId())
                .map(OrderResponse::from)
                .orElseThrow(() -> new OrderNotFoundException(request.getOrderId()));
    }
}
08
Beyond Cold Starts

Other Major Downsides of Serverless Computing

Cold starts get the headlines, but production teams run into several other downsides just as often. Understanding all of them gives a complete, honest picture.

Lock-in

1. Vendor Lock-in

Serverless functions are typically written against a specific provider’s event formats, SDKs, and deployment model. Moving an AWS Lambda function to Azure Functions usually requires rewriting the handler signature, event parsing, and often the surrounding infrastructure-as-code. The deeper you integrate with provider-specific services (Step Functions, EventBridge, DynamoDB Streams), the harder migration becomes.

Time cap

2. Execution Time Limits

Most FaaS platforms cap how long a single invocation can run — AWS Lambda’s historical maximum is 15 minutes, for example. Long-running batch jobs, video transcoding, or large data exports simply don’t fit the model without being broken into chunks or moved to a different compute service (containers, batch processing).

Cost

3. Cost Unpredictability at Scale

Pay-per-invocation pricing is cheap for spiky, low-to-moderate traffic — but at sustained high volume, it can end up more expensive than a fixed set of always-on servers or containers, because you’re paying a per-millisecond premium instead of amortised infrastructure cost.

Debugging

4. Debugging and Local Testing Difficulty

Serverless functions run inside a managed, event-driven sandbox that’s hard to fully replicate locally. Developers commonly resort to simulators (SAM CLI, LocalStack, Azure Functions Core Tools) that approximate but don’t perfectly match production behaviour — subtle bugs around IAM permissions, timeouts, or event payload shapes often only surface after deployment.

Runtime

5. Limited Control Over the Runtime Environment

You can’t SSH into a Lambda instance, install arbitrary OS packages, fine-tune kernel parameters, or run background daemons the way you can on a VM or container host. Workloads that need specialised system-level tuning are a poor fit.

Stateless

6. Statelessness Constraints

Because any execution environment can be discarded at any moment, in-memory caches, WebSocket connections, and long-lived state can’t be reliably kept inside the function itself — they must be pushed to external, managed services, adding architectural complexity and network round-trips.

Tracing

7. Observability and Distributed Debugging Complexity

A single user request might fan out across a dozen short-lived functions, each with its own log stream. Reconstructing “what happened for this one failing request” requires distributed tracing (AWS X-Ray, OpenTelemetry) — without it, debugging becomes a hunt through fragmented CloudWatch log groups.

!
The “Death by a Thousand Cold Starts” Scenario

A common real-world failure mode: a system built from dozens of small serverless functions, chained together via queues and events, where each hop pays its own cold-start tax. A request that touches five cold functions in sequence can accumulate several seconds of latency that never shows up when testing any single function in isolation.

09
Pros, Cons & Trade-offs

The Balance Sheet, Side by Side

Every design choice has a bill attached. Here is what serverless gives you — and what it charges in exchange — laid out honestly on both sides.

Advantages

  • No server provisioning or OS patching
  • Automatic scaling from zero to very high concurrency
  • Pay-per-use billing, ideal for spiky / low-traffic workloads
  • Fast iteration for small, independent pieces of logic
  • Built-in high availability across a region by default

Disadvantages

  • Cold-start latency, especially for JVM/.NET runtimes
  • Vendor lock-in to provider-specific APIs and event formats
  • Hard execution time limits for long-running work
  • Can be costlier than reserved capacity at sustained high volume
  • Harder local testing, debugging, and distributed tracing
  • No control over the underlying runtime / OS environment
  • Statelessness forces reliance on external stores for any persistence

When Serverless Is the Right Trade-off

  • Event-driven, bursty workloads (image processing, webhooks, notifications)
  • Low-to-moderate, unpredictable traffic where idle server cost would be wasteful
  • Glue code between managed services (S3 → Lambda → DynamoDB)
  • Startups optimising for time-to-market over infrastructure control

When It’s the Wrong Trade-off

  • Latency-critical, high-throughput, sustained traffic (e.g., core trading systems)
  • Long-running batch or streaming jobs beyond the platform’s time limits
  • Systems needing fine-grained OS or network control
  • Teams that need multi-cloud portability without heavy abstraction investment
10
Performance & Scalability

Scaling and Performance Aren’t the Same Thing

Serverless platforms scale horizontally by creating more parallel execution environments as demand grows — this is one of the model’s genuine strengths. But scalability and performance aren’t the same thing, and that distinction matters when discussing downsides.

Concurrency Limits

Providers cap how many concurrent executions an account or function can have (AWS Lambda’s default account concurrency limit is commonly in the low thousands unless raised). Under a sudden massive spike, functions can be throttled, returning errors instead of scaling infinitely.

The “Scale-to-Zero, Then Scramble” Pattern

A function that scales to zero during quiet periods must scale up rapidly when traffic returns — and every one of those new environments pays the cold-start cost simultaneously, which can cause a visible latency spike right at the moment traffic increases, ironically the worst possible time.

Traffic spike beginsrequests per second climbs Warm instancesavailable? Yes No Serve from warm poollow latency Provision new envscold start begins Init phaseJVM / Spring startup First requests slowadded latency visible Environment becomes warmsubsequent reqs fast joins warm pool
Fig 3 · When traffic returns after a quiet spell, every new environment pays the init cost at once — the latency spike lands at the worst possible moment.

Tuning Memory for Performance

Because CPU allocation scales with configured memory on platforms like AWS Lambda, a common (if slightly counterintuitive) performance tuning technique is to increase memory even for functions that don’t need much RAM, purely to get more CPU and finish execution faster — sometimes lowering total cost even though the per-millisecond rate is higher, because the function finishes so much sooner. This kind of tuning is invisible to teams coming from traditional servers, where memory and CPU are typically provisioned independently.

Downstream Scalability Bottlenecks

A serverless function itself might scale beautifully to thousands of concurrent executions, but the systems it talks to often can’t. A relational database, a third-party API with its own rate limits, or a legacy internal service can all become the real bottleneck — meaning the elastic scalability serverless advertises is only as good as the least elastic system in the call chain.

11
High Availability & Reliability

Retries, Idempotency, and the Storm You Didn’t Plan For

Serverless platforms typically distribute function execution across multiple availability zones automatically, which gives strong default resilience against a single data centre failure — a genuine advantage over self-managed servers.

The downside surfaces in retry and idempotency behaviour: event-driven triggers (like SQS or EventBridge) may redeliver an event if a function times out or errors, meaning your function must be designed to handle duplicate invocations safely — something teams migrating from traditional request/response servers often overlook.

Java · idempotent payment handler
// Idempotency is not automatic in serverless — you must design for it.
public class PaymentHandler implements RequestHandler<PaymentEvent, Void> {

    private final IdempotencyStore idempotencyStore; // e.g., backed by DynamoDB
    private final PaymentService paymentService;

    @Override
    public Void handleRequest(PaymentEvent event, Context context) {
        // Because the platform may redeliver this event after a timeout,
        // we must check whether we've already processed this exact request.
        if (idempotencyStore.alreadyProcessed(event.getIdempotencyKey())) {
            context.getLogger().log("Duplicate delivery ignored: " + event.getIdempotencyKey());
            return null;
        }
        paymentService.charge(event.getAccountId(), event.getAmount());
        idempotencyStore.markProcessed(event.getIdempotencyKey());
        return null;
    }
}
!
Common Mistake

Assuming “at-least-once” delivery means “exactly-once.” Most serverless event sources guarantee at-least-once delivery, so duplicate invocations are a normal, expected occurrence — not an edge case.

Retry Storms and Dead-letter Queues

When a function fails, most event sources will retry automatically, often with a backoff schedule. If the root cause of the failure is systemic — a downstream dependency being down, for instance — automatic retries can pile on load right when the system is least able to handle it, a pattern sometimes called a retry storm. Configuring a dead-letter queue, where events that fail repeatedly are routed aside for manual inspection instead of retried indefinitely, is a standard safeguard, but it’s one more piece of infrastructure that a traditional always-on server with its own internal retry logic wouldn’t necessarily need in the same form.

12
Security

Fewer Servers to Patch, More Roles to Scope

Serverless shifts a large portion of the security burden — patching the OS, securing the hypervisor — to the cloud provider, which is a genuine benefit. But it introduces its own downsides.

  • Overly broad IAM permissions: because each function needs its own execution role, teams under time pressure often grant broader permissions than necessary (“just attach AdministratorAccess to get it working”), creating a large blast radius if a function is compromised.
  • Expanded attack surface via events: every event source (queue, storage bucket, API route) is a potential entry point, and validating untrusted event payloads is easy to skip in small, quickly-written functions.
  • Dependency risk: small teams shipping many independent functions often mean many independently-managed dependency trees, each needing its own vulnerability scanning.
  • Secrets management: environment variables are a common but insecure place to store secrets; proper use of a secrets manager (AWS Secrets Manager, Azure Key Vault) adds a network round-trip and, again, more cold-start-adjacent latency.
i
Production Example

Security audits of serverless environments consistently flag IAM over-permissioning as the top finding — a direct consequence of the operational simplicity that makes serverless attractive in the first place; it’s easy to grant broad access and move on when there’s no server to reason about.

Compare a poorly scoped role against a properly scoped one. Neither example is platform-specific syntax; the point is the principle of least privilege applied to a single function’s actual needs:

Over-permissioned Role

Grants full read/write access to every table in the account, every bucket, and every queue — “just in case,” or because it was copy-pasted from another project under deadline pressure. If this one function is compromised through a dependency vulnerability or an injection flaw, the blast radius is the entire account.

Least-privilege Role

Grants read access to exactly one DynamoDB table and write access to exactly one S3 prefix — nothing else. A compromise of this function can only affect that narrow slice of data, containing the damage.

Input validation deserves equal attention. Because event payloads can originate from many different sources — an API Gateway request, a queue message, a storage event — and because small functions are often written quickly, it’s tempting to trust the shape and content of an incoming event without validation. Treating every event payload as untrusted input, the same way you’d treat a raw HTTP request body, closes off an entire class of injection and deserialisation vulnerabilities that are otherwise easy to overlook in fast-moving serverless codebases.

13
Monitoring, Logging & Metrics

A Different Set of Dashboards

Traditional servers let you SSH in and tail a log file. Serverless functions don’t have a persistent host to log into — everything must be shipped off-box in real time, which is both a strength (centralised logging by default) and a downside (you’re dependent entirely on the provider’s observability tooling and its cost).

What to Monitor

MetricWhy It Matters
Cold start rate & durationDirectly impacts tail latency (p95 / p99)
Invocation count & concurrencyCost driver and throttling risk indicator
Error rate & throttlesSignals capacity limits being hit
Duration (billed vs. actual)Cost efficiency and timeout risk
Distributed trace spansRoot-cause analysis across chained functions

Tools like AWS X-Ray, OpenTelemetry, and Datadog’s serverless monitoring help stitch together the fragmented logs from many short-lived functions into a single trace per request — without this instrumentation, debugging a multi-function chain is genuinely painful, which is itself one of serverless’s practical downsides.

Alerting on the Right Signals

Teams new to serverless often reuse the same alerting thresholds they used for traditional servers — CPU usage, disk space, memory pressure — none of which are directly actionable in a FaaS context, since you don’t manage the underlying host. The more useful alerting signals are specific to the serverless execution model itself: a sudden rise in the cold-start percentage of total invocations, a climbing throttle count (a sign you’re hitting concurrency limits), and duration approaching the configured timeout (a sign a function is about to start failing outright rather than just running slowly). Building dashboards around these serverless-specific signals, rather than repurposing server-era metrics, is one of the less obvious adjustments teams need to make.

14
Deployment & Cloud

Small Packages, Big Consequences

Serverless deployment is typically managed through infrastructure-as-code tools: AWS SAM, the Serverless Framework, AWS CDK, or Terraform. These tools help, but package size and dependency management directly affect cold-start time, so deployment pipelines for serverless often need extra steps most server-based teams don’t think about.

  • Tree-shaking or trimming unused dependencies
  • Choosing between .zip deployment packages and container images (each has different cold-start characteristics)
  • Layer management for shared libraries across functions
  • Canary or linear deployment strategies to catch regressions without full-service impact
YAML · AWS SAM template excerpt
Resources:
  OrderLookupFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: com.utivra.lambda.OrderLookupHandler::handleRequest
      Runtime: java17
      MemorySize: 1024        # More memory = more CPU = often faster cold starts
      Timeout: 10
      ProvisionedConcurrencyConfig:
        ProvisionedConcurrentExecutions: 2   # Keeps 2 warm instances, at extra cost
      Environment:
        Variables:
          TABLE_NAME: Orders
!
Multi-cloud Portability Is Hard

Because the deployment descriptors, event schemas, and IAM models differ across AWS, Azure, and GCP, teams that want cloud portability usually adopt an abstraction framework (Serverless Framework, Knative) — which adds its own learning curve and can lag behind provider-native features.

15
Databases, Caching & Load Balancing

When Your Functions Outnumber Your Connections

The stateless, massively-concurrent nature of serverless collides most visibly with the systems it talks to — and that collision is the source of a distinct family of downsides worth understanding on its own.

Database Connections

Traditional applications keep a connection pool open for the lifetime of the server. Serverless functions, scaling to potentially thousands of concurrent instances, can each try to open their own database connection — quickly exhausting a traditional relational database’s max-connections limit. This is a downside unique to the serverless connection model.

!
The Connection Storm Problem

If your function scales to 2,000 concurrent executions and each opens a connection to a PostgreSQL instance with a max of 500 connections, you’ll see connection errors under load — even though your code is “correct.” The fix is typically a connection pooler service (like AWS RDS Proxy) or using serverless-native databases (DynamoDB, Aurora Serverless) designed for this pattern.

Caching

Because in-memory state isn’t reliable between invocations, caching typically requires an external managed cache (ElastiCache, Redis), adding a network hop that a traditional in-process cache wouldn’t need — a direct performance cost of statelessness.

Load Balancing

Load balancing is handled implicitly by the platform (API Gateway routes to whichever instance is available), which removes operational burden but also removes fine-grained control — you can’t easily implement custom load-balancing algorithms or sticky sessions the way you could with your own load balancer in front of a server fleet.

Serverless-Native Databases as a Workaround

Because traditional relational databases weren’t designed for thousands of simultaneous short-lived connections, the industry response has been a category of “serverless-native” databases — Amazon Aurora Serverless, DynamoDB, Google Firestore, PlanetScale — built from the ground up to accept high, spiky connection counts through HTTP-based data APIs or built-in connection multiplexing rather than the traditional TCP connection-per-client model. Adopting one of these often solves the connection-storm downside directly, but it comes with its own trade-off: these databases frequently have different query capabilities, consistency models, or pricing structures than the relational databases teams are used to, meaning the “fix” for one serverless downside can introduce a new modelling or migration challenge elsewhere in the stack.

16
APIs & Microservices

Granularity Cuts Both Ways

Serverless functions pair naturally with microservice and event-driven architectures — each function can represent a single responsibility, triggered by an API route or an event. But this granularity is itself a double-edged sword.

!
Downside: “Distributed Monolith” Risk

Splitting logic into many tiny functions can accidentally create tight coupling through shared databases or chained synchronous calls, producing all the operational complexity of microservices (network calls, partial failures, versioning) without the genuine independence that’s supposed to justify it.

A synchronous chain of functions — Function A calls Function B calls Function C, each over HTTP — multiplies both cold-start risk and failure surface. A best practice is to prefer asynchronous, event-driven chaining (via a queue or event bus) over direct synchronous invocation wherever the business logic allows it.

Versioning is another underestimated challenge. In a traditional monolith, changing a shared internal function signature is caught immediately at compile time. In a serverless microservice landscape, a function’s “contract” is its event schema, and a breaking change can silently ripple through every downstream consumer of that event, often without any compiler or type system catching the mismatch until a production failure occurs — which is why schema registries and contract testing matter more in serverless, event-driven systems than they typically do inside a single deployable application.

17
Design Patterns & Anti-patterns

Shapes That Help, Shapes That Hurt

A handful of design patterns show up again and again in real serverless systems — and a handful of anti-patterns cause most of the pain teams later attribute to “serverless being bad.”

Useful Patterns

  • Fan-out / fan-in: one event triggers many parallel functions, results aggregated later (e.g., via Step Functions).
  • Strangler pattern: gradually migrate pieces of a monolith to serverless functions behind the same API surface.
  • Saga pattern: coordinate multi-step, multi-function transactions using compensating actions instead of distributed transactions.

Anti-patterns (and the Downsides They Cause)

!
Anti-pattern · The “Lambda Pinball”

Synchronous chains of many functions calling each other directly, multiplying cold starts and making tracing painful.

!
Anti-pattern · Monolithic Lambda

Cramming an entire application into one giant function, defeating the granularity benefits and making cold starts even heavier due to a bloated dependency tree.

!
Anti-pattern · Storing State in Memory “Because It Usually Works”

Relying on warm-start reuse for correctness is fragile and will eventually fail silently.

!
Anti-pattern · Using Serverless for Long-running Batch Jobs

Hitting timeout limits and resorting to fragile checkpoint-and-resume hacks instead of using a purpose-built batch service.

Choosing Between Synchronous and Asynchronous Invocation

One of the most consequential early decisions in a serverless design is whether a given function is invoked synchronously (the caller waits for a response, as with an API Gateway request) or asynchronously (the caller fires an event and moves on, as with a queue or event bus). Synchronous chains amplify every downside covered in this guide — cold starts stack up, a slow downstream function directly slows the caller, and a single failure can cascade. Asynchronous, event-driven chains isolate failures and let each function retry independently, at the cost of added complexity in tracking the overall status of a multi-step process. As a rule of thumb, reserve synchronous invocation for the parts of a system where a human is actively waiting for a response, and prefer asynchronous, queue-based hand-offs for everything else.

18
Best Practices & Common Mistakes

Habits That Keep the Downsides Manageable

Serverless isn’t fragile — it’s specific. A short list of boring, repeatable habits is what separates teams that stay happy on serverless from teams that quietly regret it.

Best Practices

Best Practices
  • Keep deployment packages small and dependencies minimal to reduce cold-start time.
  • Use provisioned / pre-warmed concurrency for latency-sensitive, user-facing endpoints.
  • Design every handler to be idempotent, assuming at-least-once delivery.
  • Externalise all state to managed stores; never rely on in-memory persistence across invocations.
  • Use connection poolers or serverless-native databases to avoid connection storms.
  • Instrument distributed tracing from day one, not after the first production incident.
  • Apply least-privilege IAM roles per function, not shared broad roles.
  • Benchmark actual cold-start numbers for your chosen runtime and memory configuration before committing to serverless for a latency-critical path.

Common Mistakes

!
Common Mistakes
  • Choosing Java / Spring Boot for a latency-critical endpoint without measuring cold-start impact first.
  • Treating serverless cost estimates as automatically cheaper without modelling sustained high-volume traffic.
  • Ignoring event redelivery and building non-idempotent handlers.
  • Building deeply provider-specific architectures with no exit strategy, then being surprised by lock-in.
  • Skipping local testing tools and debugging exclusively in production.

A Pre-migration Checklist

Before moving an existing workload to serverless, it’s worth working through a short checklist that directly maps to the downsides covered in this guide.

1
Have we measured cold-start duration for our actual runtime and dependency footprint, not just generic benchmarks?
2
Does any part of this workload run longer than the platform’s maximum execution duration?
3
Have we modelled cost at our expected peak sustained throughput, not just average traffic?
4
Can our database handle the connection concurrency this function’s scaling profile implies?
5
Is every handler idempotent, assuming at-least-once event delivery?
6
Do we have a distributed tracing strategy for chains of more than one function?
7
Have we scoped IAM roles per function rather than reusing one broad role everywhere?
8
Is there a realistic exit strategy if we need to move off this provider later?

Answering “no” to several of these isn’t necessarily a reason to avoid serverless — but it is a signal to budget extra engineering time for the specific downside each question maps to, rather than discovering it under production load.

19
Real-World & Industry Examples

How the Named Adopters Actually Use It

The clearest evidence for how real the downsides of serverless are is the very deliberate way experienced adopters draw the line around where they use it.

IoT

iRobot

iRobot has publicly discussed using AWS serverless services (including Lambda) as part of the cloud backend that connects Roomba robots to mobile apps, citing scalability for spiky, device-triggered event traffic as a key motivator — while also having to design around cold-start and connection-scaling considerations for millions of connected devices.

Retail

Coca-Cola

Coca-Cola has described moving parts of its vending machine backend to a serverless architecture on AWS to handle unpredictable, geographically distributed request patterns from thousands of machines, favouring the operational simplicity of not managing servers for a system with highly variable regional traffic.

Streaming

Netflix

Netflix uses serverless functions for specific operational and media-processing tasks but deliberately keeps its high-throughput, latency-critical streaming path on containers and custom infrastructure — a clear real-world illustration that serverless downsides (cold starts, execution limits, cost at scale) make it unsuitable as a universal replacement even for companies with immense cloud expertise.

Content

Thomson Reuters

Thomson Reuters has discussed adopting serverless architecture for parts of its content and news-processing pipelines to reduce operational overhead, while noting that engineering teams had to specifically re-architect around cold starts and per-invocation cost modelling for the highest-volume processing paths — a pattern consistent with the other examples above.

i
Common Pattern Across These Examples

All these cases share a theme: serverless is adopted for bursty, event-driven, loosely-coupled workloads — and deliberately avoided or supplemented with other compute models wherever sustained throughput, strict latency, or long execution time is required. That selective adoption is itself the practical answer to “what’s the downside” — companies route around it rather than eliminate it.

Even hyperscale adopters treat serverless as a scalpel, not a hammer — and that selectivity is itself the industry’s honest answer to “what’s the downside?”
19b
Quick Glossary

The Terms in One Place

A single reference table for every specialised term used in this guide — useful the second time you come back to a section and want to double-check what a word actually meant.

TermPlain-English Meaning
FaaSFunction-as-a-Service — the model of deploying single functions that a provider runs on demand.
Cold startThe delay incurred when a new execution environment must be initialised before a function can run.
Warm startReusing an already-initialised execution environment, skipping most startup overhead.
Provisioned concurrencyPaying to keep a fixed number of execution environments permanently warm.
IdempotencyA property where processing the same event twice produces the same result as processing it once.
Vendor lock-inDependence on a specific provider’s proprietary APIs, making migration costly.
StatelessnessThe design constraint that no in-memory data is guaranteed to persist between invocations.
Event sourceThe trigger — an API call, queue message, file upload, or timer — that invokes a function.
Connection stormA surge of database connections caused by many concurrent function instances connecting simultaneously.
20
FAQ, Summary & Takeaways

Common Questions, and What to Remember

A short round of the questions people ask most often about the downsides of serverless — followed by a portable summary you can carry into any architecture review.

What Is the Single Biggest Downside of Serverless Computing?

Cold-start latency is the most frequently cited downside — the delay incurred when a new execution environment must initialise before handling a request, especially pronounced in JVM-based runtimes like Java and Spring Boot.

Is Serverless Always Cheaper Than Traditional Servers?

No. It’s typically cheaper for spiky or low-to-moderate traffic, but at sustained high volume the per-invocation pricing model can exceed the cost of reserved, always-on compute.

Can You Avoid Cold Starts Entirely?

Not entirely, but you can reduce their frequency and impact using provisioned concurrency, smaller deployment packages, lighter runtimes, or techniques like AWS Lambda SnapStart for Java — each with its own added cost or constraint.

Is Serverless Suitable for Long-running Jobs?

Generally no — most FaaS platforms cap execution duration (e.g., 15 minutes on AWS Lambda), so long-running batch or streaming workloads are usually better suited to containers or dedicated batch-processing services.

Does Serverless Mean There Are No Servers at All?

No — servers still exist and run your code, but the cloud provider manages them entirely, and they’re invisible to the developer.

Why Do Java Functions Have Worse Cold Starts Than Node.js or Python?

Because starting the Java Virtual Machine and initialising a framework like Spring (classpath scanning, dependency injection, bean creation) takes far more work than starting a lightweight scripting-language interpreter. Techniques like AWS Lambda SnapStart specifically target this gap by snapshotting an already-initialised JVM.

Does Using Serverless Mean I Don’t Need to Think About Scaling at All?

Mostly, but not entirely — you still need to be aware of account-level and per-function concurrency limits, and of downstream systems (like relational databases) that don’t scale as elastically as the functions calling them, which is where connection storms come from.

Is Serverless the Same Thing as “Cloud-native”?

No. Cloud-native is a broader philosophy that includes containers, orchestration, and microservices generally; serverless is one specific compute model within that broader philosophy, alongside container-based approaches like Kubernetes.

Can Serverless Functions Maintain a Database Connection Pool to Reduce the Connection-storm Problem?

Partially — reusing a connection across warm invocations helps, but it doesn’t solve the underlying issue that each concurrent cold environment still needs its own connection, which is why dedicated connection-pooling services or serverless-native databases are the more robust fix.

Summary

Serverless computing removes the burden of provisioning, patching, and scaling servers, and it shines for event-driven, unpredictable, or infrequent workloads. But that convenience comes with real, well-documented downsides: cold-start latency (especially for JVM-based languages), vendor lock-in, execution time limits, potentially higher costs at sustained scale, harder local debugging, limited runtime control, and the architectural overhead that statelessness demands. None of these downsides make serverless a bad technology — they make it a trade-off, and the mark of a good architect is knowing which workloads land on the right side of that trade-off.

In practice, most production systems today aren’t purely serverless or purely server-based — they’re a deliberate mix, with serverless functions handling the bursty, event-driven edges of a system while more predictable, latency-sensitive, or long-running cores stay on containers or dedicated compute. Recognising that hybrid reality, rather than treating the choice as all-or-nothing, is what separates architectural decisions that hold up under real production load from ones that only looked good in a proof-of-concept.

Key Takeaways

  • Cold-start latency is the most cited downside of serverless computing, and it’s worse for JVM-based runtimes like Java / Spring Boot than for lightweight interpreted languages, particularly for Spring applications with heavy component scanning and large dependency graphs.
  • Serverless functions are stateless by design — any persistent data must live in an external managed store, not in memory.
  • Vendor lock-in, execution time limits, and cost unpredictability at scale are just as important as cold starts when evaluating serverless for production.
  • Event sources typically guarantee at-least-once delivery, so every handler should be designed to be idempotent.
  • Database connection storms are a real, distinct failure mode caused by serverless’s massive concurrency model.
  • Even hyperscale companies like Netflix use serverless selectively, not universally — proof that the downsides are real engineering constraints, not just theoretical concerns.
  • Mitigations exist for most downsides (provisioned concurrency, SnapStart, connection poolers, tracing tools) but each mitigation reintroduces some of the cost or complexity serverless was meant to remove.

If you take one thing from this guide back into your next architecture discussion, let it be this: ask “what’s the downside of serverless for this specific workload,” not “is serverless good or bad” in the abstract. The answer changes completely depending on traffic shape, latency tolerance, runtime language, and how long a single unit of work needs to run — and a good architect’s job is weighing those specifics, not applying a blanket rule in either direction.

i
Summary in One Sentence

Cold starts are the headline, but the honest answer to “what’s the downside of serverless?” is a family of trade-offs — latency, lock-in, time limits, cost curves, statelessness, and observability overhead — that only become visible under real production load, which is why experienced adopters use serverless as a scalpel, not a hammer.

“Ask what the downside is for this specific workload — not whether serverless is good or bad. The answer is different every time, and that difference is the whole job.”