Tổng hợp 136 câu hỏi phỏng vấn System Design kèm đáp án chi tiết, song ngữ Việt–Anh — sắp xếp từ cơ bản đến nâng cao. Ôn luyện miễn phí, tự động lưu tiến độ.
Có nhiều tầng caching cho frontend application, mỗi tầng phục vụ mục đích khác nhau. Tầng trình duyệt dùng HTTP headers như Cache-Control và ETag để cache tài nguyên tĩnh (JS, CSS, images), giúp giảm network requests khi user quay lại trang. Tầng ứng dụng…
CAP Theorem phát biểu rằng một hệ thống phân tán chỉ có thể đảm bảo đồng thời tối đa 2 trong 3 thuộc tính: Consistency (tính nhất quán – mọi node trả về dữ liệu mới nhất), Availability (tính sẵn sàng – mọi request đều…
ACID (Atomicity, Consistency, Isolation, Durability) là tập hợp thuộc tính đảm bảo transaction trong RDBMS luôn đáng tin cậy: toàn bộ transaction thành công hoặc rollback hoàn toàn, dữ liệu luôn hợp lệ, các transaction cô lập nhau, và dữ liệu đã commit không bao…
Vertical Scaling (scale up) là nâng cấp phần cứng của một máy chủ duy nhất: tăng CPU, RAM, SSD – đơn giản, không cần thay đổi code, nhưng bị giới hạn ở cấu hình phần cứng mạnh nhất và tạo ra single point of failure.…
Load Balancer là thành phần đứng giữa client và các server, phân phối incoming requests để không có server nào bị quá tải, đồng thời tăng availability bằng cách redirect traffic khi có server bị lỗi. Các thuật toán phổ biến: Round Robin (luân phiên…
CDN (Content Delivery Network) là mạng lưới các server phân tán địa lý, lưu trữ bản sao (cache) của static content (hình ảnh, JS, CSS, video) tại các edge nodes gần người dùng nhất. Khi user request một file, CDN route request đến edge node…
Forward proxy đứng trước client và đại diện client gửi request ra ngoài — client biết có proxy, còn server bên ngoài không biết request thực sự xuất phát từ đâu. Dùng để vượt giới hạn địa lý, giấu IP client, lọc nội dung trong…
Latency là thời gian để hoàn thành một request đơn lẻ (đo bằng ms) – thấp là tốt, thể hiện độ nhanh nhạy của hệ thống. Throughput là số lượng requests/operations hệ thống xử lý được trong một đơn vị thời gian (requests/second, transactions/second) –…
Các mô hình consistency phổ biến: - Strong Consistency (Linearizability): sau khi write thành công, mọi read sau đó đều thấy giá trị mới nhất – dễ lập trình nhất nhưng latency cao nhất vì cần coordination giữa các node. - Eventual Consistency: dữ liệu…
Sharding là kỹ thuật chia dữ liệu của một database thành nhiều phần nhỏ hơn (shards), mỗi shard nằm trên một database server riêng, cho phép scale ngang khi dữ liệu vượt quá capacity của một server. Các chiến lược: - Range-based sharding: chia theo…
Read Replica là bản sao của primary database, chỉ nhận read queries trong khi primary (master) nhận tất cả write queries – asynchronous replication đồng bộ dữ liệu từ primary sang replica. Lợi ích: giảm read load trên primary (80-90% workload thường là read), cho…
Rate Limiting là kỹ thuật kiểm soát tần suất request từ một client/IP/user để bảo vệ hệ thống khỏi abuse, DDoS, và đảm bảo fair usage. Các thuật toán: - Token Bucket – bucket chứa tokens, mỗi request tiêu 1 token, tokens được refill theo…
Connection Pooling duy trì sẵn một pool các kết nối đã được khởi tạo; application lấy connection từ pool và trả lại sau khi dùng xong — thay vì mở/đóng từng kết nối mới với overhead TCP handshake + authentication (20-100ms/lần). Lợi ích: giảm latency…
CQRS (Command Query Responsibility Segregation) là pattern tách biệt hoàn toàn model đọc (Query) và model ghi (Command) – thay vì một model dùng cho cả CRUD. Command side xử lý mutations và thường dùng domain model phức tạp; Query side tối ưu cho read…
Event Sourcing là pattern lưu trữ mọi thay đổi trạng thái của application dưới dạng chuỗi immutable events thay vì chỉ lưu trạng thái hiện tại – giống như transaction log của bank hơn là số dư hiện tại. Ví dụ: thay vì lưu account.balance…
Stateful services yêu cầu externalize state; các lựa chọn chính là Sticky Sessions, Externalized Store (Redis), và JWT — mỗi cách có trade-off riêng về complexity và failover. - Sticky Sessions: load balancer route cùng user về cùng server dựa trên cookie — đơn giản…
Monolith là toàn bộ application được deploy như một unit duy nhất – đơn giản để develop, test, deploy ban đầu, không có network overhead giữa components. Microservices chia application thành nhiều services nhỏ, độc lập, mỗi service có database riêng và được deploy độc…
API Gateway là single entry point cho tất cả client requests đến microservices – hoạt động như reverse proxy với nhiều tính năng bổ sung. Vai trò: routing (forward request đến đúng service), authentication/authorization (centralized auth thay vì mỗi service tự verify), rate limiting, SSL…
Service Mesh là tầng hạ tầng lo phần giao tiếp giữa các service trong kiến trúc microservice, thường hiện thực bằng sidecar proxy — mỗi pod của service có thêm một container proxy đi kèm. Nó cung cấp sẵn: mTLS để mã hoá liên lạc…
Circuit Breaker là pattern bảo vệ hệ thống khỏi cascading failures khi một dependency bị lỗi – lấy cảm hứng từ cầu dao điện. Hoạt động qua 3 states: Closed (hoạt động bình thường, theo dõi failure rate), Open (sau khi failure rate vượt threshold,…
Trong microservices, mỗi service có database riêng, nên không thể dùng distributed transactions (2PC) – quá phức tạp và tạo tight coupling. Saga Pattern giải quyết bằng cách chia distributed transaction thành chuỗi local transactions, mỗi bước publish event; nếu một bước fail, thực hiện…
Event-Driven Architecture (EDA) là kiến trúc nơi các components giao tiếp với nhau qua events (notifications về điều gì đó đã xảy ra) thay vì direct API calls. Producer emit events mà không biết consumer là ai; consumer subscribe và xử lý events async –…
RabbitMQ là traditional message broker (queue-based): messages được push đến consumers, sau khi consumer acknowledge thì message bị xoá, hỗ trợ nhiều messaging patterns (pub/sub, point-to-point, routing với exchanges), tốt cho task queues và RPC. Kafka là distributed event log (log-based): messages được append vào…
Serverless (FaaS – Function as a Service) là mô hình cloud computing nơi developer chỉ viết code (functions), không quản lý server infrastructure; provider tự động provision, scale, và bill theo actual invocations (pay-per-use). AWS Lambda, Google Cloud Functions, Vercel Functions là các giải pháp…
SQL (Relational DB): dùng khi cần ACID transactions (tài chính, đặt hàng), data có structure rõ ràng và ổn định, cần complex queries với JOINs. PostgreSQL, MySQL là lựa chọn mặc định tốt cho hầu hết applications. NoSQL chia thành nhiều loại: - Document DB…
Index là data structure (thường là B-Tree) cho phép database tìm kiếm records nhanh mà không cần full table scan – giảm query time từ O(n) xuống O(log n). - B-Tree Index: phổ biến nhất, hỗ trợ equality và range queries (=, <, , BETWEEN,…
Normalization là quá trình tổ chức database để giảm data redundancy và dependency thông qua các Normal Forms (1NF, 2NF, 3NF, BCNF) – chia data thành nhiều tables liên quan, tránh duplicate data. Lợi ích: storage hiệu quả, dễ maintain consistency khi update (chỉ cần…
Blob Storage là storage chuyên biệt cho unstructured data (images, video, docs) — dùng thay vì database để tránh làm DB backup lớn và ảnh hưởng query performance. AWS S3, Google Cloud Storage, Azure Blob Storage là các giải pháp phổ biến. Pattern đúng: lưu…
Vấn đề với hash(key) % N: khi số node N thay đổi (thêm/bớt 1 server), gần như toàn bộ key bị remap sang node khác → cache miss hàng loạt, rebalance data khổng lồ. Consistent Hashing: đặt cả node và key lên cùng một vòng…
Vấn đề: mạng timeout khiến client không biết request đã thành công chưa → retry → tạo double charge / double order. POST vốn không idempotent. Idempotency key: client sinh một key duy nhất (UUID) cho mỗi thao tác nghiệp vụ và gửi qua header…
Observability = khả năng suy ra trạng thái bên trong hệ thống từ output bên ngoài. Ba trụ cột bổ trợ nhau: - Metrics — số liệu tổng hợp theo thời gian (request/s, p99 latency, error rate, CPU). Rẻ, lưu lâu, dùng cho dashboard +…
Webhook = HTTP callback do server chủ động đẩy tới endpoint của khách khi có event (đảo chiều polling). Kiến trúc gửi tin cậy: - Event vào queue (Kafka/SQS), worker đọc và POST tới URL khách → tách phát sinh event khỏi việc gửi (gửi…
Mục đích không là con số chính xác, mà để chọn kiến trúc đúng tầm (cần shard chưa? cache bao nhiêu? vài server hay vài nghìn?). Phỏng vấn viên đánh giá cách bạn suy luận, không phải số thập phân. Quy trình: 1. Bắt đầu…
Khi cache đầy bộ nhớ, cần bỏ bớt entry để nhận cái mới — chính sách eviction quyết định bỏ cái nào. - LRU (Least Recently Used): bỏ entry lâu nhất chưa được truy cập. Giả định "vừa dùng gần đây thì còn dùng" (temporal…
returnUrl là nơi trình duyệt user quay về; IPN là cuộc gọi server-to-server từ cổng thanh toán. Chỉ IPN mới được dùng để chuyển đơn sang trạng thái đã thanh toán. - returnUrl: user được redirect về sau khi trả tiền. Có thể không bao…
Không có một biện pháp đơn lẻ nào đủ — xếp nhiều lớp, mỗi lớp làm chi phí của bot tăng lên. Lớp chặn trước khi tạo tài khoản: - Rate limit theo IP và theo subnet, ví dụ 5 lượt đăng ký/IP/giờ. Bot dùng…
IPN có thể không tới: server bạn đang deploy, endpoint 500, firewall chặn, hoặc cổng gặp sự cố. Vì vậy không được coi IPN là cơ chế duy nhất — cần một luồng chủ động hỏi lại. Luồng kép (push + pull): 1. Khi tạo…
Điểm mấu chốt: refund là một giao dịch riêng, không phải xoá hay sửa giao dịch cũ. Bản ghi thanh toán gốc phải giữ nguyên để đối soát và kế toán. Mô hình dữ liệu: bảng refunds tham chiếu paymentid, gồm amount, reason, status (requested…
Presigned URL cho client PUT thẳng lên S3, server không phải làm proxy dữ liệu — nhưng đổi lại server mất quyền kiểm tra nội dung tại chỗ. Bù lại bằng hai việc: siết ngay trong chữ ký, và xác nhận sau khi upload. Siết…
Trả lời theo quy mô, đừng nhảy thẳng vào Elasticsearch. Dưới khoảng vài triệu sản phẩm, PostgreSQL làm được cả ba yêu cầu. Tìm không dấu: dùng extension unaccent để bỏ dấu tiếng Việt, và lưu kết quả vào cột sinh sẵn có index, không…
Tách hai khái niệm: audit log ghi lại hành động nghiệp vụ của con người (khác application log dùng để debug). Audit log phải append-only — chỉ thêm, không sửa không xoá. Bảng tối thiểu: Ghi ở đâu: ghi trong cùng transaction với thay đổi…
Nguyên tắc: lưu UTC, chỉ chuyển đổi ở đầu vào/đầu ra. Trong DB dùng timestamptz (Postgres lưu về UTC), API trả ISO 8601 có offset (2026-08-06T14:30:00+07:00), client hiển thị theo múi giờ của người xem bằng Intl.DateTimeFormat. Dùng timestamp (không tz) là lỗi hay gặp…
Hai vấn đề: ghi quá nhiều và đếm sai. Ghi quá nhiều: mỗi lượt xem là một UPDATE vào cùng một dòng. Các request cùng lúc xếp hàng chờ khoá dòng đó, và mỗi lần cập nhật sinh một phiên bản dòng mới (Postgres) làm…
Đừng vẽ kiến trúc ngay. Trình tự được dùng phổ biến gồm 6 bước, mỗi bước có quỹ thời gian riêng: 1. Làm rõ yêu cầu (5-8 phút) — chốt phạm vi: ai dùng, tính năng nào nằm trong scope, tính năng nào bỏ. Xác…
Yêu cầu chức năng trả lời "hệ thống làm được gì": người dùng đăng bài, theo dõi người khác, xem bảng tin. Chúng thành các endpoint và bảng dữ liệu. Yêu cầu phi chức năng trả lời "hệ thống phải chạy tốt tới mức nào":…
Đề bài kiểu "thiết kế Twitter" cố ý mơ hồ — người phỏng vấn muốn xem bạn có tự thu hẹp phạm vi hay không. Bộ câu hỏi nên hỏi: Về phạm vi - Những tính năng nào nằm trong scope buổi này? (đăng bài,…
Các bậc độ lớn cần nhớ (số xấp xỉ, dùng để so sánh chứ không phải để trích dẫn chính xác): Thao tác Thời gian ------ Truy cập L1 cache ~1 ns Truy cập main memory (RAM) ~100 ns Đọc 1 MB tuần tự từ…
Ước lượng theo bậc độ lớn, làm tròn mạnh, nói rõ từng bước khi làm. Bước 1 — QPS. Một ngày có ~86400 giây, làm tròn 100k giây. Giả sử mỗi người ghi 2 bài/ngày: Với tỷ lệ đọc/ghi 100:1 thì đọc trung bình ~20k…
Percentile là ngưỡng mà một tỷ lệ request nhất định nằm dưới nó. p99 = 800 ms nghĩa là 99% request nhanh hơn 800 ms, 1% chậm hơn. Trung bình che giấu phần đuôi. Giả sử 1000 request: 990 request 50 ms, 10 request 5000…
Ba khái niệm xếp theo tầng: - SLI (Service Level Indicator) — chỉ số đo thực tế: tỷ lệ request trả về thành công, p99 latency, tỷ lệ ghi thành công. Đây là con số lấy từ hệ thống. - SLO (Objective) — mục tiêu…
Mục tiêu bước này là chốt API contract giữa client và hệ thống trước khi bàn tới bên trong. Viết 3-5 endpoint chính, mỗi cái một dòng, kèm tham số và giá trị trả về: Những điểm nên chủ động nêu: - Phân trang bằng…
Bước này chốt ba việc: thực thể chính, kiểu lưu trữ, và khoá truy cập. 1. Thực thể và quan hệ. Liệt kê 3-5 bảng cốt lõi với các cột quan trọng, không cần đủ. Với bài news feed: users, posts, follows, feeditems. 2. Chọn…
SPOF là thành phần mà khi nó hỏng thì cả hệ thống hoặc một luồng nghiệp vụ chính dừng hoạt động. Cách rà soát: đi qua từng hộp trên sơ đồ và hỏi "nếu cái này chết bây giờ thì sao". Những chỗ hay bị…
Không đặt timeout nghĩa là chấp nhận chờ vô hạn. Khi service phía dưới treo, mỗi request đang chờ vẫn giữ một thread, một kết nối và một chỗ trong connection pool. Chỉ vài chục giây, pool cạn và service của bạn ngừng phục vụ…
Trả lời theo thứ tự rẻ và nhanh trước, đừng nhảy thẳng vào phân tán: 1. Đo trước: xem CPU, RAM, disk I/O, số connection DB, latency p95. Chưa biết nghẽn ở đâu thì mọi thay đổi đều là đoán. 2. Sửa nút thắt hiển…
Sticky session là cấu hình load balancer luôn đẩy request của cùng một client về đúng một backend, thường bằng cookie do LB phát ra hoặc hash IP nguồn. Vì sao nên tránh: - Tải lệch: một backend hút phải nhóm client nặng thì không…
LB dựa vào health check để quyết định còn gửi request tới backend nào. - Passive (thụ động): quan sát chính lưu lượng thật — backend trả lỗi hoặc timeout liên tiếp quá ngưỡng thì bị đánh dấu hỏng và tạm loại (maxfails / failtimeout…
Đây là replication lag: ghi đi vào primary, đọc lại rơi vào replica chưa kịp áp dụng bản ghi đó. Với replication bất đồng bộ, độ trễ vài chục mili giây là bình thường, nhưng khi replica bận hoặc có một transaction ghi lớn thì…
Nguyên nhân: mỗi instance giữ bộ đếm riêng trong RAM, nên hạn mức bị nhân lên theo số instance — và con số này còn đổi khi autoscaling. Bộ đếm phải nằm ở kho dùng chung, thường là Redis. Token bucket trên Redis cần đọc…
Queue-based load leveling: thay vì để đỉnh tải đập thẳng vào service xử lý, request được đẩy vào hàng đợi và consumer rút ra ở tốc độ ổn định mà hệ thống chịu được. Đỉnh tải biến thành độ trễ chứ không thành lỗi. Hợp…
Chọn metric theo bản chất tải: - Service CPU-bound → CPU utilization. - Service I/O-bound (chờ DB, gọi API ngoài) → CPU gần như đứng yên trong khi đã nghẽn; dùng số request đang xử lý đồng thời hoặc RPS mỗi instance. - Worker đọc…
Vì tổng kết nối tới database là số instance × kích thước pool mỗi instance. Pool 20 với 4 instance là 80 kết nối; với 40 instance thành 800, vượt xa maxconnections mặc định của PostgreSQL (100). Đây là cái bẫy cố hữu khi scale…
Hỏi tỉ lệ đọc/ghi trước khi vẽ kiến trúc, vì hai hướng tối ưu ngược nhau. Đọc-nặng (mạng xã hội, tin tức, sàn thương mại — đọc thường gấp hàng chục tới hàng trăm lần ghi): - Cache nhiều tầng, CDN cho nội dung công…
Làm rõ yêu cầu trước: ai tạo link (nội bộ marketing, không phải public), link có hạn dùng không, thống kê cần real-time hay trễ vài phút. Giả sử 100k link, 5 triệu click/tháng — tức chỉ ~2 click/giây trung bình, đỉnh chiến dịch có…
Làm rõ quy mô: 5 triệu sản phẩm, vài nghìn shop, traffic đọc gấp hàng trăm lần ghi. Đó là lý do tách đường đọc và đường ghi (CQRS ở mức nhẹ, không cần event sourcing). Dữ liệu gốc nằm ở Postgres: Dùng cột path…
Làm rõ trước: khách chỉ xem được shipper của đơn của mình, cần cập nhật mỗi 3-5 giây (không phải 60 lần/giây), và chỉ trong lúc đơn đang giao. Giả sử 20.000 shipper hoạt động, mỗi người ping 5 giây một lần → 4.000 ghi/giây.…
Ba yêu cầu quyết định thiết kế: tin nhắn không mất, thứ tự trong một hội thoại phải ổn định, và người offline vẫn nhận đủ khi mở app. Data model — khoá chính đặt đúng là xong nửa bài: seq là số tăng dần…
Câu trả lời đúng ở quy mô này là "đừng vội fan-out". Với vài trăm nghìn user và mỗi người theo dõi vài trăm nguồn, dựng feed lúc đọc (pull) là đủ và ít thành phần phải vận hành nhất. Data model: Dựng feed lúc…
Chốt: service nghiệp vụ không được biết đang gửi bằng kênh nào. Chúng chỉ phát một sự kiện có ý nghĩa nghiệp vụ; việc chọn kênh, dựng nội dung, giới hạn tần suất nằm ở hệ thống thông báo. Luồng: Data model chính: Chọn kênh:…
Vấn đề đầu tiên phải nêu: UPDATE posts SET views = views + 1 mỗi lượt xem sẽ khoá cùng một dòng — bài viral biến thành điểm nóng và làm chậm cả bảng. Cách làm: đếm ở Redis, ghi xuống DB theo lô. -…
Nguyên tắc mở đầu: file không đi qua API server. Client xin URL ký sẵn (pre-signed URL) rồi upload thẳng lên object storage (S3/GCS/R2). API chỉ cấp quyền và nhận thông báo hoàn tất — nhờ vậy API không bị chiếm băng thông và không…
Làm rõ: bác sĩ có lịch làm việc lặp theo tuần, mỗi ca chia thành slot 15-30 phút, có thể nghỉ đột xuất, và bệnh nhân huỷ khá nhiều. Tải rất thấp (vài chục request/giây) nhưng yêu cầu tính đúng đắn cao — đây là…
Làm rõ quy mô: 5.000 nhân viên, mỗi người 2-4 lần chấm công/ngày → khoảng 20.000 bản ghi/ngày, dồn vào hai khung giờ ngắn. Tổng tải rất nhỏ; phần khó nằm ở tính đúng đắn và quy tắc nghiệp vụ, không ở scale. Data model:…
Hai câu hỏi làm rõ quyết định toàn bộ: giỏ hàng có cần giữ lại sau khi đóng trình duyệt không (có), và khách chưa đăng nhập có được thêm vào giỏ không (có — bắt đăng nhập trước làm giảm chuyển đổi). Lưu ở…
Thường là không. Lời khuyên phổ biến là monolith first: bắt đầu bằng một monolith được module hoá tốt, tách service chỉ khi có lý do cụ thể. Vì sao chưa nên tách: - Ranh giới nghiệp vụ ở giai đoạn đầu chưa ổn định.…
Cắt theo năng lực nghiệp vụ (business capability) / subdomain, không cắt theo tầng kỹ thuật. Bounded context là phạm vi mà một mô hình dữ liệu có nghĩa nhất quán. Ví dụ chữ "Order": - Trong context Bán hàng: Order có giỏ hàng, khuyến…
Database per service: mỗi service sở hữu schema của mình, service khác chỉ truy cập qua API, không đọc/ghi thẳng bảng. Lý do: - Chia sẻ database làm hai service dính chặt vào cấu trúc bảng. Đổi tên một cột là phải phối hợp deploy…
Hai thứ bắt buộc: correlation id và log tập trung. Correlation id (request id): sinh một id duy nhất ở cửa ngõ (gateway hoặc service đầu tiên), gắn vào header, truyền tiếp qua mọi lời gọi xuống dưới và ghi vào mọi dòng log. Để…
Hai lựa chọn chính: API composition hoặc CQRS read model. API composition — một thành phần (gateway/BFF/service tổng hợp) gọi từng service rồi ghép kết quả. - Ưu: đơn giản, dữ liệu luôn mới, không cần hạ tầng thêm. - Nhược: latency = chặng chậm…
Trace là toàn bộ hành trình của một request qua hệ thống. Span là một đoạn công việc trong trace (một lời gọi HTTP, một truy vấn DB, một lần xử lý message) — có tên, thời điểm bắt đầu/kết thúc, thuộc tính, và id…
Vấn đề: instance của service lên xuống liên tục (autoscale, deploy, container chết và được tạo lại) nên IP/port không cố định. Không thể hardcode địa chỉ trong config. Cơ chế chung: mọi instance đăng ký vào một service registry khi khởi động và gửi…