Amazon EC2
Virtual machines. You pick CPU/memory/network, you own the OS, you patch it, you scale it. Everything more managed (Lambda, Fargate, App Runner) is a trade of control for operational load.
Instance families
The letter tells you what it’s tuned for; the number is the generation; the suffix is the chip.
| Family | Tuned for | Typical use |
|---|---|---|
t (t4g, t3) |
burstable, cheap | dev boxes, low-traffic services |
m (m7g, m7i) |
balanced | general web/app servers |
c (c7g, c7i) |
compute | CPU-bound APIs, batch, encoding |
r / x |
memory | caches, in-memory DBs, big pandas jobs |
i / d |
local NVMe storage | high-IOPS data stores |
p / g / inf / trn |
GPU / accelerators | model training (p, trn), inference (g, inf) |
Suffix g = Graviton (AWS ARM). Typically ~20% cheaper for similar performance on most Python workloads. The catch is any dependency with x86-only native wheels — check before committing.
Burstable instances and the CPU credit trap
t-family instances earn CPU credits while idle and spend them when busy. Run above the baseline long enough and you exhaust credits, then either you’re throttled hard (standard mode) or silently billed for surplus (unlimited mode, the default on t3/t4g).
This is a classic production surprise: a service that was fine for weeks degrades badly under sustained load, and CPU metrics look “fine” because you’re being throttled rather than saturated. Watch CPUCreditBalance. If a workload has a steady floor of CPU use, it does not belong on t.
Purchasing models
| Model | Discount vs on-demand | Commitment |
|---|---|---|
| On-demand | - | none |
| Savings Plans / Reserved | up to ~72% | 1 or 3 years |
| Spot | up to ~90% | can be reclaimed with a 2-minute warning |
| Dedicated host | premium | licensing/compliance |
Spot is the interesting one in interviews: it’s ideal for fault-tolerant, checkpointed, restartable work — batch, CI runners, ML training with checkpointing, stateless workers behind a queue. It is wrong for anything that can’t lose a node abruptly. The 2-minute interruption notice arrives via instance metadata or EventBridge; a well-built consumer drains and checkpoints on it.
Storage
- EBS — network-attached block storage, persists independently of the instance.
gp3is the default choice: IOPS and throughput are provisioned separately from size, unlikegp2where they were tied to volume size.io2for high-durability high-IOPS databases. - Instance store — physical NVMe on the host. Very fast, and wiped when the instance stops or the host fails. Only for scratch, caches, or replicated data.
The trap: “I stopped the instance to save money and lost the data” — that’s instance store.
Networking
An instance lives in a subnet in a VPC. Reachability is governed by two layers:
| Scope | Stateful? | Rules | |
|---|---|---|---|
| Security group | instance (ENI) | yes — return traffic auto-allowed | allow only |
| Network ACL | subnet | no — must allow both directions | allow and deny |
Most real-world “why can’t it connect” answers are: security group missing an inbound rule, no route to an internet/NAT gateway, or a NACL blocking the ephemeral return port. Security groups can reference other security groups as the source — that’s the clean way to say “only the app tier may reach the DB tier”, rather than hardcoding CIDRs.
Scaling
An Auto Scaling Group keeps N healthy instances across AZs, replaces failed ones, and scales on a policy (target tracking on CPU or on ALB request count per target is the common setup). Pair it with an ALB, put the ALB health check as the ASG health check source, and instances that stop serving traffic get replaced automatically.
Key mechanics worth naming: launch templates (versioned instance definition), warm-up / cooldown (stops thrash), lifecycle hooks (drain connections before termination), and mixed instance policies (blend on-demand and spot in one ASG).
Metadata service — IMDSv2
Instances read their own identity and credentials from 169.254.169.254. Enforce IMDSv2 (session-token based). IMDSv1 was a plain GET, which meant an SSRF bug in your app could be pivoted into stealing the instance role’s credentials — the mechanism behind several well-known breaches.
TOKEN=$(curl -sX PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 300")
curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/iam/security-credentials/
Never put long-lived access keys on an instance. Attach an instance profile (IAM role); the SDK picks the credentials up automatically and rotates them.
When not to use EC2
- Request/response workloads with spiky or low traffic — Lambda removes the idle cost and the patching.
- Containerized services — Fargate or ECS/EKS; you stop managing hosts.
- You just want a database/cache — RDS/Aurora/ElastiCache, not EC2 with Postgres installed by hand.
Reach for EC2 when you need OS-level control, specific hardware (GPU, local NVMe, huge memory), licensing constraints, or a lift-and-shift of something that assumes a real machine.
Interview angle
- “EC2 vs Lambda vs Fargate — how do you choose?” — by request shape and operational appetite. Spiky/event-driven and short: Lambda. Containerized, steady, want no host management: Fargate. Need OS control, GPUs, local NVMe, or sustained high load where per-invocation pricing loses: EC2. Cost crosses over as utilization rises — Lambda is cheapest when mostly idle, EC2/Fargate when mostly busy.
- “When would you use Spot?” — fault-tolerant, interruptible, checkpointed work: batch, CI, ML training, queue workers. Handle the 2-minute interruption notice by draining and checkpointing. Never for a stateful singleton.
- “Security group vs NACL?” — SG is stateful and instance-level, allow-rules only; NACL is stateless and subnet-level, supports deny. Stateless is why NACLs bite you on ephemeral return ports. SGs can reference other SGs, which is how you express tier-to-tier access.
- “How does an app on EC2 get AWS credentials?” — instance profile / IAM role via IMDS, rotated automatically. Enforce IMDSv2 so an SSRF can’t be turned into credential theft. Static keys on disk are the wrong answer.
- “Instance stopped and the data vanished — why?” — it was on instance store, not EBS. EBS persists across stop/start; instance store does not survive stop or host failure.
- “Your
t3.smallservice degrades after a few weeks of growth. Why?” — CPU credit exhaustion. Burstable instances throttle (or bill surplus) once the baseline is exceeded for long enough. Move tom/cwhen the load has a steady floor.