Lesson 0036 · System Design · Penutup · ±45 menit · opsional, pengecualian durasi

Mock interview 45 menit: typeahead (autocomplete)

Satu soal yang belum dibahas di track ini, dikerjakan sendiri dengan kerangka 5 langkah dan timer, lalu dinilai dengan checklist yang memberi penalti untuk over-engineering

Lesson ini opsional dan merupakan satu-satunya pengecualian durasi di track ini: ±45 menit, sama dengan satu ronde interview. Kerangkanya sama dengan lesson 0027, tapi kali ini tidak ada penjelasan sebelum Anda menjawab. Soalnya, typeahead, sengaja tidak muncul di studi kasus 0028–0034, jadi Anda tidak bisa menjawab dari hafalan.

Target lesson ini: Anda bisa menjawab "Rancang typeahead untuk kotak pencarian dengan 10 juta DAU" dalam 45 menit tanpa catatan, mengikuti lima langkah sesuai waktu, memulai dari desain v1 paling sederhana, dan membenarkan setiap komponen tambahan dengan angka. Nilainya minimal 4 dari 6 poin checklist setelah penalti.

Aturan main

  1. Siapkan kertas atau whiteboard. Jawab dengan suara keras, seolah interviewer duduk di depan Anda. Merekam suara sendiri sangat membantu saat menilai.
  2. Tekan Mulai. Timer pindah segmen sendiri, seperti interviewer yang memotong: kalau waktu langkah habis, lanjut ke langkah berikutnya.
  3. Jangan buka jawaban contoh selama mock. Buka per langkah setelah timer selesai, lalu bandingkan.
  4. Kalau Anda butuh angka yang tidak ada di soal, ajukan asumsi dengan suara keras, seperti di interview sungguhan. Asumsi Anda boleh berbeda dari jawaban contoh selama dipakai secara konsisten.
"Kami ingin menambah typeahead (autocomplete) di kotak pencarian aplikasi kami: saat user mengetik, muncul saran pencarian. Aplikasi kami punya 10 juta user aktif harian. Rancang sistemnya." (45 menit)

Langkah 1 — Klarifikasi requirement (±5 menit)

Tulis 3–5 functional requirement dan non-functional requirement dalam angka. Pertanyaan klarifikasi standar ada di lesson 0027.

Lihat jawaban contoh langkah 1

Kalimat kunci: "boleh telat satu jam" dan "boleh degradasi". Keduanya akan membuat desain jauh lebih murah di langkah 4 dan 5.

Langkah 2 — Estimasi (±5 menit)

Hitung QPS rata-rata dan puncak, rasio baca:tulis, dan ukuran data. Ingat: satu pencarian bisa menghasilkan beberapa request saran.

Lihat jawaban contoh langkah 2
BesaranHitunganHasil
Request saranClient menunggu jeda ketikan ±100–200 ms (debounce) sebelum mengirim, jadi ±4 request per pencarian, bukan satu per huruf107 × 10 × 4 = 4 × 108 per hari
QPS baca4 × 108 ÷ 105 detik±4.000 QPS, puncak ±8.000 (asumsi 2×)
TulisPencarian yang benar-benar dikirim: 108 per hari, dicatat ke log (±50 byte)±1.000 QPS log, ±5 GB per hari; dibaca batch, bukan per request
Data saran±3 × 107 prefix unik (1–10 karakter) × 10 saran × ±20 byte±6 GB, muat di memori satu node
Bandwidth8.000 QPS × ±1 KB respons±8 MB/s ≈ 64 Mbps, kecil

Kesimpulan angka: sangat read-heavy (±4 baca per pencarian, tulis hanya ke log), data kecil, dan target latency ketat. Deep dive nanti berfokus pada jalur baca, bukan storage.

Langkah 3 — API dan data model (±7 menit)

Tulis 1–2 endpoint dan tabel utama dengan key-nya.

Lihat jawaban contoh langkah 3
GET /suggest?q=ind&limit=10
  → 200 OK   { "suggestions": ["indonesia", "indomaret", "indihome", …] }

Log pencarian (append-only, dari layanan search yang sudah ada)
  term, searched_at

Tabel term_counts            ← dihitung ulang batch job setiap jam dari log
  term   text    PRIMARY KEY
  count  bigint
  index: (term text_pattern_ops)   ← untuk LIKE 'prefix%'

