What is Serverless Computing? Functions, Cold Starts, and Trade-offs

Serverless computing lets you run application code without managing the underlying servers. You write a function, deploy it to a provider like AWS Lambda, and the provider handles provisioning, scaling, availability, and patching. When your function is triggered -- by an API request, a file upload, a database change, or a scheduled cron -- the provider runs it and charges you for execution time only.

The term "serverless" is a slight misnomer -- there are servers, you just do not manage them. What it really means is that the server is not your problem. This is a genuine advantage for certain workloads. It is also a source of surprises for teams that adopt it without understanding the constraints.

Serverless functions often sit alongside Docker containers in modern cloud architectures, and both are typically managed through CI/CD pipelines.

How AWS Lambda Works

A Lambda function is a piece of code (Python, Node.js, Go, Java, or a custom runtime) packaged as a deployment zip or container image. You define the trigger -- an API Gateway HTTP request, an S3 upload event, an SQS message, a CloudWatch Events schedule -- and Lambda runs your function when that trigger fires.

Here is a simple Python Lambda function that processes S3 upload events:

import json
import boto3

s3 = boto3.client('s3')
rekognition = boto3.client('rekognition')

def handler(event, context):
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = record['s3']['object']['key']

        # Run image analysis on the uploaded file
        response = rekognition.detect_labels(
            Image={'S3Object': {'Bucket': bucket, 'Name': key}},
            MaxLabels=10,
            MinConfidence=80
        )

        labels = [label['Name'] for label in response['Labels']]
        print(f"Detected labels for {key}: {labels}")

        # Store results back to S3
        result_key = f"results/{key}.json"
        s3.put_object(
            Bucket=bucket,
            Key=result_key,
            Body=json.dumps({'labels': labels}),
            ContentType='application/json'
        )

    return {'statusCode': 200, 'body': 'processed'}

Every time a file is uploaded to the configured S3 bucket, Lambda invokes this function automatically. Zero servers to provision, zero instances to keep running between uploads.

The Cold Start Problem

Cold starts are the most frequently cited serverless performance issue. When Lambda receives an invocation and no warm execution environment exists, it must: pull your deployment package, initialise the language runtime, load your code and dependencies, and then run your handler. For a Python function with minimal dependencies, this might take 200--400ms. For a Java function with a Spring framework, it can exceed 3--5 seconds.

The practical implications: cold starts matter for user-facing APIs where latency is visible. They matter less for background processing, batch jobs, or event-driven workflows where a few seconds of startup latency is invisible.

Mitigation options include: keeping functions small and dependencies minimal; using provisioned concurrency to pre-warm a set number of instances; choosing runtimes with fast initialisation (Python, Node.js, Go over Java); and keeping functions warm with scheduled low-cost pings for critical paths.

Pricing Model

Lambda charges on two dimensions: the number of invocations (currently $0.20 per million requests) and duration ($0.0000166667 per GB-second). The first 1 million requests and 400,000 GB-seconds per month are free. For event-driven workloads with irregular traffic, this pricing model is hard to beat -- you pay nothing when nothing runs.

The trap is high-throughput workloads. A function handling 100 million requests per month at 200ms average duration and 512MB memory will cost more than the equivalent ECS task running continuously. Model your expected traffic before committing an architecture to serverless.

When Serverless Is the Right Choice

Serverless fits naturally for: event-driven processing (S3 upload processing, webhook handlers, message queue consumers); scheduled batch jobs that run infrequently; low-traffic APIs with variable or unpredictable load; glue code between AWS services; and anything where you want to avoid infrastructure management overhead entirely.

Serverless tends to become a trap for: latency-sensitive, high-traffic APIs where cold starts are visible and costs escalate; long-running workloads (Lambda has a 15-minute maximum execution time); stateful workloads that need in-process caching; and complex architectures where vendor lock-in to AWS event bindings creates significant migration risk.

Serverless is covered as part of the cloud architecture section in the DevOps tools guide.

Frequently Asked Questions