10 câu hỏi có thể gặp khi phỏng vấn
Chọn theo kỹ năng và cấp của tin (Node.js, System Design & Kiến trúc, ReactJS). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.
01Process Node trên production tăng RAM liên tục rồi bị kill. Bạn tìm memory leak thế nào?Node.js · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Node.js →Trước hết xác nhận có leak thật: theo dõi heap qua thời gian (
process.memoryUsage(), metrics của APM). Heap tăng rồi giảm sau GC là bình thường; chỉ tăng không giảm mới là leak.Nguyên nhân hay gặp:
- Cache trong bộ nhớ (
Map, object) không giới hạn kích thước hoặc thời hạn. - Event listener đăng ký mỗi request mà không gỡ (thường kèm cảnh báo
MaxListenersExceededWarning). - Closure giữ object lớn; timer không
clearInterval. - Mảng toàn cục lưu dữ liệu request để debug rồi quên xoá.
Cách điều tra:
- Chạy với
--inspect, mở Chrome DevTools, chụp heap snapshot trước và sau khi bắn tải, so sánh object tăng thêm và chuỗi retainers. - Dùng
--heapsnapshot-near-heap-limitđể tự chụp snapshot khi sắp hết bộ nhớ.
Người phỏng vấn muốn nghe: cache thì dùng LRU có giới hạn hoặc Redis, và biết rằng tăng
--max-old-space-sizechỉ làm lỗi đến chậm hơn.- Cache trong bộ nhớ (
02Bạn mở rộng (scale) một API Node.js thế nào? Graceful shutdown là gì và vì sao cần?Node.js · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Node.js →Node một process chỉ dùng tốt một core, nên scale theo chiều ngang:
- Chạy nhiều process (cluster, PM2) hoặc nhiều container sau load balancer, Kubernetes tự tăng giảm số pod.
- App phải stateless: session, cache, rate limit, lock để ở Redis hoặc DB, không để trong bộ nhớ process.
- WebSocket nhiều instance cần adapter qua Redis pub/sub để gửi tin giữa các instance.
- Đặt giới hạn connection pool DB theo tổng số instance.
Graceful shutdown: khi nhận
SIGTERM(deploy, scale down), ngừng nhận request mới, chờ request đang chạy xong, đóng DB và queue, rồi thoát:process.on("SIGTERM", () => { server.close(async () => { await db.close(); process.exit(0); }); });Hay sai: không xử lý
SIGTERM, mỗi lần deploy lại cắt ngang request và job đang làm dở. Nên đặt thêm timeout buộc thoát nếu chờ quá lâu.03Khi xây dựng API bằng Node.js, bạn chú ý những vấn đề bảo mật nào?Node.js · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Node.js →- Validate mọi input ở biên bằng schema (Zod, Joi,
class-validatortrong NestJS); chỉ nhận field cho phép để tránh mass assignment. - Injection: dùng query có tham số hoặc ORM, không nối chuỗi SQL. Với MongoDB, chặn object toán tử như
{ "$gt": "" }lọt vào điều kiện truy vấn. - Xác thực và phân quyền: kiểm tra quyền trên từng tài nguyên (user này có sở hữu đơn hàng này không), không chỉ kiểm tra đã đăng nhập.
- Rate limiting cho login, OTP, API tốn tài nguyên.
- Header bảo mật (Helmet), CORS chỉ mở cho origin cần thiết.
- Secret để trong biến môi trường hoặc secret manager, không commit; không log token, mật khẩu.
- Dependency: chạy
npm audithoặc công cụ quét trong CI, khoá phiên bản bằng lockfile.
Người phỏng vấn muốn nghe: lỗi phân quyền theo đối tượng (IDOR) rất phổ biến, và bạn biết cách phòng nó.
- Validate mọi input ở biên bằng schema (Zod, Joi,
04Thiết kế hệ thống thông báo (notification) gửi push, email, SMS cho hàng triệu người dùng.System Design & Kiến trúc · Senior
Gợi ý trả lời
Ôn thêm câu hỏi System Design & Kiến trúc →Tách phần nhận yêu cầu khỏi phần gửi qua hàng đợi, và tách riêng từng kênh để kênh này lỗi không ảnh hưởng kênh khác.
- Notification service nhận yêu cầu, kiểm tra cài đặt và tuỳ chọn tắt thông báo của người dùng, render template, rồi đẩy vào queue theo kênh.
- Worker theo kênh gọi nhà cung cấp (FCM/APNs, email, SMS), retry có backoff, chuyển message lỗi vĩnh viễn sang dead letter queue.
- Ưu tiên: OTP, giao dịch dùng queue riêng, không bị kẹt sau chiến dịch marketing gửi hàng loạt.
- Chống trùng: idempotency key cho mỗi thông báo.
- Giới hạn: rate limit theo nhà cung cấp và theo người dùng; tôn trọng khung giờ yên lặng.
- Lưu trạng thái gửi, mở, lỗi để theo dõi và xử lý token thiết bị hết hạn.
Người phỏng vấn muốn nghe: bạn ước lượng được lưu lượng lúc cao điểm và nêu cách scale worker theo độ dài hàng đợi.
05Hệ thống microservices gặp sự cố, bạn cần những gì để quan sát (observability) và tìm nguyên nhân?System Design & Kiến trúc · Senior
Gợi ý trả lời
Ôn thêm câu hỏi System Design & Kiến trúc →Cần đủ ba nguồn tín hiệu được liên kết với nhau: metrics, logs, traces.
- Metrics: theo phương pháp RED cho service (Rate, Errors, Duration với p95, p99) và USE cho tài nguyên. Cảnh báo dựa trên SLO (vd. tỉ lệ lỗi, độ trễ) thay vì CPU đơn thuần.
- Logs có cấu trúc (JSON), kèm
trace_idvàrequest_idđể lọc toàn bộ log của một request qua nhiều service. - Distributed tracing với OpenTelemetry: thấy request đi qua những service nào, chậm ở đoạn nào.
- Dashboard theo từng service, ghi nhận các lần deploy để đối chiếu với thời điểm lỗi.
Khi có sự cố: ưu tiên khôi phục (rollback, tắt feature flag) trước, tìm nguyên nhân gốc sau, rồi viết postmortem không đổ lỗi cá nhân.
Người phỏng vấn muốn nghe: một sự cố thật bạn từng tham gia và điều đã cải thiện sau đó.
06So sánh CSR, SSR, SSG và ISR. Lỗi hydration mismatch là gì và xử lý ra sao?ReactJS · Senior
Gợi ý trả lời
Ôn thêm câu hỏi ReactJS →- CSR: trình duyệt tải JS rồi mới render; nội dung hiện chậm, kém cho SEO.
- SSR: server render HTML cho mỗi request. Dữ liệu luôn mới, tốn tài nguyên server.
- SSG: render sẵn lúc build. Rất nhanh, hợp nội dung ít đổi.
- ISR / revalidate: trang tĩnh được làm mới định kỳ hoặc theo sự kiện.
Hydration là bước React gắn sự kiện vào HTML do server render. Mismatch xảy ra khi lần render đầu ở client khác HTML từ server:
- Dùng
Date.now(),Math.random(), múi giờ,windowhoặclocalStoragetrong lúc render. - HTML lồng sai (
<div>trong<p>), extension trình duyệt sửa DOM.
Cách sửa: chuyển phần chỉ có ở client vào
useEffect, hoặc render component đó chỉ ở client; định dạng ngày giờ bằng múi giờ cố định.Người phỏng vấn muốn nghe: bạn chọn cách render theo từng trang, dựa trên độ tươi dữ liệu và nhu cầu SEO.
07Thiết kế xử lý job nền (gửi email, đồng bộ dữ liệu) trong hệ thống Node.js thế nào để không mất job và không xử lý trùng?Node.js · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Node.js →Dùng message queue thay vì xử lý ngay trong request: BullMQ (Redis), RabbitMQ hoặc dịch vụ queue của cloud. API đẩy job rồi trả về ngay; worker riêng xử lý.
Những điểm cần thiết kế:
- Retry có backoff (tăng dần thời gian chờ) và giới hạn số lần thử; job vẫn lỗi thì đưa vào dead-letter queue để xem lại.
- Idempotency: hầu hết queue đảm bảo "ít nhất một lần", nên job có thể chạy hai lần. Dùng khoá idempotency hoặc kiểm tra trạng thái trước khi làm (ví dụ email đã gửi chưa).
- Không mất job khi ghi DB: ghi dữ liệu và "sự kiện cần gửi" trong cùng transaction (outbox pattern), rồi một tiến trình khác đẩy sang queue.
- Giới hạn concurrency của worker, timeout cho từng job.
Hay sai: dùng
setTimeouthay mảng trong bộ nhớ làm "queue". Restart hoặc deploy là mất hết job.08Event loop của Node gồm những phase nào?
process.nextTick, Promise,setImmediatevàsetTimeoutchạy theo thứ tự nào?Node.jsGợi ý trả lời
Ôn thêm câu hỏi Node.js →Event loop của Node (libuv) đi qua các phase chính: timers (
setTimeout,setInterval), poll (chờ và xử lý I/O), check (setImmediate), close callbacks.Giữa các callback, Node chạy hết hàng đợi
process.nextTicktrước, rồi đến microtask của Promise.setTimeout(() => console.log("timeout")); setImmediate(() => console.log("immediate")); Promise.resolve().then(() => console.log("promise")); process.nextTick(() => console.log("nextTick")); // nextTick, promise, rồi timeout/immediate- Thứ tự giữa
setTimeout(0)vàsetImmediateở module chính là không chắc chắn; nhưng nếu cả hai được đặt trong một callback I/O thìsetImmediateluôn chạy trước.
Hay sai: gọi
process.nextTickđệ quy, khiến event loop không bao giờ sang được phase I/O.- Thứ tự giữa
09Stream trong Node là gì? Backpressure là gì? Làm sao xử lý file vài GB mà không hết RAM?Node.js
Gợi ý trả lời
Ôn thêm câu hỏi Node.js →Stream xử lý dữ liệu theo từng chunk thay vì đọc hết vào bộ nhớ. Có bốn loại: Readable, Writable, Duplex, Transform.
Backpressure: khi bên ghi chậm hơn bên đọc, dữ liệu dồn lại trong bộ đệm.
write()trả vềfalseđể báo nên dừng đọc cho đến khi có sự kiệndrain.Dùng
pipelineđể tự xử lý backpressure, lỗi và dọn dẹp:import { pipeline } from "node:stream/promises"; import { createGzip } from "node:zlib"; await pipeline( fs.createReadStream("big.csv"), createGzip(), fs.createWriteStream("big.csv.gz"), );Ứng dụng: upload/download file lớn, xuất CSV từ DB theo con trỏ, proxy dữ liệu.
Hay sai: dùng
fs.readFilecho file lớn, hoặc.pipe()nối nhiều bước mà không bắt lỗi ở từng stream, khiến file descriptor bị rò.10Bạn có câu hỏi gì cho chúng tôi không?Câu hỏi hành vi & văn hoá
Gợi ý trả lời
Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →Luôn có câu hỏi. Đây là cơ hội thể hiện sự quan tâm và cũng là lúc bạn đánh giá công ty.
Câu hỏi nên chuẩn bị (chọn 2–3 câu hợp với người đang phỏng vấn):
- "Một ngày làm việc của vị trí này thường như thế nào? Team có bao nhiêu người, gồm những vai trò gì?"
- "Ba tháng đầu, anh/chị kỳ vọng người vào vị trí này làm được gì?"
- "Team đang gặp thách thức kỹ thuật hoặc quy trình nào lớn nhất?"
- "Quy trình release và code review của team ra sao?"
- "Công ty đánh giá hiệu suất và review lương theo chu kỳ nào?"
- "Vì sao vị trí này đang tuyển: mở rộng team hay thay người?"
Hay sai: "Dạ không ạ", hoặc chỉ hỏi về nghỉ phép, lương thưởng ngay ở vòng kỹ thuật. Chuyện chế độ nên hỏi kỹ với HR.
Bạn đã phỏng vấn ở ONE Tech Stop Vietnam Company Ltd?
Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.
Chia sẻ kinh nghiệm phỏng vấn