How to explain to students
Open with: "Imagine renting a server vs renting a taxi. EC2 = your own car (you pay 24/7 even when parked). Lambda = Uber (you pay only the trip)." Both run code. The difference is billing model and operational ownership.
Lambda makes sense when traffic is spiky, low-volume, or event-driven: a webhook handler called 100 times a day, a nightly cron job, an S3-upload thumbnailer. It stops making sense when traffic is steady and high — at ~5 million requests/day, EC2 or ECS becomes cheaper. The other big trade-off is cold starts: a Lambda that hasn't run in 5 minutes takes 200ms–2s to start.
🎯 Practice Questions
(a) Stripe webhook (50 events/day), (b) Real-time chat (5k concurrent connections), (c) Image thumbnailer triggered by S3 upload, (d) Steady-traffic REST API at 200 RPS.
Show Answer
(b) Real-time chat → Fargate. WebSockets with 5k connections need long-lived processes; Lambda WebSocket support exists but is unwieldy at this scale.
(c) Image thumbnailer → Lambda. Classic event-driven workload, S3 trigger, finishes in seconds.
(d) Steady 200 RPS API → Fargate. 200 × 86,400 = ~17M req/day. Lambda would charge per request and run constantly anyway; Fargate is cheaper at that volume and avoids cold starts.
How to explain to students
Mental model: "A Lambda is a vending machine. The trigger is the coin slot — it can be a button (HTTP), a sensor (S3 upload), a timer (cron), or another machine (DynamoDB stream)." The Lambda code doesn't change much. The trigger changes the event payload it receives.
The four canonical triggers cover 80% of real-world serverless: API Gateway (HTTP), S3 (file uploaded), DynamoDB Streams (row changed), EventBridge (schedule or cross-service event). Each delivers a typed event to your handler — read the AWS docs for the exact JSON shape.
🎯 Practice Questions
Show Answer
Records in the event payload — instead of 10 invocations. This is intentional: it reduces cold-start overhead and keeps cost down.Implication: always loop over
event.Records in S3 handlers. Treating event.Records[0] as if it were the only record will silently drop events under load.
sendEmail() directly inside the signup handler?How to explain to students
API Gateway sits in front of Lambda and turns HTTP into Lambda invocations. You define routes (POST /items, GET /items/{id}) in API Gateway; each route is wired to a Lambda function. API Gateway handles authentication, rate-limiting, and CORS.
Two flavours: REST API (the original, more features but more expensive) and HTTP API (newer, cheaper, simpler — start here unless you need the REST features). For most learners, HTTP API is the right default.
🎯 Practice Questions
app.example.com calls your API at api.example.com and gets a CORS error. List the two places the fix can live and the trade-off between them.Show Answer
Access-Control-Allow-Origin headers; your Lambda doesn't need to know about CORS at all.Option B — fix in Lambda: return CORS headers from every handler. Works, but easy to miss on a route, and adds CORS logic to every function.
Trade-off: Option A is centralised + DRY but adds API Gateway-specific config. Option B is portable but bug-prone. Pick A unless you have a specific reason.
POST /items and GET /items into two separate Lambdas instead of one with internal routing?How to explain to students
Don't put a Lambda in front of RDS for first projects. RDS = always-on database = 24/7 cost = defeats the serverless free-tier dream. DynamoDB is AWS's serverless key-value/document store — pay-per-request, autoscales, never down. Combined with S3 for files, you can build a complete serverless app at $0 idle.
DynamoDB has a learning curve — there are no joins, indexing is deliberate, and you design tables around your access patterns, not the data shape. Start with the simplest one-table design.
PAY_PER_REQUEST mode. $0 idle, scales to whatever traffic comes.🎯 Practice Questions
Show Answer
DynamoDB has no joins. Every query reads at most one partition key + sort key range. So you design the table so the queries you'll run map directly onto a single partition lookup. This often means denormalising — storing the same data in multiple shapes — and pre-computing relationships at write time.
The mantra: "What questions will I ask of this data?" before you design the table — opposite of SQL where you can usually re-shape queries later.
serverless deploy ships it all.How to explain to students
Wiring a Lambda + API Gateway + DynamoDB + IAM by hand takes 20+ AWS CLI commands and is impossible to reproduce. The Serverless Framework (or AWS SAM, or AWS CDK) describes everything in one file and generates the underlying CloudFormation. The community-favourite is Serverless Framework — readable YAML, tons of plugins, multi-cloud.
It also handles environments: a single command can deploy to dev / staging / prod with different env vars, IAM roles, and table names. Critical once your project leaves your laptop.
🎯 Practice Questions
Show Answer
AWS SAM — AWS-only YAML, thin wrapper over CloudFormation, official AWS support.
AWS CDK — write infra in TypeScript/Python/Go (real code, not YAML). Compiles to CloudFormation.
"Terraform but for serverless" → AWS CDK is closest in spirit (real code, declarative). But Serverless Framework is closer in scope — both are higher-level abstractions tuned for serverless apps. Terraform itself works fine for serverless too, just with more boilerplate.
${self:provider.stage} in the table name items-dev / items-staging / items-prod important?serverless deploy with no --stage flag and accidentally deploys to prod. How would you prevent this?How to explain to students
AI can produce a high-quality Lambda handler in seconds — these functions are usually 20–50 lines, follow well-known patterns (parse event, do work, return response), and have lots of training data. AI is also strong at IAM policies and serverless.yml YAML.
The trap: AI sometimes generates over-permissive IAM (everyone gets "Action": "*") and forgets edge cases (no input validation, no error handler). Treat the output as a draft and review every IAM statement before deploying.
🎯 Practice Questions
iam simulate-custom-policy instead of just trusting the output?Show Answer
1. Hallucinated action names.
s3:GetAllObjects, dynamodb:WriteAll — sound real, don't exist.2. Over-permissive scopes. AI defaults to
"Resource": "*" when one specific ARN would do. Works, then fails the security review.3. Wrong resource ARN format. S3 actions need both
arn:aws:s3:::bucket AND arn:aws:s3:::bucket/*. AI sometimes only includes one.iam simulate-custom-policy takes the policy + a list of actions + ARNs and tells you which would be allowed/denied. Run it before deploy — it's free and prevents the "policy has no effect, why doesn't this work" debugging session.
How to explain to students
Walk through this on screen first, then have students recreate it for their own domain (todos, bookmarks, notes — anything CRUD-shaped). The artefact: a public REST API at https://<random>.execute-api.eu-west-1.amazonaws.com, talking to DynamoDB, deployed via one command, costing $0/mo idle.
Sample quiz questions (interactive)
Fill-in-the-command
prod.How to explain to students
Frame as a cost-engineering memo: "You've been asked to host the company's contact-form backend (50 submissions/day, mostly business hours). Compare three architectures and recommend one with numbers. Your manager doesn't have time to read more than one page." This forces students to think about cost per request, idle cost, and operational overhead.
📋 Assignment Requirements
- Workload spec (use this exactly): "A contact form backend receiving 50 POST requests/day on weekdays (avg 200ms, 256 MB), storing each submission in a database, sending an email via SES on each submission, plus a static HTML status page served at
/." - Compare three architectures: (a) S3 + Lambda + DynamoDB + SES, (b) EC2 t3.micro + nginx + Postgres + SES, (c) Beanstalk + RDS + SES
- For each architecture: monthly cost breakdown (compute, storage, network, SES) using current AWS pricing
- Identify the AWS Free Tier coverage for each (be honest — some hide hidden costs after 12 months)
- Compare on three axes: cost, operational overhead, scalability headroom
- Include a 1-paragraph recommendation. Justify with at least 2 numeric arguments.
- Include 1 architecture diagram (hand-drawn, draw.io, or Excalidraw) for the recommended option
- Bonus: Pick a 100×-traffic version (5,000 submissions/day) — does the recommendation change? Why?
- Bonus: A 1-page tear-down script or reverse architecture diagram showing what to delete to stop billing