Skip to content
DevRecall
← Roadmap
24

AWS for Full-stack Engineers

drafted

IAM, 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.
  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

  7. 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.

  8. 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.

  9. 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. 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. 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. 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ệmMột câuVí dụ ngắn
IAM role + STSIdentity không có long-term key; ai được phép AssumeRole sẽ nhận temporary credentialsECS task role cho phép task đọc đúng 1 bucket, không cần access key trong .env
Policy evaluationMặ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épSCP chặn ap-southeast-1 thì admin cũng không tạo được EC2 ở region đó
Public vs private subnetPublic = route table có 0.0.0.0/0 → IGW; private thì khôngALB ở public subnet, ECS task + RDS ở private subnet
NAT GatewayCho private subnet gọi ra internet, không cho gọi vào; tính tiền theo giờ và theo GBTask gọi Stripe API qua NAT; kéo image ECR qua NAT → hoá đơn data processing tăng vọt
Security Group vs NACLSG: 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ờ + GBS3 gateway endpoint cắt phí NAT cho upload/download
Lambda cold startLần đầu (hoặc khi scale out) phải tạo execution environment + chạy init codeNext.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 replicaMulti-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 timeoutMessage đ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 haiLambda timeout 60s nhưng visibility 30s → duplicate
Presigned URLURL tạm thời ký bằng credential của bạn, cho client upload/download S3 trực tiếpBrowser 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ọnHợp khiKhông hợp khiChi phí vận hành
LambdaTraffic đột biến / thưa, event-driven (S3, SQS), job ngắnRequest dài (> 15 phút), WebSocket giữ lâu, cần connection pool ổn định, latency p99 nhạy cold startThấp nhất; nhưng debug phân tán, quota concurrency
ECS FargateWeb/API container chạy liên tục, Socket.IO, team không muốn quản nodeCần GPU/daemonset/tuỳ biến kernel; workload rất lớn thì EC2 rẻ hơnThấp–vừa
EKSĐã có chuẩn Kubernetes, multi-cloud, nhiều team, cần ecosystem (Argo, operators)Team nhỏ, 3–5 serviceCao (upgrade cluster, add-on, networking)
EC2 + ASGCần kiểm soát OS, workload ổn định dùng Savings PlansMuốn deploy nhanh, ít opsCao nhất (patch, AMI)
ALBHTTP/HTTPS, route theo host/path, WebSocket, OIDC authNon-HTTP, cần IP tĩnhTheo giờ + LCU
NLBTCP/UDP/TLS, IP tĩnh, latency thấp, PrivateLinkCần route L7Theo giờ + NLCU
API GatewayAPI cho Lambda, cần throttling/usage plan/API key, auth tích hợpPayload lớn, request dài, traffic rất cao ổn định (giá per-request)Theo request
RDS/AuroraDữ liệu quan hệ, transaction, query linh hoạtAccess pattern key-value ở quy mô cực lớnVừa
DynamoDBAccess pattern biết trước, key-value, scale gần như vô hạnAd-hoc query, join, báo cáoThấp
SQSWork queue, buffer, retry + DLQCần replay, nhiều consumer đọc cùng streamRất thấp
SNS / EventBridgeFan-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 .env củ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-rds allow 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.

Personal notes (Notion)

Ghi chú cá nhân — có thể sai hoặc lỗi thời, dùng để tham khảo.

Interview Questions

Showing 64 / 64

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::acme-uploads/avatars/*"
  }]
}
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)));