Skip to content

Intermediate · Serverless, monitoring and cost control · topic 19 of 50 · 30 min

Serverless with AWS Lambda

Explanation

Serverless means AWS runs the servers for you: you upload a function, it runs only when an event arrives, it scales out on its own and scales to zero when idle. AWS Lambda charges per request and per GB-second of run time. It suits short, spiky jobs (up to 15 minutes) and is a poor fit for long jobs or a steady, heavy load.

Why serverless?

With EC2 you rent a server by the hour. You choose its size, patch its operating system, and pay for it even at 3 am when nobody uses your app. Serverless is a different deal. There are still servers, but AWS owns and manages them completely. You give AWS a small piece of code and say when it should run. AWS starts it, runs it, and stops it.

Three ideas make serverless attractive. First, no servers to manage: no operating system patches and no capacity planning. Second, automatic scaling: one request or ten thousand, AWS starts as many copies as needed. Third, scale to zero and pay per use: when there are no requests, there is no compute bill.

Think of it like this: Serverless is like taking an auto-rickshaw instead of owning a car. You pay per ride, there is no insurance or servicing to worry about, and on days you stay home you pay nothing. But if you drive 100 km every single day, owning a car (a server you keep running) may work out cheaper.

A Lambda function: handler, event and context

A Lambda function is your code plus its settings: the runtime, memory, timeout and permissions. The runtime is the language environment that runs your code. AWS provides managed runtimes for Python, Node.js, Java, .NET and Ruby. Go and Rust run on the OS-only runtime, and you can also package a function as a container image.

The handler is the function Lambda calls each time. It receives two things. The event is a JSON object that describes what happened: an HTTP request, a file upload, a queue message. The context is an object with details about this run, such as the request ID and how many milliseconds are left before the timeout.

python
import json

def handler(event, context):
    params = event.get("queryStringParameters") or {}
    name = params.get("name", "friend")
    return {
        "statusCode": 200,
        "headers": {"Content-Type": "application/json"},
        "body": json.dumps({"message": f"Namaste, {name}!"}),
    }
A handler behind API Gateway. The body must be a string, so the dictionary is turned into JSON text.

Triggers: what makes a function run

TriggerExampleHow Lambda is called
API GatewayA mobile app calls GET /menuSynchronous: the caller waits for the answer
Amazon S3A photo is uploaded to a bucketAsynchronous: S3 hands over the event and moves on
Amazon SQSOrder messages wait in a queueLambda polls the queue and sends batches to your code
EventBridge scheduleEvery night at 2 am ISTAsynchronous, on a cron or rate schedule
yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  ThumbnailFunction:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: python3.13
      Handler: app.handler
      CodeUri: src/
      MemorySize: 512
      Timeout: 30
      Environment:
        Variables:
          OUTPUT_PREFIX: thumbnails/
      Events:
        PhotoUploaded:
          Type: S3
          Properties:
            Bucket: !Ref PhotosBucket
            Events: s3:ObjectCreated:*
        Nightly:
          Type: Schedule
          Properties:
            Schedule: cron(30 20 * * ? *)
  PhotosBucket:
    Type: AWS::S3::Bucket
An AWS SAM template: one function with two triggers. The cron time is in UTC, so 20:30 UTC is 2 am in India.

Limits you must know

SettingLimit (check the Lambda quotas page for changes)
TimeoutDefault 3 seconds, maximum 900 seconds (15 minutes)
Memory128 MB to 10,240 MB. CPU power grows with memory
Temporary disk (/tmp)512 MB by default, configurable up to 10,240 MB
Environment variables4 KB in total per function
Deployment package50 MB zipped upload, 250 MB unzipped, or a container image up to 10 GB
ConcurrencyA per-Region quota of running copies, often 1,000; new accounts may start lower

How Lambda is priced

You pay for two things. Requests: about US$0.20 per million. Duration, measured in GB-seconds: the memory you chose in GB multiplied by the seconds your code ran. On x86 in us-east-1 one GB-second costs about US$0.0000166667; Arm (Graviton) functions cost less. Every month the always-free allowance covers 1 million requests and 400,000 GB-seconds. Prices change and differ by Region, so always check the current pricing page.

