{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::acme-uploads/avatars/*"
}]
}
AWS for Full-stack Engineers
draftedIAM, VPC, compute (EC2/ECS/Lambda), ALB/API Gateway, S3/CloudFront, RDS/Aurora, SQS/SNS, observability — theo tình huống phỏng vấn cho một app Node/Next.js.
0/64 rated · mastery 0%
Bài học
12 bài · ~152 phút đọc. Học theo thứ tự, rồi làm câu hỏi.- 01~15 phút· 5 câuverify
IAM: user, group, role, STS và credentials cho workload
Principal là gì, vì sao role + STS thay cho access key dài hạn, trust policy khác permissions policy thế nào, least privilege theo đúng resource type (bug ListBucket kinh điển), và cách ECS/EKS/EC2 lấy credential an toàn qua container endpoint, Pod Identity/IRSA và IMDSv2. Các policy được chạy thật qua IAM simulator local.
- 02~12 phút· 4 câuverify
Policy evaluation, Organizations và guardrails
IAM quyết định Allow/Deny theo thứ tự nào khi có identity policy, resource policy, SCP/RCP, permission boundary và session policy; cross-account cần gì ở hai phía; OIDC federation thay access key trong CI; landing zone nhiều account cho team 30 người; và giờ đầu tiên khi một access key admin bị lộ. Mọi case evaluation chạy thật qua simulator local.
- 03~12 phút· 7 câuverify
VPC: subnet, routing, NAT, Security Group và VPC endpoint
Subnet public hay private do route table quyết định, NAT Gateway cho đi ra mà không cho vào (và vì sao nó hay là dòng đắt nhất hoá đơn), Security Group stateful vs NACL stateless, gateway vs interface endpoint, thiết kế VPC 3 AZ có tính toán CIDR thật, vì sao Lambda trong public subnet không ra được internet, và phí public IPv4 từ 2024.
- 04~11 phút· 4 câuverify
Chọn compute: EC2 + ASG, ECS Fargate, Lambda, EKS
Mỗi lựa chọn compute đổi gì lấy gì (ai vận hành cái gì, scale thế nào, trả tiền theo gì), shared responsibility dịch chuyển ra sao từ EC2 sang Fargate sang Lambda, Auto Scaling Group và target tracking hoạt động thế nào, và khi nào không nên serverless-first, kèm phép tính break-even Lambda vs Fargate chạy thật.
- 05~12 phút· 6 câuverify
Lambda: execution environment, cold start, concurrency và limits
Vòng đời execution environment (INIT, INVOKE, SHUTDOWN) và vì sao code ngoài handler chạy một lần, cold start của Node gồm những gì, concurrency = RPS × duration, reserved vs provisioned concurrency, connection storm tới Postgres (đo thật: 100 invocation để lại 99 kết nối), các limit cắn app Next.js, p99 SSR và vòng lặp S3 trigger đốt tiền.
- 06~12 phút· 6 câuverify
ALB, NLB, API Gateway và deploy không lỗi trên ECS
Chọn ALB, NLB hay API Gateway (REST/HTTP) trước một backend Node; vì sao task ECS fail health check rồi restart vòng lặp (đo thật: app bind 127.0.0.1); 502 khi deploy do SIGTERM, deregistration delay và keep-alive (đo thật trên Node 24, gồm keepAliveTimeoutBuffer mới); chạy migration như one-off task; và lớp real-time Socket.IO 50k kết nối.
- 07~12 phút· 6 câuverify
S3 và CloudFront: upload, consistency, OAC và storage class
Presigned PUT vs presigned POST (đo thật trên MinIO: PUT không giới hạn được size và mặc định không ký Content-Type), strong consistency và conditional writes chống lost update, CloudFront cho Next.js (behavior, cache, OAC), vì sao OAC trả 403 cho mọi object, storage class và lifecycle, và pipeline upload + thumbnail an toàn cho app multi-tenant.
- 08~12 phút· 5 câuverify
RDS, Aurora, DynamoDB và ElastiCache
Multi-AZ (availability) khác read replica (scale đọc) thế nào và ngoại lệ Multi-AZ DB cluster; kiến trúc Aurora tách compute/storage; vì sao writer failover vài chục giây mà app lỗi vài phút (đo thật: pool không timeout treo vô hạn, có timeout lỗi trong 2 s); chọn DynamoDB hay Aurora theo access pattern (key design chạy thật trên DynamoDB Local); và ElastiCache cho app Node.
- 09~13 phút· 7 câuverify
SQS, SNS, EventBridge và MSK
Visibility timeout và vì sao SQS là at-least-once (đo thật trên ElasticMQ: một message bị xử lý 3 lần rồi vào DLQ), heartbeat bằng ChangeMessageVisibility, standard vs FIFO (dedup và head-of-line theo group), bug charge hai lần của SQS → Lambda và cách sửa bằng partial batch response + idempotency (DynamoDB Local), backlog/backpressure, SNS fan-out vs EventBridge, và khi nào giữ Kafka bằng MSK.
- 10~13 phút· 4 câuverify
Secrets, KMS và Cognito
Secrets Manager hay Parameter Store cho DB password và config, rotation không làm rớt kết nối (đo thật: single-user rotation làm pod đang cache lỗi auth, alternating-users thì không), KMS và envelope encryption (chạy thật trên LocalStack, gồm encryption context), key policy là cửa chính, thiết kế quản lý secret cho 15 service × 3 môi trường, và Cognito user pool/identity pool cho B2B2C kèm verify JWT đúng cách.
- 11~13 phút· 4 câuverify
Observability, Route 53, DR và Well-Architected
CloudWatch Logs/Metrics/Alarms cho service Node trên ECS, Embedded Metric Format và vì sao dimension userId làm hoá đơn bùng nổ (tính thật: 16 triệu metric), X-Ray và OpenTelemetry (ADOT); Route 53 routing policy và vì sao failover bằng DNS chậm hơn trên giấy; bốn chiến lược DR theo RTO/RPO và chọn cho e-commerce RTO 1h/RPO 5 phút; review một workload theo Well-Architected.
- 12~13 phút· 6 câuverify
Cost và kiến trúc tham chiếu cho platform multi-tenant
Điều tra hoá đơn tăng gấp đôi theo service → usage type → ngày (chạy thật trên dữ liệu mẫu), kế hoạch cắt 30% mà không giảm reliability và cách chọn mức cam kết Savings Plans (commit theo đáy, không theo trung bình), kiến trúc AWS cho platform B2B2C multi-tenant với lý do từng lựa chọn, strangler-fig migration bằng ALB weighted target group, và cách trả lời các câu CV khi chưa vận hành AWS production.
Tóm tắt & cheat sheet của track
TL;DR
- Phỏng vấn AWS cho full-stack không phải đề thi chứng chỉ: interviewer muốn nghe bạn deploy một app Node/Next.js thật — traffic đi qua đâu, secret nằm ở đâu, cái gì chết thì hệ thống sống sót thế nào, và hoá đơn cuối tháng bao nhiêu.
- 5 trục phải nói trôi chảy: IAM (ai được gọi API nào — role + STS, least privilege, thứ tự evaluate policy), VPC (public/private subnet, NAT, SG vs NACL, VPC endpoint), compute (ECS/Fargate vs Lambda vs EKS vs EC2), data (RDS/Aurora Multi-AZ vs read replica, DynamoDB, ElastiCache, S3), integration (SQS/SNS/EventBridge, visibility timeout, DLQ).
- Mọi câu trả lời tốt đều có 3 lớp: cơ chế (nó hoạt động thế nào) → failure mode (nó hỏng thế nào) → cost/ops (nó tốn bao nhiêu, ai vận hành).
- Con số (limit, giá, quota) thay đổi liên tục — nói con số kèm "khoảng / theo docs hiện tại", và luôn kiểm tra Service Quotas trước khi thiết kế.
Khái niệm cốt lõi
| Khái niệm | Một câu | Ví dụ ngắn |
|---|---|---|
| IAM role + STS | Identity không có long-term key; ai được phép AssumeRole sẽ nhận temporary credentials | ECS task role cho phép task đọc đúng 1 bucket, không cần access key trong .env |
| Policy evaluation | Mặc định deny → explicit Deny thắng tất cả → cần ít nhất một Allow, và mọi "trần" (SCP, permission boundary, session policy) đều phải cho phép | SCP chặn ap-southeast-1 thì admin cũng không tạo được EC2 ở region đó |
| Public vs private subnet | Public = route table có 0.0.0.0/0 → IGW; private thì không | ALB ở public subnet, ECS task + RDS ở private subnet |
| NAT Gateway | Cho private subnet gọi ra internet, không cho gọi vào; tính tiền theo giờ và theo GB | Task gọi Stripe API qua NAT; kéo image ECR qua NAT → hoá đơn data processing tăng vọt |
| Security Group vs NACL | SG: stateful, chỉ allow, gắn ENI, reference được SG khác. NACL: stateless, có deny, gắn subnet, rule có thứ tự | RDS SG chỉ allow 5432 từ sg-app |
| VPC endpoint | Đi tới AWS service bằng mạng nội bộ; Gateway endpoint (S3, DynamoDB) miễn phí, Interface endpoint (PrivateLink) tính theo giờ + GB | S3 gateway endpoint cắt phí NAT cho upload/download |
| Lambda cold start | Lần đầu (hoặc khi scale out) phải tạo execution environment + chạy init code | Next.js SSR trên Lambda: request đầu sau khi idle chậm hơn vài trăm ms tới vài giây |
| Multi-AZ vs read replica | Multi-AZ = availability (standby đồng bộ, failover tự động). Read replica = scale đọc (async, có lag) | Aurora: replica vừa là failover target vừa phục vụ đọc |
| SQS visibility timeout | Message đang được xử lý bị ẩn trong khoảng này; hết giờ mà chưa delete → message hiện lại → xử lý lần hai | Lambda timeout 60s nhưng visibility 30s → duplicate |
| Presigned URL | URL tạm thời ký bằng credential của bạn, cho client upload/download S3 trực tiếp | Browser PUT ảnh 20 MB thẳng lên S3, API server không phải stream file |
Cơ chế hoạt động — một app Next.js + Node API trên AWS
IAM policy evaluation (trong một account, rút gọn):
(simplified) Nhánh "Resource-based policy Allow → ALLOW" chỉ bỏ qua identity policy khi resource policy nêu đích danh role session principal (ARN
assumed-role/...); grant cho role ARN vẫn cần identity policy cho phép.
Cross-account: cần cả hai phía cho phép — identity policy ở account gọi và resource policy (hoặc trust policy của role) ở account đích. Chi tiết edge case (resource policy grant trực tiếp cho role session, permission boundary) xem docs "Policy evaluation logic".
Trade-offs
| Lựa chọn | Hợp khi | Không hợp khi | Chi phí vận hành |
|---|---|---|---|
| Lambda | Traffic đột biến / thưa, event-driven (S3, SQS), job ngắn | Request dài (> 15 phút), WebSocket giữ lâu, cần connection pool ổn định, latency p99 nhạy cold start | Thấp nhất; nhưng debug phân tán, quota concurrency |
| ECS Fargate | Web/API container chạy liên tục, Socket.IO, team không muốn quản node | Cần GPU/daemonset/tuỳ biến kernel; workload rất lớn thì EC2 rẻ hơn | Thấp–vừa |
| EKS | Đã có chuẩn Kubernetes, multi-cloud, nhiều team, cần ecosystem (Argo, operators) | Team nhỏ, 3–5 service | Cao (upgrade cluster, add-on, networking) |
| EC2 + ASG | Cần kiểm soát OS, workload ổn định dùng Savings Plans | Muốn deploy nhanh, ít ops | Cao nhất (patch, AMI) |
| ALB | HTTP/HTTPS, route theo host/path, WebSocket, OIDC auth | Non-HTTP, cần IP tĩnh | Theo giờ + LCU |
| NLB | TCP/UDP/TLS, IP tĩnh, latency thấp, PrivateLink | Cần route L7 | Theo giờ + NLCU |
| API Gateway | API cho Lambda, cần throttling/usage plan/API key, auth tích hợp | Payload lớn, request dài, traffic rất cao ổn định (giá per-request) | Theo request |
| RDS/Aurora | Dữ liệu quan hệ, transaction, query linh hoạt | Access pattern key-value ở quy mô cực lớn | Vừa |
| DynamoDB | Access pattern biết trước, key-value, scale gần như vô hạn | Ad-hoc query, join, báo cáo | Thấp |
| SQS | Work queue, buffer, retry + DLQ | Cần replay, nhiều consumer đọc cùng stream | Rất thấp |
| SNS / EventBridge | Fan-out (SNS) / route theo nội dung event, SaaS integration, scheduler (EventBridge) | Cần ordering nghiêm ngặt + replay dài hạn (→ Kinesis/MSK) | Thấp |
Pitfalls
- Nhét access key vào
.envcủa container thay vì dùng task role / instance profile / IRSA / Pod Identity. - Policy
"Resource": "*"và"Action": "s3:*""cho chạy được đã" — rồi không bao giờ siết lại. - Đặt RDS ở public subnet với
0.0.0.0/0:5432để "debug nhanh". - Quên NAT Gateway data processing: kéo image ECR, gọi S3 qua NAT thay vì VPC endpoint → hoá đơn lớn bất ngờ. NAT Gateway nên có một cái mỗi AZ nếu cần HA (và traffic cross-AZ cũng tốn tiền).
- Lambda mở DB connection trong handler → connection storm khi scale; không dùng RDS Proxy.
- SQS visibility timeout ngắn hơn thời gian xử lý → duplicate; không có DLQ → poison message lặp vô hạn.
- Nghĩ "Multi-AZ = scale đọc" (sai với RDS Multi-AZ instance: standby không phục vụ đọc).
- Bucket S3 public để CloudFront đọc — dùng OAC và bucket private.
- Không đặt budget alarm và không tag tài nguyên → không biết tiền đi đâu.
Cheat sheet
- Người/CI dùng Identity Center / OIDC federation (GitHub Actions →
AssumeRoleWithWebIdentity), workload dùng role. Không có long-term key. - Explicit Deny > mọi thứ. SCP không cấp quyền, chỉ đặt trần.
- Private subnet đi ra: NAT GW (tốn tiền) hoặc VPC endpoint (S3/DynamoDB gateway: miễn phí).
- SG reference SG:
sg-rdsallow 5432 từsg-app— không dùng CIDR. - S3: strong read-after-write consistency (từ 12/2020). Upload lớn → presigned URL + multipart.
- CloudFront → S3: OAC (OAI là legacy).
- Lambda + RDS → RDS Proxy; tạo client ngoài handler.
- SQS: visibility timeout ≥ ~6× function timeout khi dùng Lambda event source (khuyến nghị của AWS); DLQ với
maxReceiveCount(≥ 5 với Lambda); consumer phải idempotent (at-least-once). Message tối đa 1 MiB (trước đây 256 KiB) — lớn hơn thì lưu S3, gửi pointer. - Multi-AZ = HA; read replica = scale đọc; Aurora Global Database / cross-region replica = DR.
- DR theo chi phí tăng dần: backup & restore → pilot light → warm standby → multi-site active/active.
- Well-Architected: 6 pillars — Operational Excellence, Security, Reliability, Performance Efficiency, Cost Optimization, Sustainability.
References
- IAM — Policy evaluation logic ↗
- IAM — Security best practices ↗
- Amazon VPC — How Amazon VPC works ↗
- AWS Lambda — Quotas ↗
- AWS Lambda — Understanding the execution environment lifecycle ↗
- Amazon SQS — Visibility timeout ↗
- Amazon S3 — Data consistency model ↗
- Amazon CloudFront — Restricting access to an Amazon S3 origin (OAC) ↗
- Amazon RDS — Multi-AZ deployments ↗
- Amazon RDS Proxy ↗
- AWS Well-Architected Framework ↗
- Disaster recovery of workloads on AWS (whitepaper) ↗
Interview Questions
Showing 64 / 64
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
const s3 = new S3Client({});
export async function createUploadUrl(tenantId: string, fileType: string) {
const key = `uploads/${tenantId}/${crypto.randomUUID()}`;
const cmd = new PutObjectCommand({ Bucket: process.env.BUCKET!, Key: key, ContentType: fileType });
return { key, url: await getSignedUrl(s3, cmd, { expiresIn: 300 }) };
}
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": "arn:aws:s3:::acme-reports/*"
}]
}
500 RPS × 0.2 s = 100 concurrent environments
500 RPS × 3 s (DB slow!) = 1,500 → vượt quota 1,000 mặc định → throttling
import { Pool } from "pg";
export const handler = async (event: any) => {
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 10 });
const { rows } = await pool.query("SELECT * FROM products WHERE id = $1", [event.pathParameters.id]);
return { statusCode: 200, body: JSON.stringify(rows[0]) };
};
# serverless / SAM-ish config
ChargeWorker:
Timeout: 60 # seconds
Events:
Queue:
Type: SQS
BatchSize: 10
PaymentsQueue:
VisibilityTimeout: 30 # seconds
# no RedrivePolicy
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Service": "cloudfront.amazonaws.com" },
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::acme-web",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EDFDVBD6EXAMPLE"
}
}
}]
}
Lambda: VpcConfig subnets = [subnet-pub-a, subnet-pub-b] # route 0.0.0.0/0 -> igw-123
SecurityGroup sg-lambda: outbound all
No NAT Gateway in the VPC.
const server = app.listen(3000);
server.keepAliveTimeout = 65_000; // > ALB idle timeout (60s)
server.headersTimeout = 66_000;
process.on("SIGTERM", () => server.close(() => process.exit(0)));