System Design Expectations (Senior Level)

📖 Concept

System design at Google's senior level is one of the most critical rounds. For Android roles, this focuses on mobile-first system design — not just backend architecture.

What Google evaluates:

  1. Requirements Gathering — Do you ask the right clarifying questions?
  2. High-Level Architecture — Can you diagram the major components and their interactions?
  3. API Design — RESTful contracts, data models, request/response schemas
  4. Data Layer — Local storage, caching strategies, sync mechanisms
  5. Scalability — How does the system handle millions of users?
  6. Offline Support — A uniquely mobile concern that backend-focused candidates miss
  7. Trade-offs — Every decision has pros and cons. Can you articulate them?
  8. Failure Handling — Network errors, partial sync, conflict resolution

Common mobile system design questions at Google:

  • Design Google Photos for Android
  • Design Gmail's offline mode
  • Design a real-time chat application
  • Design a news feed with infinite scroll
  • Design Google Maps navigation for Android
  • Design an offline-first document editor

The framework for mobile system design:

1. Requirements & Constraints (5 min)
   - Functional: What does the app DO?
   - Non-functional: Scale, latency, offline, battery
   - Out of scope: What to exclude

2. High-Level Architecture (10 min)
   - UI Layer → ViewModel → Repository → Data Sources
   - Network layer, local database, sync engine
   - Diagram the data flow

3. Deep Dive (20 min)
   - Pick 2-3 critical components to design in detail
   - Data models, API contracts, sync strategies
   - Caching, pagination, error handling

4. Trade-offs & Scalability (10 min)
   - Alternative approaches considered
   - How to handle 10x growth
   - Failure scenarios and recovery

Senior-level signal: You should be able to discuss how the mobile client interacts with the backend, even if you're designing the Android side. Understanding the full stack — not just the Android layer — is what separates L5 from L4.

💻 Code Example

codeTap to expand ⛶
1// System Design: Offline-First Sync Architecture (High-Level Code)
2// This is the kind of architectural code Google expects you to sketch
3
4// 1. Data Model with sync metadata
5data class Note(
6 val id: String = UUID.randomUUID().toString(),
7 val title: String,
8 val content: String,
9 val updatedAt: Long = System.currentTimeMillis(),
10 val syncStatus: SyncStatus = SyncStatus.PENDING,
11 val version: Int = 1
12)
13
14enum class SyncStatus { SYNCED, PENDING, CONFLICT }
15
16// 2. Repository Pattern — Single source of truth
17class NoteRepository(
18 private val localDb: NoteDao,
19 private val remoteApi: NoteApi,
20 private val syncEngine: SyncEngine
21) {
22 // Local-first: always read from local DB
23 fun getNotes(): Flow<List<Note>> = localDb.getAllNotes()
24
25 // Write locally first, then sync
26 suspend fun saveNote(note: Note) {
27 val updated = note.copy(
28 syncStatus = SyncStatus.PENDING,
29 updatedAt = System.currentTimeMillis(),
30 version = note.version + 1
31 )
32 localDb.upsert(updated)
33 syncEngine.schedulePush(updated.id)
34 }
35
36 // Sync engine handles push/pull
37 suspend fun sync() {
38 syncEngine.pushPendingChanges(localDb, remoteApi)
39 syncEngine.pullRemoteChanges(localDb, remoteApi)
40 }
41}
42
43// 3. Sync Engine — Conflict resolution strategy
44class SyncEngine {
45 suspend fun pushPendingChanges(local: NoteDao, remote: NoteApi) {
46 val pending = local.getNotesByStatus(SyncStatus.PENDING)
47 for (note in pending) {
48 try {
49 val serverNote = remote.pushNote(note)
50 local.upsert(note.copy(
51 syncStatus = SyncStatus.SYNCED,
52 version = serverNote.version
53 ))
54 } catch (e: ConflictException) {
55 // Last-write-wins or manual conflict resolution
56 local.upsert(note.copy(syncStatus = SyncStatus.CONFLICT))
57 }
58 }
59 }
60
61 suspend fun pullRemoteChanges(local: NoteDao, remote: NoteApi) {
62 val lastSync = local.getLastSyncTimestamp()
63 val remoteChanges = remote.getChangesSince(lastSync)
64 for (change in remoteChanges) {
65 val localNote = local.getById(change.id)
66 if (localNote == null || localNote.syncStatus == SyncStatus.SYNCED) {
67 local.upsert(change.copy(syncStatus = SyncStatus.SYNCED))
68 }
69 // If local has pending changes, mark as conflict
70 }
71 }
72
73 fun schedulePush(noteId: String) {
74 // Use WorkManager for reliable background sync
75 // Exponential backoff, network constraint
76 }
77}

🏋️ Practice Exercise

System Design Practice:

  1. Design Google Photos for Android — focus on image loading, caching, and sync
  2. Design an offline-capable email client — consider draft saving, send queue, search
  3. Design a real-time collaborative document editor (like Google Docs)
  4. Design a ride-sharing app's driver tracking system
  5. Design Instagram's feed — infinite scroll, caching, prefetching
  6. Design a notification system for a social media app
  7. For each design, create:
    • Component diagram showing data flow
    • API contract for 3 key endpoints
    • Local database schema (Room entities)
    • Sync strategy with conflict resolution
    • Failure handling for 3 common failure modes
  8. Practice whiteboarding each design in 35 minutes
  9. Prepare to answer: "How would this change if we needed to support 100M users?"
  10. Prepare to answer: "What would you change if the user has poor/intermittent connectivity?"

⚠️ Common Mistakes

  • Designing only the backend and ignoring the Android client architecture — for Android roles, the mobile side is the focus

  • Not discussing offline support — this is the #1 differentiator for mobile system design

  • Jumping into low-level details without establishing high-level architecture first

  • Ignoring data consistency — what happens when the user edits offline and syncs later?

  • Not quantifying scale — 'a lot of users' is not a number. State assumptions: '10M DAU, 50 req/sec per user'

💼 Interview Questions

🎤 Mock Interview

Mock interview is powered by AI for System Design Expectations (Senior Level). Login to unlock this feature.