Intermediate · Serverless, monitoring and cost control · topic 19 of 50 · 30 min
Serverless with AWS Lambda
Explanation
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.
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.
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}!"}),
}Triggers: what makes a function run
| Trigger | Example | How Lambda is called |
|---|---|---|
| API Gateway | A mobile app calls GET /menu | Synchronous: the caller waits for the answer |
| Amazon S3 | A photo is uploaded to a bucket | Asynchronous: S3 hands over the event and moves on |
| Amazon SQS | Order messages wait in a queue | Lambda polls the queue and sends batches to your code |
| EventBridge schedule | Every night at 2 am IST | Asynchronous, on a cron or rate schedule |
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::BucketLimits you must know
| Setting | Limit (check the Lambda quotas page for changes) |
|---|---|
| Timeout | Default 3 seconds, maximum 900 seconds (15 minutes) |
| Memory | 128 MB to 10,240 MB. CPU power grows with memory |
| Temporary disk (/tmp) | 512 MB by default, configurable up to 10,240 MB |
| Environment variables | 4 KB in total per function |
| Deployment package | 50 MB zipped upload, 250 MB unzipped, or a container image up to 10 GB |
| Concurrency | A 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.
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}"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.
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
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.
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"])}Practice (0/3 done)
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.
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.)
A nightly job converts a full day of CCTV footage and takes about 2 hours. Where should it run?
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Event-driven design: API Gateway, SQS, SNS, EventBridge and Step FunctionsServerless, monitoring and cost control · same module
- Monitoring with CloudWatch, CloudTrail and ConfigServerless, monitoring and cost control · same module
- Cost control in practiceServerless, monitoring and cost control · same module
- Core Google Cloud servicesGoogle Cloud and comparing the clouds
- Amazon ECS and AWS FargateContainers in the cloud
- Portfolio projects that get interviewsCertifications and cloud careers
Questions people ask about this
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.
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.
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.
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.
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
- 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.
- Module 5 exam: Serverless, monitoring and cost control · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, Microsoft Azure essentials. 50 topics left in the course before the final exam.