Worked example: a function with 512 MB (0.5 GB) runs for 200 ms (0.2 s) and gets 3 million requests a month. Duration is 3,000,000 × 0.5 × 0.2 = 300,000 GB-seconds, which fits inside the free 400,000. Requests: 3 million minus 1 million free leaves 2 million, which is 2 × US$0.20 = US$0.40 for the month.

Cold starts

When a request arrives and no copy of your function is ready, Lambda must create a new execution environment: download your code, start the runtime, and run your setup code. This extra delay is a cold start. It can be under 100 ms for a small Python function or a few seconds for a large Java app. Later requests reuse the warm environment and are fast.

  • Keep the package small and avoid heavy frameworks you do not need.
  • Create SDK clients and database connections outside the handler, so warm runs reuse them.
  • Give more memory: you also get more CPU, so setup finishes sooner.
  • Use provisioned concurrency (copies kept warm, charged even when idle) for latency-sensitive APIs.
  • Use SnapStart where your runtime supports it (Java, and newer Python and .NET versions; check the docs).

Execution role and environment variables

Every function has an execution role: an IAM role Lambda takes on when your code runs. If the code reads from DynamoDB, the role needs that permission and nothing more. The managed policy AWSLambdaBasicExecutionRole lets the function write its logs to CloudWatch. Environment variables hold settings such as a table name or a stage name, so the same code runs in dev and prod.

bash
aws lambda invoke --function-name hello-api \
  --cli-binary-format raw-in-base64-out \
  --payload '{"queryStringParameters":{"name":"Asha"}}' out.json
cat out.json

aws lambda update-function-configuration --function-name hello-api \
  --memory-size 512 --timeout 30 \
  --environment "Variables={STAGE=dev,TABLE_NAME=orders-dev}"
Call a function from the AWS CLI, then change its memory, timeout and environment variables.

When NOT to use Lambda

  • Jobs longer than 15 minutes, such as a two-hour video render. Use ECS with Fargate or AWS Batch, or split the job with Step Functions.
  • A steady, heavy load all day and night. A right-sized EC2 or container fleet with a Savings Plan is often cheaper.
  • Work that needs a GPU, or a lot of local state kept between requests.
  • APIs where even an occasional cold start of a second is not acceptable, unless you pay for provisioned concurrency.
Careful: Common mistakes: (1) Leaving the default 3-second timeout, so slow calls fail. Set a timeout that fits the work. (2) An S3-triggered function that writes its output into the same bucket and prefix, which triggers itself again in a loop. Write to a different bucket or prefix. (3) Putting passwords in plain environment variables or printing them to logs. Use Secrets Manager or Parameter Store. (4) Putting a function in a VPC and wondering why it cannot reach the internet: it needs a NAT gateway or VPC endpoints.
Tip: Lambda writes everything your code prints to a CloudWatch log group named /aws/lambda/<function-name>. When something fails, look there first.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Serverless with AWS Lambda · 1/8

Serverless with AWS Lambda

In this lesson you meet serverless computing and AWS Lambda, where you upload code and AWS runs the servers.

Prefer a video by a teacher? Find free videos on “aws lambda tutorial for beginners python handler api gateway” on YouTube ↗

In real life: Product photos for a kirana delivery app

A small grocery delivery startup in Pune lets shop owners upload product photos from their phones. Each upload lands in an S3 bucket, which triggers a Lambda function that makes a small thumbnail and saves it under another prefix. Most days there are a few hundred uploads, so the bill is close to zero and fits the free allowance. Before Diwali, thousands of shops upload at once and Lambda simply runs more copies in parallel. Nobody had to add servers, and nobody pays for idle servers in the quiet weeks after the festival.

python
import boto3

s3 = boto3.client("s3")  # created once, reused by warm runs

def handler(event, context):
    for record in event["Records"]:
        bucket = record["s3"]["bucket"]["name"]
        key = record["s3"]["object"]["key"]
        print("New photo:", bucket, key)
        # download, resize, and upload to thumbnails/ here
    return {"processed": len(event["Records"])}
