RFC / Design Doc Yazma
Önemli teknik kararlar için RFC (Request for Comments) / design document yazmayı öğreten skill — problem, alternatives, trade-off, karar, migration. Takımı alignment'a getiren, gelecek için referans olan belge.
İçerik
RFC / Design Doc Yazma
RFC = karar verilmeden önce yazılır. Hedef: alternatifleri gör, trade-off'ları yaz, takımı hizala, gelecek için referans bırak. Kod yazmadan önce doğru tartışmayı yaptığını garanti eder.
Ne zaman aktif olur
- Yeni bir sistem / servis tasarlanırken
- Mevcut mimaride önemli değişiklik önerilirken
- Teknoloji seçimi yapılırken (framework, DB, queue)
- Cross-team etkili karar alınırken
- "Geri alınamaz" kararlarda (data model, public API)
Ne zaman RFC yazma
- Küçük, geri alınabilir karar (3 günde bitecek iş)
- Sadece 1 kişiyi ilgilendiren implementasyon detayı
- "Kararı zaten verdim, yazmak sadece formalite" — alignment için yararlı
- Bug fix, feature'ın minor varyasyonu
Heuristic: 2+ kişi etkileniyor + karar 1 haftadan uzun sürecek bir yatırım için → RFC.
Şablon
# RFC-XXX: <Başlık>
**Yazar:** <isim>
**Status:** Draft | Under Review | Accepted | Rejected | Superseded
**Tarih:** <ISO>
**Reviewers:** <isim, isim>
**Related:** <RFC-YYY, Ticket-ZZZ>
## Özet
<2-3 cümle: ne öneriyorsun, neden>
## Bağlam & motivasyon
<Problem neden var? Hangi tetikleyici? Ne kadar büyük?>
## Hedefler
- <Ölçülebilir hedef 1>
- <Ölçülebilir hedef 2>
## Hedef olmayanlar (non-goals)
- <Bu RFC'nin kapsamı DIŞINDA olanlar>
## Mevcut durum
<Şu an nasıl çalışıyor? Neden yetersiz?>
## Alternatifler
### Seçenek A: <isim>
**Nasıl:** ...
**Artı:** ...
**Eksi:** ...
**Maliyet:** ...
### Seçenek B: ...
### Seçenek C: ...
## Önerilen çözüm
<Alternatiflerden hangisi ve neden>
### Detaylar
<Gerekli teknik detay: schema, API contract, akış>
## Migration & rollout
<Şu andan önerilen duruma nasıl geçeriz? Feature flag? Safe rollout?>
## Risk
<Ne yanlış gidebilir, nasıl azaltırız>
## Open questions
<Karar verilememiş / input beklenen noktalar>
## Timeline
<Rough takvim, milestone'lar>
## Referanslar
<Blog, paper, benzer projeler>
Her bölüm nasıl yazılır
Başlık
Kısa, özgün. Numaralandır.
Kötü: Search Improvements, Database Thing, New Feature
İyi: RFC-018: Turkish-aware fuzzy matching for product search
Status
Lifecycle takip edilebilir olsun:
- Draft: yazım aşamasında, feedback'e hazır
- Under Review: reviewer'lar feedback veriyor
- Accepted: karar verildi, implement edilecek
- Rejected: karar reddedildi, neden ileride gerekirse bakılır
- Superseded by RFC-XXX: yerine yeni RFC geçti
Özet
Reader'ın ilk gördüğü şey. 2-3 cümle:
Mobilde search'te %34 zero-result oranını düşürmek için Lunr'dan
Fuse.js + Turkish tokenizer'a geçiş öneriyoruz. A/B test ile kademeli
rollout, 4 hafta implementation + 2 hafta gözlem.
Bağlam
Neden bu RFC var? Sayısal / somut.
Son 3 çeyrekte mobil search funnel conversion'ı %8'den %6'ya düştü.
Analytics'te zero-result query oranı %34 (karşılaştırma: desktop
%18). En çok zero-result alan 100 query incelendi: 78'i Türkçe çekim
eki nedeniyle eşleşmiyor ("arabaların" → "araba" bulunamıyor).
Kullanıcı araştırmasında bu noktada vazgeçme / rekabet arama oranı
yüksek — tahmini yıllık kayıp $X.
Hedefler / Non-goals
Hedefler ölçülebilir. Non-goals scope korur.
## Hedefler
- Zero-result oranı %34 → %15 (90 gün)
- Search latency p95 artışı < %10
- Türkçe çekim formlarının %80+'ında başarılı eşleşme
## Non-goals
- Voice / image search (gelecek RFC)
- Personalization
- Multi-lingual (sadece TR öncelik)
- Full-text search yerine semantic/vector search (bakılmadı)
Mevcut durum
Okuyan her seviyeden anlasın. Diyagram kullan.
Şu anki flow:
1. Client: GET /api/search?q=araba
2. Backend: Lunr index query (memory, Node.js)
3. Ranked results dönüş
Sorunlar:
- Lunr Turkish analyzer yok — çekim eki eşleşmiyor
- Index size 500K item, query p95 45ms (OK)
- Update: 10 dakikada bir full rebuild, memory 700MB
Alternatifler
En az 2-3 alternatif. Hiçbiri seçilmemiş göründüğünde bile. "X'i düşündük ama eledi bıraktık" süreçle birlikte.
Her alternatif için:
- Nasıl çalışır (brief)
- Artı: neden çekici
- Eksi: trade-off
- Maliyet: zaman, para, risk
Önerilen çözüm
Alternatifler arasından hangisi ve neden. Savunmayı yap.
"B seçeneği çünkü...":
- X kriterinde en iyi
- Y risk kabul edilebilir
- Z maliyet bütçemiz içinde
Detaylar
Teknik spec:
- Data model / schema diff
- API contract (endpoint, request/response)
- Sequence diagram for kritik flow
- Error cases
- Performance budget
- Security / privacy considerations
Burada kod değil, architecture. Actual implementation PR'da.
Migration & rollout
- Geçiş fazları
- Feature flag mi?
- A/B test mi?
- Eski sistemi ne zaman kapatırız?
- Rollback planı
Risk
Cidden düşünülmüş risk listesi. Her biri için azaltma.
### Risk: Türkçe tokenization yanlış eşleşme üretir
**Olasılık:** Orta
**Etki:** Yanlış sonuçlar user frustration
**Azaltma:**
- 500 query fixtures ile offline eval
- Shadow traffic (%5) 1 hafta, eşleşme quality ölç
- Gradual rollout: 10% → 50% → 100%
**Rollback:** feature flag off → Lunr'a dön
Open questions
Bilinçli bilinmezlikler. Reviewer'lar burada input verir.
- [OPEN] Synonym expansion dictionary hangi kaynaktan? TDK mı custom mu?
- [OPEN] Cache stratejisi — per-user mı global mı?
- [OPEN] Metrikler: relevance'ı nasıl ölçeceğiz? NDCG, MRR?
İyi RFC özellikleri
- Reviewer 10 dakikada anlayabiliyor (özet + hedefler)
- Karar verici 20 dakikada alternatifleri tartabiliyor
- Implementor spec olarak kullanabiliyor
- 6 ay sonra geri dönüldüğünde "neden böyle yaptık" cevabı burada
Review süreci
1. Draft (yazar)
İlk draft tamamlandı, yazar kendisi review etti. #design-review gibi kanala link paylaş, async feedback bekle.
2. Async review (1 hafta)
Reviewer'lar yorum bırakır. Yazar her yoruma:
- Kabul → draft güncellenir
- Tartışma → reply ile gerekçe
- Reddet → neden, alternatif sunar
3. Sync meeting (gerekirse)
Async'te çözülmeyenler için 30-45 dk meeting. Tüm reviewer'lar gelir. Decision verilir veya "şu açıklık sonrası karar".
4. Accept / Reject
- Accept: status değişir, implementation ticket'ları açılır
- Reject: gerekçe yazılır, öğrenilenler doc'ta kalır
- Revise: major değişiklikle tekrar review
5. Superseded
RFC accept edildi ama sonra başka bir RFC onu geçersiz kıldıysa: Superseded by RFC-XXX. Eski RFC silinmez.
Somut örnek (özet)
# RFC-018: Turkish-aware fuzzy matching for product search
**Yazar:** Altay
**Status:** Under Review
**Tarih:** 2026-04-22
**Reviewers:** @mehmet (search), @ayse (frontend), @data-team
## Özet
Lunr'dan Fuse.js + Turkish tokenizer'a geçiş. Zero-result oranını
%34'ten %15'e düşürmek için 4 hafta implementation + gradual rollout.
## Bağlam
Mobil search funnel conversion %8 → %6 (Q2 → Q4). Analytics'te zero-
result %34. User research: çekim eki hatası ana sebep ("arabaların"
→ "araba" bulmuyor). Tahmini yıllık kayıp $180K.
## Hedefler
- Zero-result %34 → %15 (90 gün)
- Query p95 latency artışı < %10 (şu an 45ms)
- Türkçe çekim eki %80+ eşleşme
## Non-goals
- Voice / image search
- Personalization
- Semantic / vector search (ayrı RFC-019)
- Arapça / Kürtçe gibi ek diller
## Mevcut durum
Lunr.js in-memory index, Node.js. 500K SKU. Turkish analyzer yok.
Index rebuild 10 dk/periyot, 700MB RAM.
## Alternatifler
### A) Fuse.js + custom Turkish tokenizer
- **Nasıl:** Fuse.js fuzzy matching + özel suffix stripper
- **Artı:** Hafif (22KB), embedded, test edilebilir
- **Eksi:** Index update 12 dk (2 dk geriledi), relevance tuning emek
- **Maliyet:** 3-4 hafta
### B) Elasticsearch + Turkish analyzer
- **Nasıl:** ES cluster, Turkish plugin
- **Artı:** Olgun, pro relevance tuning, synonym desteği
- **Eksi:** Yeni infra, cluster cost ~$300/ay, operational overhead
- **Maliyet:** 8-10 hafta + ongoing ops
### C) Managed (Algolia, Meilisearch)
- **Nasıl:** 3. parti SaaS
- **Artı:** Out-of-box Turkish, hızlı entegrasyon
- **Eksi:** Data 3. partide (compliance), $500-2K/ay, vendor lock
- **Maliyet:** 2 hafta entegrasyon
## Önerilen çözüm: A
Fuse.js + custom Turkish tokenizer.
Gerekçe:
- Bütçe içinde (3-4 hafta)
- Vendor-free, data in-house
- Embedded: operasyonel overhead yok
- Mevcut index rebuild pipeline korunur
B seçeneği uzun vadede çekici ama şu ihtiyaç + bütçe için fazla.
Gelecekte search relevance hedef çubuğu yükselirse RFC-YY.
## Detaylar
...
(schema, API, tokenizer pipeline diyagramı, fuzzy config, vs.)
## Migration & rollout
- Phase 1 (Wk 1-2): tokenizer + fuse.js config
- Phase 2 (Wk 3): A/B infrastructure + feature flag
- Phase 3 (Wk 4): 10% traffic shadow
- Phase 4 (Wk 5): 10% live → izleme
- Phase 5 (Wk 6-8): 50% → 100%
## Risk
- Yanlış Türkçe eşleşme → fixture eval + shadow traffic
- Index büyümesi → memory profil sık
- Fuse.js config drift → lock dependency, locked test
## Open questions
- [OPEN] Synonym dict kaynağı (TDK / manuel / ikisi)
- [OPEN] Metric — NDCG mi MRR mi primary?
## Timeline
Accept bu hafta → Wk 8 sonu %100 live.
Anti-pattern'ler
- ❌ Alternatifleri yazmadan "seçildi" bölümü
- ❌ Somut metrik yok, "daha iyi olacak"
- ❌ Non-goals eksik — scope genişler
- ❌ Migration & rollback planı yok
- ❌ Diyagram eksik, sadece metin (komplex sistem okunmaz)
- ❌ Open question yok — her şey kesinmiş gibi
- ❌ RFC yazılıp reviewer'a gönderilmiyor, yalnız yazılıp unutulmuş
- ❌ Feedback gelmiyor → sync meeting planlama
- ❌ Review sonrası doc güncellemeyi unutma
- ❌ Status field güncellenmiyor (hala "Draft" görünüyor)
Checklist — RFC paylaşmadan önce
- Özet 2-3 cümle
- Bağlam somut (sayılarla)
- Ölçülebilir hedef ve non-goal
- En az 2 alternatif + artı/eksi
- Seçim gerekçelendirildi
- Migration / rollout planı
- Risk + azaltma
- Open questions explicit
- Timeline rough
- Reviewer'lar assign
- Diyagram (gerekliyse)