Base.vn Prep

2026-05-19 · Middle-level

PHASE 3

Mock Questions

23 câu chia 6 nhóm. Click từng câu để xem hint. Verbalize ra mồm trước gương.

▌React / Frontend

Sự khác nhau giữa useMemouseCallback?

A: Cùng concept (memoize). useMemo cache giá trị. useCallback cache function reference. useCallback(fn, deps) ≡ useMemo(() => fn, deps).

Khi nào dùng React.memo?

A: Child re-render nhiều mà props ít đổi. Chỉ effective khi props primitive hoặc reference stable. Đo bằng DevTools Profiler trước — KHÔNG memoize mọi component.

Controlled vs uncontrolled form, pick cái nào?

A: Controlled — validate realtime, re-render mỗi keystroke. Uncontrolled (ref) — perf tốt cho form lớn. Thực tế: React Hook Form hoặc TanStack Form — uncontrolled internal + dev UX controlled.

Server Component vs Client Component (Next.js 13+)?

A: Server Component (default trong app dir) — render server, không state/event, không ship JS. Bundle nhỏ, data fetch trực tiếp DB. Client Component — "use client". Rule: leaf interactive = client, parent = server.

Tránh re-render không cần thiết?

A: (1) State local nhất có thể. (2) Split component giới hạn scope. (3) React.memo + stable props. (4) Context split (data vs dispatcher). (5) Đo Profiler trước, đừng premature.

▌TanStack Query / Data Layer

staleTime vs gcTime khác gì?

A: staleTime = data còn fresh bao lâu (không auto-refetch). gcTime = giữ trong memory bao lâu sau khi không dùng (default 5m). Stale ≠ deleted — vẫn show cache, chỉ refetch background.

Invalidate query sau mutation?

A: queryClient.invalidateQueries({queryKey:['tasks']}) trong onSuccess. Dùng key factory để invalidate chính xác. Optimistic: onMutate set cache trước, onError rollback.

Khi nào dùng useInfiniteQuery?

A: Pagination kiểu "load more" hoặc infinite scroll. API trả cursor hoặc page number. getNextPageParam trả key cho lần fetch tiếp.

TanStack Query có thay được Redux?

A: Cho server state — có (cache, sync tốt hơn). Cho UI state (modal, theme, form draft) — không. Dùng useState/Zustand. 80% Redux trong app thật ra là server state.

▌Backend / API / Auth

Vì sao access token nên short-lived?

A: JWT không revoke được. Leak = hijack đến khi exp. Short-lived (5-15m) giới hạn exploit window. Refresh token dài hơn nhưng revoke được (lưu DB) + rotate mỗi lần dùng.

JWT lưu ở đâu cho web?

A: Access: memory — KHÔNG localStorage (XSS). Refresh: httpOnly + Secure + SameSite cookie. JS không đọc được. Reload page → /refresh → access mới.

PUT vs PATCH?

A: PUT thay thế toàn bộ (full replace, idempotent). PATCH update partial. Cả 2 idempotent theo spec nhưng PATCH dễ implement non-idempotent.

N+1 query, phát hiện + fix?

A: Phát hiện: log SQL trong dev (Prisma log:['query']). Fix: include/select để JOIN. DataLoader cho GraphQL. Materialized view nếu query phức tạp lặp.

Enforce multi-tenant isolation ở Prisma?

A: (1) Table có tenant_id. (2) Prisma middleware inject where:{tenantId} từ AsyncLocalStorage. (3) Postgres RLS làm safety net. (4) Integration test verify.

Rate limiting handle thế nào?

A: Redis INCR + TTL cho fixed window. Sliding window log chính xác hơn. Token bucket cho burst-friendly. Key = userId/IP. Trả 429 + Retry-After.

401 vs 403?

A: 401 — bạn là ai (chưa auth, token sai/hết hạn). 403 — biết bạn là ai nhưng không có quyền. FE: 401 → redirect login, 403 → "không có quyền".

▌Architecture / Patterns

SOLID là gì, ví dụ thực tế?

A: Single responsibility, Open/closed, Liskov, Interface segregation, Dependency inversion. Xem page principles hoặc design patterns.

Repository pattern khi nào over-engineering?

A: App nhỏ < 5 tables, không swap ORM, team 1-2 người. Prisma trực tiếp trong service đủ. Repository thừa layer, slow phát triển.

Monolith vs microservices?

A: Default monolith. Split khi (1) team > 2-3 squad độc lập, (2) scale khác nhau (video vs API), (3) công nghệ khác (ML Python). Đừng split sớm — phải distributed transaction, eventual consistency.

CI/CD pipeline điển hình?

A: PR → lint + typecheck + test → build → deploy preview. Merge main → migration → deploy prod → smoke test → rollback nếu fail. Cache deps + artifact. Secret qua env.

▌Database

Index khi nào hại?

A: Mỗi index = write update index → chậm INSERT/UPDATE. Low-cardinality (boolean) — full scan rẻ hơn. Composite sai thứ tự (range trước equality) → miss. Đo EXPLAIN ANALYZE.

Breaking migration deploy thế nào?

A: Expand-contract. (1) Add column nullable. (2) Code dual-write. (3) Backfill. (4) Switch read sang mới. (5) Drop cột cũ deploy sau. KHÔNG drop trong cùng deploy với code change.

Transaction isolation level?

A: Read Uncommitted, Read Committed (default Postgres), Repeatable Read, Serializable. Cao = ít concurrent. 99% case Read Committed đủ.

▌Behavioral / STAR Hooks

Kể về 1 lần fix bug khó nhất

Framework: Situation (production bug, user impact) → Task (mình trực) → Action (reproduce, hypothesis, tool, root cause) → Result (số/metric, lesson). Pick bug có depth (race, leak, N+1, stampede) — không pick "typo".

Lần bất đồng với teammate

A: Tránh "tôi đúng họ sai". Show: lắng nghe → data → compromise hoặc spike thử cả 2. Result: giải pháp tốt hơn cả ban đầu, hoặc nhường vì lý do hợp lý.

Vì sao bạn ứng tuyển Base.vn?

Talking points: Product impact (Base phục vụ hàng ngàn DN VN). Stack overlap (Next.js + NestJS + Postgres). Multi-tenant SaaS — bài toán hay. Sản phẩm thực không phải outsource. Muốn build domain HR/Work. Cá nhân hóa — đề cập 1-2 sản phẩm cụ thể.

← Phase 2 Next: Backend →