Kenapa text_pattern_ops: dokumentasi PostgreSQL menyebut operator class ini membandingkan nilai "strictly character by character", sehingga cocok untuk "queries involving pattern matching expressions (LIKE or POSIX regular expressions)" kalau database tidak memakai locale "C". [1]

Langkah 4 — High-level design v1 (±13 menit)

Gambar diagram v1 sendiri dulu: desain paling sederhana yang memenuhi angka langkah 2. Telusuri satu request baca (user mengetik "ind") dan satu jalur tulis (pencarian masuk ke hitungan popularitas).

Lihat jawaban contoh langkah 4

v1: satu app server stateless dan satu PostgreSQL. Baca: SELECT term FROM term_counts WHERE term LIKE 'ind%' ORDER BY count DESC LIMIT 10. Tulis tidak lewat request saran sama sekali: batch job setiap jam membaca log pencarian, menghitung ulang term_counts, lalu menggantinya. Karena popularitas boleh telat satu jam, tidak ada counter yang ditulis setiap ketikan.

Log pencarian→ Batch job per jam→ term_counts→ GET /suggest
Client App server PostgreSQL Log pencarian Batch job GET /suggest LIKE 'ind%' per jam
v1: cukup untuk mulai. Belum ada cache, load balancer, atau queue, karena belum ada angka yang menuntutnya.

Kalimat untuk interviewer: "Untuk mulai cukup satu app server dan PostgreSQL dengan index prefix. Kalau p99 melewati 100 ms, saya ukur query-nya dulu, lalu mulai dari perubahan termurah."

Langkah 5 — Deep dive, bottleneck, trade-off (±15 menit)

Cari bottleneck pertama menurut angka, tambahkan satu komponen per alasan, dan sebut biayanya. Gambar evolusi v2 sendiri dulu.

Lihat jawaban contoh langkah 5

Evolusi dari v1 ke v2, satu komponen per alasan:

  1. Ukur dulu. EXPLAIN ANALYZE menjalankan query dan menampilkan waktu sebenarnya per node rencana. [2] Hasil yang diharapkan: prefix panjang ("indom") cepat, prefix pendek ("a", "in") lambat, karena index memang menemukan barisnya tapi ORDER BY count harus menimbang ratusan ribu baris yang cocok.
  2. p99 prefix pendek > 100 ms: precompute. Batch job yang sama menulis tabel prefix_topk(prefix PRIMARY KEY, suggestions) berisi 10 saran teratas untuk setiap prefix 1–10 karakter (±6 GB). Baca menjadi satu lookup primary key. Ini trie (prefix tree) yang "diratakan" menjadi tabel; trie di memori adalah alternatif yang sama cepatnya tapi harus dibangun ulang dan direplikasi sendiri. Biayanya: batch job lebih lama, dan saran tetap telat sampai satu jam, yang sudah diizinkan requirement.
  3. 8.000 QPS puncak: saran untuk satu prefix hanya berubah setiap jam, jadi respons boleh di-cache. RFC 9111: directive max-age menyatakan respons "is to be considered stale after its age is greater than the specified number of seconds". [3] Cache-Control: public, max-age=3600 membuat browser dan CDN menyerap prefix populer. Biayanya: saran bisa basi sampai satu jam lebih, dan CDN adalah biaya bulanan.
  4. Availability 99,9%: server kedua di belakang load balancer. Server stateless, jadi tidak ada state yang dipindah.
  5. Kalau database masih jenuh setelah cache: salin prefix_topk (±6 GB) ke Redis sebagai key-value. Sorted set Redis bisa mencari rentang leksikografis kalau semua anggotanya memakai score yang sama [4], tapi hasilnya diurutkan menurut abjad, bukan popularitas; karena itu key per prefix berisi daftar top-10 lebih cocok.
  6. Yang tidak ditambahkan: sharding (6 GB muat di satu node), Kafka + stream processing (popularitas boleh telat satu jam), microservices (satu tim, satu fitur). SRE Book menyebut kompleksitas seperti ini accidental complexity, yang "can be resolved with engineering effort", berbeda dengan kompleksitas yang melekat pada masalahnya. [5] Sebut sinyal kapan naik: kalau requirement berubah menjadi "trending dalam 1 menit", baru stream processing dibenarkan.
