❓ Q: Tại sao bước đầu tiên phải là Functional Requirements thay vì nhảy vào vẽ sơ đồ ngay?
💡 A: Để thiết lập phạm vi (Scope) và sự đồng thuận với người phỏng vấn. Nếu không có yêu cầu chức năng, bạn sẽ thiết kế một hệ thống thừa thãi hoặc thiếu hụt các tính năng cốt lõi.
❓ Q: Quy tắc “Top 3” trong Functional Requirements là gì?
💡 A: Chỉ chọn ra 3 tính năng quan trọng nhất để thiết kế sâu. Việc liệt kê quá nhiều sẽ làm loãng buổi phỏng vấn và bạn sẽ không đủ thời gian để hoàn thiện thiết kế chi tiết (Deep Dives).
❓ Q: Sự khác biệt giữa một Non-functional Requirement “tốt” và “xấu” là gì?
💡 A: Yêu cầu “xấu” là cảm tính (ví dụ: “hệ thống phải nhanh”). Yêu cầu “tốt” là định lượng được và có ngữ cảnh (ví dụ: “Độ trễ khi tải Newsfeed phải dưới 200ms cho 99% yêu cầu - P99”).
❓ Q: Trong CAP Theorem, tại sao Partition Tolerance thường được coi là mặc định?
💡 A: Vì trong các hệ thống phân tán (Distributed Systems), lỗi mạng giữa các node là điều không thể tránh khỏi. Do đó, bài toán thực tế luôn là chọn giữa Consistency (Nhất quán) hay Availability (Sẵn sàng).
❓ Q: “Actors” và “Resources” giúp ích gì trong việc xác định Core Entities?
💡 A: Actors giúp xác định ai tác động vào hệ thống (User, Admin). Resources là các danh từ cần thiết để thực hiện chức năng (Tweet, Video, Comment). Đây là bộ khung để xây dựng Database Schema sau này.
❓ Q: Tại sao nên sử dụng danh từ số nhiều cho REST API Resources?
💡 A: Đây là tiêu chuẩn ngành (Standard Practice). Ví dụ /v1/users/{id} thể hiện việc truy cập vào một tài nguyên cụ thể trong một tập hợp các người dùng, giúp API rõ ràng và chuyên nghiệp.
❓ Q: Khi nào thì gRPC (RPC) chiếm ưu thế hơn REST trong System Design?
💡 A: Khi thiết kế giao tiếp nội bộ giữa các Service (Service-to-service communication). RPC hiệu quả hơn về hiệu suất và độ trễ nhờ sử dụng giao thức nhị phân (Binary protocol).
❓ Q: Tại sao tuyệt đối không lấy user_id từ Request Body cho các tác vụ nhạy cảm?
💡 A: Để tránh lỗi bảo mật nghiêm trọng. Kẻ tấn công có thể thay đổi user_id trong body để thao tác dữ liệu của người khác. Luôn phải trích xuất user_id từ Authentication Token đã được xác thực ở Header.
❓ Q: Chiến lược “Vẽ theo API” trong High-level Design có lợi ích gì?
💡 A: Giúp thiết kế đi đúng trọng tâm và có logic. Bạn đi qua từng Endpoint (ví dụ: Đăng Tweet → Lưu DB → Đẩy vào Cache), từ đó các thành phần (Components) sẽ tự động xuất hiện trên sơ đồ một cách tự nhiên.
❓ Q: Khi vẽ sơ đồ, tại sao không nên thêm Cache hay Load Balancer ngay từ phút đầu tiên?
💡 A: Để tránh làm phức tạp hóa vấn đề. Hãy tập trung vào luồng dữ liệu cơ bản (Happy Path) trước, sau đó mới thêm các lớp tối ưu ở phần Deep Dives khi thảo luận về khả năng mở rộng (Scalability).
❓ Q: Khi nào Capacity Estimation thực sự mang lại giá trị cho bài phỏng vấn?
💡 A: Khi con số đó dẫn đến một quyết định kỹ thuật cụ thể. Ví dụ: Nếu dữ liệu quá lớn không thể chứa trong 1 ổ đĩa → Cần Sharding. Nếu lượt đọc cao gấp 100 lần lượt ghi → Cần Read Replicas hoặc Caching.
❓ Q: Vị trí tốt nhất để liệt kê Database Fields (Columns) trên sơ đồ là ở đâu?
💡 A: Ngay cạnh biểu tượng Database đó. Việc này giúp người phỏng vấn dễ dàng theo dõi dữ liệu nào đang được lưu trữ mà không cần phải chuyển sang trang khác.
❓ Q: Sự khác biệt giữa Fanout-on-read và Fanout-on-write trong thiết kế Newsfeed?
💡 A:
Fanout-on-write: Ghi dữ liệu vào feed của tất cả người theo dõi ngay khi đăng (nhanh khi đọc, chậm khi ghi).
Fanout-on-read: Chỉ tổng hợp feed khi người dùng mở app (chậm khi đọc, nhanh khi ghi).
❓ Q: “Harden your design” trong Deep Dives nghĩa là gì?
💡 A: Là quá trình rà soát lại các điểm yếu: Single Point of Failure (Điểm lỗi đơn lẻ), Bottlenecks (Điểm nghẽn), và đảm bảo hệ thống không sụp đổ khi lượng người dùng tăng đột biến.
❓ Q: Làm thế nào để thể hiện sự “Seniority” (cấp bậc cao) trong lúc Deep Dive?
💡 A: Không đợi hỏi mới trả lời. Hãy chủ động nói:
“Hệ thống này hiện đang có điểm yếu ở X khi có lượng truy cập lớn, tôi đề xuất giải quyết bằng cách sử dụng Y.”
Đồng thời luôn cân nhắc sự đánh đổi (Trade-offs) ⚖️.