How to explain to students
Open with the pizza analogy: "Cooking at home = on-prem (you do everything). Take-and-bake = IaaS (kitchen + ingredients are yours, but the dough is provided). Delivery = PaaS (you eat at home, someone else cooks). Dining out = SaaS (you just show up)." Same hunger, very different ownership boundaries.
In AWS terms: EC2 is IaaS (you get a VM, you install everything). Elastic Beanstalk is PaaS (push your code, AWS runs it). Cognito is SaaS (auth-as-a-service, no code). DevOps engineers spend most time in IaaS + PaaS.
🎯 Practice Questions
Show Answer
PaaS: RDS (managed database — you choose engine + size, AWS handles backups + patches), Elastic Beanstalk (push code, AWS runs it), Lambda (push functions, AWS runs them).
SaaS: Cognito (auth-as-a-service — call an API, no infra at all).
The lines blur — Lambda is sometimes called Functions as a Service (FaaS), a sub-category of PaaS. The point is: as you move IaaS → SaaS, you give up control to gain speed.
How to explain to students
AWS has 250+ services. You don't need 250. Master four — EC2 (compute), S3 (storage), IAM (permissions), VPC (networking) — and you can read 90% of architecture diagrams. Everything else is built on top of these.
Mental model: "VPC is the building. EC2 is the rooms. S3 is the warehouse next door. IAM is the keycard system."
🎯 Practice Questions
Show Answer
S3 → file cabinet — drop in objects, retrieve them. No structure beyond keys.
IAM → keycard system — controls who can enter which rooms.
VPC → gated community — the whole neighborhood + which cars can enter, with internal streets (subnets) and gates (security groups).
i-0a1b2c3d, vpc-456, and arn:aws:iam::123:user/deploy in a CloudFormation log. What is each, and which AWS service?How to explain to students
More students quit AWS over a surprise bill than for any technical reason. Spend 30 minutes locking down billing before spinning up a single resource: enable MFA on root, create an IAM user for daily work, set a billing alarm at $5, and confirm Free Tier is active. This is non-negotiable.
Pick a region close to you (latency) and to your students (compliance). For Pakistan-based learners, me-central-1 (UAE) or ap-south-1 (Mumbai) are the lowest latency. For free-tier learning, us-east-1 often has the broadest service availability.
🎯 Practice Questions
Show Answer
1. A billing alarm via CloudWatch + SNS — would have emailed at $5, $25, $100.
2. Free-tier verification — they ran a non-free-tier instance type (e.g.
t3.large instead of t3.micro), or kept resources running 24/7 past the 750-hr/month free quota.3. A "stop on shutdown" plan — left an EC2 + RDS + NAT gateway running. NAT gateway alone is ~$32/month idle.
Honourable mentions: no AWS Budgets, no
aws-nuke teardown script, no daily check-in habit.
How to explain to students
IAM is the most-skipped, most-failed-interview-on AWS topic. The mental model: users are humans, roles are non-humans (an EC2 instance, a Lambda, GitHub Actions). Both can have policies attached — JSON documents listing allowed actions on specific resources. Always grant the minimum permissions to do the job (least privilege).
Anti-pattern: Action: "*", Resource: "*". That's the IAM equivalent of chmod 777 — it works, until it ruins your week.
🎯 Practice Questions
course-uploads — and nothing else.Show Answer
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::course-uploads",
"arn:aws:s3:::course-uploads/*"
]
}]
}Notice two ARNs: the bucket itself (for
ListBucket) and /* for the objects inside (for PutObject). Forgetting ListBucket on the bucket ARN is the most common bug.
"Action": "*". Suggest two specific replacements for two different real-world scenarios (e.g. a CI deploy role, a read-only audit user).How to explain to students
Static = pre-built HTML/CSS/JS files. No server required. Render once, serve forever (until rebuild). Examples: portfolios, marketing sites, React/Vue SPAs after build. AWS path: S3 + CloudFront ($1–2/month).
Dynamic = a server runs code on every request. Examples: REST APIs, server-rendered apps, anything with a database. AWS path: Elastic Beanstalk, ECS, or EC2 ($10+/month).
Many students push static sites onto EC2 because they don't realise S3 + CloudFront is faster, cheaper, and infinitely more scalable. Always ask: "Does this need a runtime, or just files?"
🎯 Practice Questions
Show Answer
1. Cost: EC2 t3.micro = ~$8/mo running 24/7. S3 + CloudFront for a low-traffic portfolio = under $1/mo.
2. Operational burden: EC2 needs OS patches, restarts, certificate management, security-group tuning. S3 + CloudFront is fully managed — zero ops.
3. Performance + scale: EC2 serves from one region. CloudFront caches at 400+ edge locations globally — your portfolio loads in 50ms in Karachi and Toronto.
The only reason to use EC2 for a static site is if your hosting platform requires it (rare). Otherwise, S3 + CloudFront wins on every axis.
How to explain to students
The architecture is simple: S3 stores your files. CloudFront is the CDN that caches them at 400+ edge locations and adds HTTPS. Route 53 points your custom domain at CloudFront. Total cost for a typical portfolio: under $2/month.
Common mistake: students enable "S3 static website hosting" directly and skip CloudFront. That gives you HTTP-only and no CDN. Always front S3 with CloudFront — it's free up to 1 TB/month outbound on most regions.
🎯 Practice Questions
us-east-1 (N. Virginia), even if your S3 bucket is in me-central-1?Show Answer
us-east-1 by historical AWS design. CloudFront only reads ACM certificates from us-east-1.Your S3 bucket can live in any region — CloudFront pulls from it via signed requests regardless. But if you request your cert in
me-central-1, CloudFront simply won't see it. This is one of the most common day-1 AWS gotchas.
aws s3 sync, users still see the old version. What command makes CloudFront fetch the new file?How to explain to students
EC2: raw VM. You SSH in, install Node, run pm2 start. Maximum control, maximum maintenance.
ECS Fargate: "run my container, don't bother me with VMs". You write a task definition, AWS runs it.
Elastic Beanstalk: "run my code, handle everything". You upload a zip or a Docker image, AWS does the rest.
For first deploys, Beanstalk is the right answer. For containerised apps, ECS Fargate. For learning + customization, EC2. Anything that says "Kubernetes" can wait — you don't need K8s before your first 100 customers.
🎯 Practice Questions
Show Answer
1. App is already containerised → Fargate runs the same Dockerfile from local dev with no changes.
2. No EC2 fleet to manage — Fargate handles the underlying compute.
3. Per-task pricing scales smoothly from 1 task to 100 without infra rework.
Beanstalk's Docker single-container platform is also fine and slightly simpler to set up — pick it if the team has zero AWS experience and "5 commands to running" is the priority.
myapp-prod.eu-west-1.elasticbeanstalk.com. How do you put it behind app.muzammilbilwani.com with HTTPS?How to explain to students
Rule 1: "Code goes in git, config goes in env vars." Anything that changes between dev and prod (database URLs, API keys, log levels) is environment configuration. Inject at runtime, never hard-code.
For non-secret config: env vars or AWS Parameter Store (free, encrypted-at-rest). For secrets: AWS Secrets Manager (~$0.40/secret/month, supports automatic rotation). Beanstalk and ECS can pull these directly into the running app.
For deployment strategies, AWS gives you rolling by default on Beanstalk and ECS, and blue-green via CodeDeploy or "Swap Environment URLs" on Beanstalk.
🎯 Practice Questions
DB_URL = "postgres://..." in your application source code a bug, even if you only deploy to one environment?Show Answer
Parameter Store is free + encrypted, but rotation is manual. Use it for non-rotating config (feature flags, log levels, public URLs).
Practical default: "Use Parameter Store for everything; promote to Secrets Manager only when you need rotation or cross-account access."
eb swap in 4 steps. What happens to the old environment after a successful swap?process.env.DB_URL on startup. The value is set in Beanstalk env vars. After a deploy, DB_URL is empty inside the container. List two likely causes.How to explain to students
A deployed app is only as good as its recovery story. Two questions to answer for every deploy: (1) when the process crashes, who restarts it? (2) when something breaks, where do I read the logs?
On EC2: systemd or PM2 manage the process. Logs flow to journald or PM2's log files, then forwarded to CloudWatch Logs. On Beanstalk + ECS: AWS handles process management; logs go to CloudWatch automatically. Your job is to make the app log to stdout, not files — AWS captures stdout.
pm2 startup + pm2 save.🎯 Practice Questions
/var/log/myapp.log"?Show Answer
1. Containers are ephemeral. Files inside a container vanish when the container restarts. stdout is captured by the container runtime (Docker / ECS / Beanstalk) and forwarded to a durable log service (CloudWatch).
2. Twelve-factor app: the app shouldn't decide where logs go — that's the platform's job. Decoupling lets you swap log sinks (CloudWatch → Loki → Datadog) without touching code.
3. Multiple instances: 10 EC2 instances writing to 10 separate
/var/log files is a debugging nightmare. stdout → CloudWatch unifies them.
Restart=always). How would you detect that this is happening and alert on it?How to explain to students
AWS error messages are notorious — "User: arn:aws:iam::… is not authorized to perform … because no identity-based policy allows the … action" is a paragraph saying "you forgot a permission." AI is great at translating these into a fix. It's also great at writing the first draft of an IAM policy from a plain-English description.
The trap: AI confidently invents IAM action names that don't exist (s3:GetAllObjects isn't real). Always verify against the AWS docs before merging. And never paste real ARNs that contain account IDs into public AI tools — even though account IDs are technically not secret, they're useful for an attacker.
🎯 Practice Questions
s3:GetAllObjects. You apply it and the deploy fails. Why?Show Answer
s3:GetAllObjects doesn't exist. AI hallucinated a plausible-sounding action name. The real action is s3:GetObject (singular), and to "read everything" you broaden the Resource ARN to arn:aws:s3:::bucket/*, not the action.Verification routine: any unfamiliar IAM action name → search the AWS Service Authorization Reference. If it's not there, the AI invented it.
aws iam simulate-principal-policy command to verify whether user "deploy" can ecs:UpdateService on cluster "prod". Sketch the command.How to explain to students
Walk through this end-to-end on screen. By the end of this project, every student should have a personal https://<name>.com serving a real portfolio. This is the artefact they list on their CV. Insist on a custom domain — cloudfront.net URLs don't impress recruiters.
/index.html, not /* — saves on the free tier limit.Sample quiz questions (interactive)
Fill-in-the-command
./dist folder to bucket my-site while deleting orphaned files.E123ABC.How to explain to students
Frame this as a real internship task: "Your manager: 'We need this API live behind a custom domain by Friday. Use Beanstalk. Make sure it has HTTPS, env vars for the database, and a working healthcheck.'" This forces them to integrate everything from the prior modules into one shipping artefact.
📋 Assignment Requirements
- Pick (or write) a Node.js/Python/Go REST API with at least 3 endpoints, including
/healthz - Provision a free-tier Postgres on AWS RDS (or Aurora Serverless v2 for zero-cost-at-rest)
- Deploy the app via Elastic Beanstalk on a t3.small (one instance is fine)
- Pass
DB_URLvia Beanstalk env vars or Parameter Store — never hard-coded - Configure healthcheck path =
/healthzin Beanstalk - Attach a custom subdomain (
api.yourname.com) via Route 53 alias to Beanstalk's CNAME - Provision a free TLS cert via ACM and attach to the Beanstalk load balancer (HTTPS only, redirect HTTP → HTTPS)
- Logs from the app must appear in CloudWatch Logs
- The app must restart automatically when it crashes (Beanstalk default)
- Document the deploy in a 1-page README — architecture diagram + cost breakdown + how to redeploy
- Bonus: GitHub Actions workflow that runs
eb deployon push tomainvia OIDC (no long-lived AWS keys) - Bonus: Tear-down script that removes every resource you created