Client CDN Load balancer App 1 App 2 Redis (top-k) prefix_topk Batch job max-age=3600 per jam
v2: setiap kotak tambahan punya angka. CDN untuk 8.000 QPS prefix populer; dua app server untuk 99,9%; prefix_topk untuk p99 prefix pendek; Redis hanya kalau database masih jenuh setelah cache.

Penilaian — Nilai jawaban Anda sendiri

Setelah timer selesai dan kelima jawaban contoh dibuka, nilai rekaman atau catatan Anda dengan checklist ini. Soal yang sama ada di bank soal sebagai soal lisan.

"Rancang sistem typeahead (autocomplete) untuk kotak pencarian dengan 10 juta DAU. Anda punya 45 menit." (mock penuh, 45 menit)
Bandingkan dengan jawaban contoh dan checklist-nya

"Saya klarifikasi dulu: saran 10 teratas yang diawali prefix, diurutkan popularitas; 10 juta DAU, 10 pencarian per hari; p99 di bawah 100 ms karena user sedang mengetik; popularitas boleh telat satu jam. Estimasinya: dengan debounce sekitar 4 request per pencarian, jadi 4 × 10⁸ per hari, sekitar 4.000 QPS rata-rata dan 8.000 puncak; data saran sekitar 6 GB. API-nya GET /suggest?q=. v1 sederhana dulu: satu app server dan PostgreSQL, tabel term_counts dengan index text_pattern_ops, query LIKE prefix ORDER BY count LIMIT 10, dan batch job per jam yang menghitung ulang dari log. Setelah saya ukur, prefix pendek akan lambat karena cocok dengan jutaan baris, jadi batch job yang sama menulis tabel prefix_topk sehingga baca menjadi satu lookup primary key. Karena saran hanya berubah tiap jam, saya pasang Cache-Control max-age=3600 supaya browser dan CDN menyerap prefix populer. Server kedua di belakang load balancer untuk availability. Sharding belum perlu karena 6 GB muat di satu node; Kafka real-time juga tidak, karena requirement mengizinkan telat satu jam."

Checklist: apakah Anda menyebut…

  • requirement dalam angka: DAU, p99 < 100 ms, popularitas boleh telat ±1 jam?
  • estimasi: ±4.000 QPS rata-rata, puncak ±8.000, data saran ±6 GB?
  • API GET /suggest?q= dan data model term_counts lalu prefix_topk?
  • v1 sederhana dulu: satu app server + PostgreSQL dengan index prefix, satu request ditelusuri?
  • bottleneck prefix pendek diukur dulu, lalu top-k per prefix dan Cache-Control?
  • setiap komponen dibenarkan dengan angka (cache untuk 8.000 QPS, sharding belum perlu untuk 6 GB)?

Penalti: kurangi satu poin untuk setiap komponen tanpa alasan angka yang Anda gambar (Kafka "untuk jaga-jaga", sharding untuk 6 GB, microservices, Elasticsearch di v1). Ini tanda over-engineering yang dinilai negatif oleh interviewer. Kurangi satu poin juga kalau Anda masih di langkah 3 saat segmen High-level dimulai.

Lulus jika minimal 4 dari 6.

Cek cepat setelah mock

Kuis singkat untuk mengunci angka dan keputusan utama. Ini feedback cepat, bukan bukti penguasaan; yang dicatat tetap hasil review 0035.

Setelah mock

Bacaan lanjutan (opsional, tidak dihitung dalam durasi) PostgreSQL docs: Operator Classes and Operator Families, ±10 menit. Kapan index B-tree bisa dipakai untuk LIKE 'prefix%'.

Track System Design selesai. Kembali ke indeks untuk mengulang lesson atau review yang lemah.

Istilah: GLOSSARY.md (bagian "Penutup") · Indeks: semua lesson System Design

Ada yang belum jelas? Tanyakan ke saya (agent) di terminal, misalnya: "jadilah interviewer dan beri saya soal mock baru", "nilai jawaban mock saya dengan checklist ini", atau "bagaimana menambah saran personal per user tanpa merusak cache?"

Sumber: [1] PostgreSQL docs: Operator Classes and Operator Families · [2] PostgreSQL docs: Using EXPLAIN · [3] RFC 9111: HTTP Caching, 5.2.2.1 max-age · [4] Redis docs: Sorted sets · [5] Google SRE Book, bab 9: Simplicity