An S3-triggered handler. One event can carry several records.

Practice (0/3 done)

Task 1 · Code · Python

Write lambda_monthly_cost(requests, avg_ms, memory_mb, price_per_million=0.20, price_per_gb_second=0.0000166667, free_requests=1_000_000, free_gb_seconds=400_000). GB-seconds = requests × (avg_ms / 1000) × (memory_mb / 1024). Subtract the free allowances (never below zero), price what is left, and return the total in US dollars rounded to 2 decimal places. The rates are parameters because prices change: check the current pricing page.

Task 2 · Code · Javascript

Write handler(event) for a small GST API behind API Gateway (REST API proxy format). If event.httpMethod is not "GET", return status 405. If event.path is not "/gst", return 404. Read amount and rate from event.queryStringParameters (which may be null); rate defaults to 18. If amount is missing, empty, not a number or negative, return 400. Otherwise return 200 with a body of {"amount", "rate", "gst", "total"}, where gst = amount × rate / 100 and both gst and total are rounded to 2 decimals. Every response is { statusCode, headers: { "Content-Type": "application/json" }, body: JSON string }, and error bodies look like {"error": "..."}. (In real Lambda you would write an async handler; here it is a plain function so the tests can call it.)

Task 3 · Question

A nightly job converts a full day of CCTV footage and takes about 2 hours. Where should it run?

Quick quiz

Question 1

1.What is the maximum timeout of a single Lambda invocation?

Question 2

2.How do you give a Lambda function more CPU power?

Question 3

3.A function uses 1,024 MB and runs for 500 ms. How many GB-seconds is one run?

Question 4

4.Which change does NOT help reduce cold start time?

Question 5

5.What gives a Lambda function permission to read from a DynamoDB table?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What is the maximum timeout of a single Lambda invocation?

Answer: 15 minutes

The timeout can be set up to 900 seconds, which is 15 minutes. The default is only 3 seconds.

How do you give a Lambda function more CPU power?

Answer: Increase its memory setting

Lambda gives CPU in proportion to the memory you configure, so more memory also means more CPU.

A function uses 1,024 MB and runs for 500 ms. How many GB-seconds is one run?

Answer: 0.5

1,024 MB is 1 GB, and 500 ms is 0.5 seconds. 1 × 0.5 = 0.5 GB-seconds.

Which change does NOT help reduce cold start time?

Answer: Raising the timeout from 30 to 300 seconds

The timeout only sets how long a run may last. It does nothing for start-up time.

What gives a Lambda function permission to read from a DynamoDB table?

Answer: Its execution role

The execution role is the IAM role Lambda assumes when running your code. Its policy must allow the DynamoDB read.

A nightly video-processing job can restart if stopped. Which pricing model is likely cheapest?Related

Answer: Spot Instances

Spot is up to about 90% off and suits work that can handle a 2-minute interruption.

From Pricing, billing and cost control

Which service runs your container, scales with traffic and can scale down to zero?Related

Answer: Cloud Run

Cloud Run is serverless containers with scale to zero.

From Core Google Cloud services

When would the EC2 launch type make more sense than Fargate?Related

Answer: For a steady, heavy workload that needs GPUs or special instance types

The EC2 launch type gives you control of instance types such as GPUs, and can be cheaper for steady, tightly packed load.

From Amazon ECS and AWS Fargate

What makes a portfolio README most useful to an interviewer?Related

Answer: A diagram, reasons for each service, security choices, cost and teardown steps

Interviewers want to see your decisions and that you think about security and cost.

From Portfolio projects that get interviews

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Serverless, monitoring and cost control” before its exam: Event-driven design: API Gateway, SQS, SNS, EventBridge and Step Functions, Monitoring with CloudWatch, CloudTrail and Config, Cost control in practice.
  2. Module 5 exam: Serverless, monitoring and cost control · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Microsoft Azure essentials. 50 topics left in the course before the final exam.

← Previous: DNS and CDN: Route 53 and CloudFront