← Về Roadmap
Module 15 — System Design & Behavioral
Nên có
⏱ 6-8 giờ
📋 Prerequisites: All previous modules
🎯 Mục tiêu học tập
Trả lời được Mobile System Design questions (offline-first, chat, auth)
Thành thạo STAR method cho behavioral questions
Hiểu Architecture patterns cho React Native apps
Tự tin mock interview
📖 Hướng dẫn học
2
Practice 3 system design questions
Viết ra giấy hoặc doc, vẽ diagram. Thời gian: ~2h
3
Prepare 5 STAR stories
Viết ra 5 tình huống thực tế từ kinh nghiệm. Thời gian: ~1h
4
Mock interview với bạn
Tập trả lời thành tiếng. Record lại nếu có thể. Thời gian: ~1-2h
⚡ Khung trả lời nhanh
Clarify: user là ai, scale, offline cần không, security/compliance có gì đặc biệt?
Scope: chốt MVP trước, nói rõ phần chưa design sâu.
Architecture: screen/state/API/storage/sync/monitoring.
Trade-off: vì sao chọn giải pháp này, đổi lại mất gì.
Failure modes: mạng yếu, token hết hạn, conflict, crash, retry, rollout.
🧭 Vòng lặp học module này
Hiểu bản chất: system design mobile là trade-off giữa UX, network, storage, security, release và failure modes.
Thấy bug thật: design chỉ có tool name nhưng thiếu offline, retry, conflict, monitoring, rollout.
Debug: hỏi requirement, bóc scope, tìm bottleneck/failure mode trước khi chọn tool.
Fix: trình bày MVP, architecture, trade-off, failure handling và future work.
Áp dụng playground: viết design note 1-2 trang cho auth/product/cart/offline/release.
📚 Lý thuyết chi tiết & System Design Questions
1. Design Offline-First Note-Taking App
Yêu cầu
Users tạo/sửa/xóa notes, sync across devices, hoạt động offline.
Key Decisions
Local Storage: WatermelonDB hoặc SQLite cho structured data, MMKV cho settings/metadata.
Sync Strategy:
Optimistic local-first: Write local immediately → queue sync operations → sync khi có network
Sync queue: Mỗi mutation (create/update/delete) → push vào queue → retry với exponential backoff
Last-write-wins: Simple conflict resolution — latest timestamp wins. Hoặc field-level merging cho complex cases
Conflict Resolution:
Version vector hoặc timestamp-based
Field-level merge: nếu user A edit title, user B edit body → merge both changes
Conflict UI: hiện diff cho user resolve manually (nếu cần)
Architecture:
UI Layer → Repository → Local DB (source of truth)
→ Sync Engine → Remote API
Sync Engine:
- NetworkMonitor → trigger sync khi reconnect
- OperationQueue → ordered mutations
- ConflictResolver → merge/overwrite strategy
2. Design Push Notification System
End-to-end Flow
Backend Push Service Device
| | |
|-- Send notification ---→ | |
| (FCM/APNs payload) | |
| |-- Deliver to device -→|
| | |-- Display notification
| | |-- User taps
| | |-- Deep link → open screen
Key Components
Token management: Register device token → store in backend → refresh on app update
FCM (Android) + APNs (iOS): Platform push services
Notification types: Data-only (app handles display) vs Notification (system displays)
Foreground handling: react-native-push-notification, custom in-app banner
Deep linking: notification.data.url → navigate to specific screen
Notification preferences: per-channel opt-in/out, quiet hours
Analytics: delivered → opened → action rate
3. Design Real-Time Chat App
Architecture
UI (FlatList inverted)
↕
Chat Store (Zustand/Redux)
↕
Message Service
├── WebSocket Client (real-time)
├── REST API (history, media upload)
└── Offline Queue (pending messages)
Local DB: SQLite/WatermelonDB (message history cache)
Key Decisions
Real-time: WebSocket (bidirectional, persistent connection). Fallback: Long Polling
Message ordering: Server-assigned timestamps + sequence numbers
Offline: Queue outgoing messages → send khi reconnect → optimistic UI (hiện message ngay)
Delivery status: Sent → Delivered → Read (3 checkmarks pattern)
Pagination: Load older messages on scroll up — cursor-based pagination
Media: Upload to S3/CloudStorage → send URL in message
Typing indicator: Throttled WebSocket events
4. Design Authentication System
Token Flow
Login → Server returns {accessToken, refreshToken}
↓
accessToken: short-lived (15min), stored in memory
refreshToken: long-lived (30 days), stored in Keychain/Keystore
↓
API call → attach accessToken in Authorization header
↓
401 Unauthorized → use refreshToken to get new accessToken
↓
refreshToken expired → force logout
Key Decisions
Token storage: accessToken → memory (React state/context). refreshToken → Keychain (iOS) / Keystore (Android). TUYỆT ĐỐI KHÔNG AsyncStorage
Token refresh: Axios interceptor + request queue (xem Module 07)
Biometrics: Face ID/Touch ID/Fingerprint để unlock stored credentials
Multi-device: Server track device sessions, allow revoke per device
Social login: OAuth2 flow → exchange auth code cho tokens
5. Design Caching Strategy cho Media-Heavy App
Multi-layer Cache
Memory Cache (LRU, ~50 items)
↓ miss
Disk Cache (react-native-fast-image, ~500MB)
↓ miss
CDN / Remote Server
Key Decisions
Images: react-native-fast-image (tự động memory + disk cache)
API data: React Query (staleTime, gcTime, persist to MMKV)
Cache invalidation: Time-based (staleTime) + event-based (invalidateQueries)
Prefetch: Prefetch next page images khi user scroll gần cuối
Cache size limit: LRU eviction policy, disk quota
6. Design State Management cho 20+ Screen App
Phân loại State
Loại Tool Ví dụ
Local UI state useState, useReducer Modal open, form input, tab active
Shared UI state Zustand store Theme, user preferences, cart
Server state React Query User data, products, posts
Navigation state React Navigation Screen stack, deep link state
Auth state Context + Zustand Login status, tokens
Project Structure (Feature-based)
src/
├── features/
│ ├── auth/
│ │ ├── screens/
│ │ ├── hooks/
│ │ ├── api/
│ │ └── store/
│ ├── products/
│ ├── cart/
│ └── profile/
├── shared/
│ ├── components/
│ ├── hooks/
│ ├── utils/
│ └── api/
├── navigation/
└── app/
📚 Architecture Patterns
Feature-based vs Layer-based
Layer-based Feature-based
Structure components/, screens/, hooks/, api/ features/auth/, features/products/
Scalability Folders phình to, khó tìm file Mỗi feature isolated, dễ navigate
Team work Conflicts nhiều (edit cùng folder) Teams work on different features
Recommendation Small apps (<10 screens) Medium-Large apps (10+ screens)
Clean Architecture (Simplified cho Mobile)
Presentation Layer (Screens, Components, ViewModels/Hooks)
↓
Domain Layer (Use Cases, Business Logic, Interfaces)
↓
Data Layer (Repositories, API clients, Local DB, DTOs)
Repository Pattern: Abstraction layer giữa data sources và business logic. Repository decide lấy data từ cache hay network, transform DTOs thành domain models.
📚 Behavioral Questions (STAR Method)
STAR = Situation → Task → Action → Result
Luôn trả lời theo format này. Cụ thể, có metrics nếu có.
Q1: Bug chỉ xảy ra trên production — approach?
Situation: Users report crash nhưng team không reproduce được trên dev.
Task: Tìm và fix bug, minimize user impact.
Action:
Check Sentry/Crashlytics crash reports — stack trace, device info, OS version
Check affected user segments (specific device? OS version? network?)
Reproduce với production build (Hermes + release mode)
Add remote logging nếu cần (không thể reproduce locally)
Hotfix → CodePush/EAS Update nếu JS-only fix
Post-mortem: add regression test, improve monitoring
Result: Fix deployed trong X giờ, crash rate giảm từ Y% xuống Z%.
Q2: App bị 1-star reviews vì crash — action plan?
Action plan:
Triage: Sort crashes by frequency × severity. Top 3 crashes = priority
Stability sprint: Dành 1 sprint focus 100% vào stability (no new features)
Error boundaries: Wrap critical screens → graceful fallback thay vì crash
Global error handler: Catch unhandled Promise rejections + JS exceptions
Monitoring: Set alerts cho crash rate threshold
Reply reviews: Acknowledge issue, promise fix timeline
Regression tests: Add tests cho mỗi crash fix
Q3: Code review checklist?
Correctness: Logic đúng? Edge cases handled?
Performance: Re-renders unnecessary? Memory leaks? FlatList optimized?
Security: Sensitive data exposed? Input validated?
Types: TypeScript strict? No any? Proper null handling?
Tests: New code có tests? Edge cases covered?
Readability: Naming clear? Functions small? No magic numbers?
Accessibility: Labels? Touch targets? Screen reader?
Platform: Works on both iOS + Android?
Q4: Join team mới, codebase 50K+ LOC — onboarding?
Week 1: Đọc README, architecture docs. Setup project, run locally. Đọc PR history (understand conventions).
Week 2: Pick small bugs/tasks. Đọc code theo feature (follow 1 request end-to-end). Review PRs của teammates.
Week 3-4: Take on medium features. Pair program với senior. Document kiến thức mới (ADRs, wiki).
Key: Ask questions early. Không giả vờ hiểu. Document gaps cho future joiners.
Q5: Deadline tight, feature chưa xong — prioritize?
Approach:
Communicate sớm với PM/stakeholders — không hide
Break feature thành Must-have / Nice-to-have
Negotiate scope: ship MVP first, iterate later
Cut: animations, edge cases, advanced settings → tech debt ticket
Increase: pair program, ask help, reduce meetings
KHÔNG cut: tests cho critical flows, security, data integrity
❓ Câu hỏi phỏng vấn & Interview Tips
Ngày phỏng vấn
System Design: Hỏi clarifying questions TRƯỚC khi design. Ai dùng? Scale bao nhiêu? Offline cần không?
Coding: Nói ra thought process. Viết brute force trước → optimize sau.
Behavioral: Luôn dùng STAR. Specific, có metrics. "Giảm crash rate 40%" thay vì "fix nhiều bugs".
Hỏi ngược: Tech stack? Team size? Code review process? Release cycle? Testing practices?
Thái độ: Không biết thì nói không biết. Đừng fake. Interviewers respect honesty.
⚠️ Lỗi thường gặp khi trả lời
Nhảy vào tool quá sớm: “dùng Redux/SQLite/WebSocket” trước khi hỏi requirement.
Không nói trade-off, làm câu trả lời giống danh sách keyword.
Bỏ qua failure mode mobile: offline, app background, token expired, low storage, push permission denied.
Không phân biệt MVP và future improvement, khiến scope quá rộng.
Behavioral trả lời chung chung, không có tình huống, hành động, kết quả cụ thể.
🏢 Case đi làm thật
Case: Interviewer hỏi design chat app. Câu trả lời chỉ nói WebSocket + FlatList + Redux nên bị thiếu chiều sâu.
Cách nâng cấp: Thêm message ordering, pending/offline queue, retry, local DB, pagination older messages, media upload, reconnect/backoff, push notification khi app background, delivery/read status và monitoring crash/log.
🧠 Ghi nhớ nhanh
System design mobile tốt không phải chọn nhiều tool. Điểm mạnh nằm ở requirement rõ, boundary rõ, trade-off rõ và biết app sẽ hỏng ở đâu khi vào production.
❔ Câu hỏi tự kiểm tra
1. Offline-first app cần lưu operation queue như thế nào để retry an toàn?
2. Chat app xử lý message pending, failed và duplicated ra sao?
3. Auth system cần làm gì khi refresh token bị revoke ở một thiết bị?
4. Behavioral story của bạn có Situation, Task, Action, Result rõ chưa?
✅ Checklist tự đánh giá
Tôi design được offline-first app (sync strategy, conflict resolution)
Tôi giải thích được push notification flow end-to-end
Tôi design được real-time chat architecture
Tôi hiểu token-based auth flow + secure storage
Tôi biết caching strategy multi-layer
Tôi tổ chức được state management cho large app
Tôi phân biệt Feature-based vs Layer-based structure
Tôi đã chuẩn bị 5 STAR stories
Tôi đã mock interview ít nhất 1 lần
Tôi có code review checklist riêng
📎 Tài nguyên
📺 Search "Mobile System Design Interview" trên YouTube