RFC'den Production'a: Implementation Hakkında Anlatmadıkları
Güzel RFC tasarımları ile karmaşık production gerçekliği arasındaki boşluk üzerine samimi bir değerlendirme ve bildirim sistemleri örneğinden gerçek dersler
Özet
RFC'ler production'la karşılaştığında nadiren değişmeden kalır ve bu mutlaka bir problem değil. Bildirim sistemi implementasyonlarını inceleyerek, zarif tasarımların organizasyonel kısıtlar, timeline baskıları ve beklenmeyen gereksinimlerle karşılaştığında nasıl evrimleştiğini öğrenebiliriz. Bu inceleme, teorik tasarım ile pratik implementasyon arasındaki boşluğu kapatmaya yardımcı olan kalıpları ortaya çıkarır.
Durum: Güzel RFC vs Production Gerçekliği
Güzelce hazırlanmış bir RFC okurken, zarif mimari diyagramlara bakıp "İşte bu, sonunda mükemmel çalışacak tasarım bu" diye düşündüğün o anı bilir misin? Sonra altı ay sonra kendini production sorunlarının içinde bulursun, timeline iki katına çıkmıştır ve o tertemiz database şeması sanki blender'dan geçmiş gibi görünür.
Bu kalıp sistem implementasyonlarında tekrar tekrar ortaya çıkar. RFC ile production arasındaki boşluk bir bug değil - gerçek takımlarla, gerçek iş baskıları altında karmaşık sistemler inşa etmenin bir özelliği. Bu boşluğu anlamak daha etkili planlama yapmamıza ve gerçekçi beklentiler belirlememize yardımcı olur.
Not: Aşağıdaki örnekler farklı organizasyonlardaki birden fazla bildirim sistemi implementasyonundan uyarlanmıştır. Spesifik detaylar değişebilse de, açıklanan kalıplar ve zorluklar bu alandaki yaygın deneyimleri temsil eder.
Görev: RFC'den Gerçekliğe Bildirim Sistemi İnşa Etmek
Her RFC iyimserlikle başlar. Aklımdaki bildirim sistemi RFC'si bir şaheserdi: temiz mimari diyagramlar, kapsamlı database şemaları, aşamalı dağıtım planları. Yaşadığımız her bildirim sorununu çözeceğini vaat ediyordu:
RFC kusursuz görünüyordu. Her şeyi düşünmüştük: rate limiting, deduplication, preference management, hatta sessiz saatler bile. Aşamalı yaklaşım muhafazakar görünüyordu - core infrastructure için 4 hafta kesinlikle yeterli olmalıydı?
Aksiyon: Implementasyon Zorlukları ve Adaptasyonlar
Database Şeması Evrimi
RFC'nin database şeması güzelliğin ta kendisiydi. Temiz, normalize edilmiş, düzgün foreign key'ler ve constraint'ler. RFC'nin önerdiği buydu:
Production'a geçtikten üç ay sonra, o tablo aslında şöyle görünüyordu:
Bu şema değişikliklerinin her biri bir production incident'ı, bir performance krizi veya tahmin edemediğimiz bir feature request'i temsil ediyor. Tertemiz RFC tasarımı gerçeklikle buluştu ve gerçeklik kazandı.
WebSocket Connection Management Karmaşıklığı
RFC kendinden emin bir şekilde real-time bildirimleri WebSocket'lerle handle edeceğimizi söylüyordu. Örnek kod çok temiz görünüyordu:
Altı ay sonra, mobil uygulama deployment'ının yanlış gittiği meşhur "50,000 zombie connection" felaketi dahil birden fazla production incident'ından sonra, elimizde aslında şu vardı:
Bu eklemelerin her biri bir production incident'ından geldi. Circuit breaker? Redis cluster'ımızı çökerttiğimizde eklendi. Chunking logic? Gömülü resimli bir marketing bildirimi mobile client'ları çökerttiğinde keşfettik. Rate limiting? 100,000 support ticket üreten bir notification storm sırasında öğrendik.
Zaman Çizelgesi ve Kapsam Evrimi
RFC'nin aşamalı yaklaşımı çok mantıklı görünüyordu:
- Phase 1 (Hafta 1-4): Core Infrastructure
- Phase 2 (Hafta 5-8): Advanced Features
- Phase 3 (Hafta 9-12): Integration & Optimization
Gerçekte olan:
Hafta 1-4: Infrastructure Sürprizi
Core infrastructure inşa etmek yerine, üç hafta sadece environment'ları ayarlamak ve "standart" database setup'ımızın write throughput'u kaldıramadığını keşfetmekle geçti. 4. hafta tamamen başka bir sistemdeki production incident ile takımımızı çeken bir olayla tükendi.
Hafta 5-12: Scope Creep Senfonisi
Product management, erken demo'ları görünce heyecanlandı. "Slack bildirimleri ekleyebilir miyiz?" Tabii, çok zor değil. "Kritik alert'ler için SMS?" Mantıklı. "Ah, bir de marketing kampanyaları için 90 gün önceden bildirim schedule etmeyi desteklememiz gerekiyor." Pardon, ne?
Ay 4-6: Integration Cehennemi
RFC'deki o temiz API tasarımını hatırlıyor musun? Tüm servislerimizin aynı authentication sistemini kullandığını varsayıyordu. Plot twist: kullanmıyorlardı. Üç farklı auth sistemimiz vardı (JWT, OAuth2 ve legacy session-based sistem) ve bildirimlerin hepsiyle çalışması gerekiyordu.
Ay 7-8: Performance Hesaplaşması
Sistem "çalışıyordu" ama production yükünü kaldıramıyordu. RFC saniyede 10,000 bildirim vaat ediyordu. Biz 500 ile uğraşıyorduk. Sonraki iki ay profiling, caching, query optimization ve mimari değişikliklerin bulanıklığıydı.
En büyük sürpriz? Darboğaz beklediğimiz yerde değildi (database write'ları). Template rendering'di. Süslü personalization sistemimiz kullanıcı context'i toplamak için bildirim başına 20+ API çağrısı yapıyordu.
Takım Ölçekleme ve Organizasyonel Değişiklikler
RFC "12 hafta için 2 developer" diyordu. Gerçekte kim çalıştı:
- 2 senior engineer (full-time olması gerekiyordu, production support yüzünden aslında %60)
- 1 junior engineer (2. ayda eklendi, 3. ayı codebase'i öğrenmekle geçirdi)
- 2 contractor (4. ayda "hızlı kazançlar" için eklendi, 5. ayı kodlarını düzeltmekle geçirdik)
- 1 DevOps engineer (sözde "danışmanlık", 3. ayda aslında full-time)
- 1 database uzmanı (5. ayda performance krizi için getirildi)
- Product manager (proje boyunca iki kez değişti)
- 3 farklı engineering manager (6. ayda reorg oldu)
Her takım değişikliği context kaybı, mimari tartışmaları ve yeniden çalışma anlamına geliyordu. Contractor kodu code review'da iyi görünüyordu ama hala ödediğimiz teknik borç yarattı. 6. aydaki reorg, yeni engineering manager "mimariyi yeniden gözden geçirmek" istediğinde projeyi neredeyse öldürüyordu.
Monitoring Gereksinimleri Keşfi
RFC'nin monitoring üzerine bir bölümü vardı. Delivery rate, response time ve error rate gibi metrikleri listeliyordu. Mantıklı, değil mi? Production'da gerçekten monitor etmemiz gerekenler:
Bu metriklerin her biri bir şeyler ters gittiği için var ve çok geç olana kadar geleceğini görmedik.
Teknik Borç Birikim Desenleri
RFC teknik borçtan bahsetmiyordu. 8. aya geldiğimizde uğraştığımız şey:
Template System Frankenstein'ı
Basit bir template sistemi ile başladık. Production'a geldiğimizde, farklı takımların farklı gereksinimleri olduğu ve hiç birleştirmeye vaktimiz olmadığı için aynı anda çalışan üç farklı template engine'imiz vardı.
Hiç Bitmeyen Migration
O güzel database şemasını hatırlıyor musun? Altı aydır "v2"ye migrate ediyoruz. Her iki şemayı da paralel çalıştırıyoruz, ara sıra bildirim kaybeden karmaşık bir sync sistemi ile.
Sonuç: Implementasyon Deneyiminden Dersler
RFC net success kriterleri tanımlamıştı: %99.9 uptime, <100ms delivery, saniyede 10,000 bildirim. Sonunda bu sayılardan bazılarına ulaştık, ama yanlış metrikler olduğu ortaya çıktı.
Aslında önemli olan:
- Kullanıcı mutluluğu: %99 delivery rate'imiz vardı ama kullanıcılar kötü zamanlandığı için bildirimleri sevmiyordu
- Developer verimliliği: Diğer takımlar "temiz" API'mıza kapsamlı yardım olmadan entegre olamıyordu
- Operasyonel yük: Tüm otomasyonumuza rağmen sistem sürekli bakım gerektiriyordu
- İş değeri: Marketing özelliklerin yarısını kullanamıyordu çünkü çok karmaşıktı
Anahtar Implementasyon İçgörüleri
Bildirim sistemi implementasyonlarında tutarlı olarak birkaç kalıp ortaya çıkar:
1. RFC'ler Hipotez, Spesifikasyon Değil
RFC'ni başlangıç hipotezi olarak değerlendir. Production'a çarptığı an, sürekli revizyon gerektiren yaşayan bir belge haline gelir. RFC'mizi çok uzun süre "spec" olarak dondurmuştuk, gerçeklik ayrıldığında sonsuz karışıklığa neden oldu.
2. Bilinmeyen Bilinmeyenler İçin Bütçe Ayır
Timeline ve bütçen ne olursa olsun, iki katına çıkar, sonra bilmediğini bilmediğin şeyler için %50 ekle. Bu kötümserlik değil; düzinelerce projeden pattern tanıma.
3. İlk Günden Migration İçin Tasarla
Her güzel şema migration'a ihtiyaç duyacak. Her temiz API versiyonlamaya ihtiyaç duyacak. Her basit sistem backward compatibility'ye ihtiyaç duyacak. Bu yetenekleri baştan inşa et, sonradan düşünme.
4. Edge Case'ler Norm'dur
RFC review'da tartıştığın o edge case? Herkesin "ortaya çıkarsa hallederiz" dediği? Ortaya çıkacak, muhtemelen production'da, muhtemelen en kötü zamanda. Tartışıyorsan, edge case değildir.
5. Organizasyonel Dinamikler Teknik Mükemmelliği Yener
En iyi teknik tasarım takım dinamiklerini, politik gerçeklikleri ve organizasyonel kısıtlamaları hesaba katmazsa başarısız olur. 3. ayda katılan contractor senin güzel mimarini umursamıyor. 6. aydaki reorg her kararı sorgulayacak.
6. Gerçekten Debug Edeceğin Şeyleri Monitor Et
RFC'nin söylediğini monitor etme. Her şey yanarken bir incident sırasında neye ihtiyacın olacağını monitor et. Bu business metrikler, kullanıcı deneyimi metrikleri ve detaylı operasyonel metrikler demek, sadece teknik istatistikler değil.
Tasarım ve Implementasyon Arasında Köprü Kurma
Peki RFC ile production arasındaki boşluğu nasıl kapatırız? Yıllarca farklı yaklaşımları denedikten sonra, gerçekten işe yarayan:
Minimum Sevilebilir Ürün ile Başla
Minimum yaşayabilir değil - minimum sevilebilir. Kullanıcıların gerçekten kullanmak istediği küçük bir şey inşa et, sonra iterate et. Bildirim sistemimiz her şeyi bir kerede inşa etmeye çalışmak yerine sadece mükemmel çalışan email bildirimleri ile başlasaydık daha iyi olurdu.
Mükemmellik İçin Değil, Değişim İçin Tasarla
Database şeman değişecek. API'n evrimleşecek. Mimarin kayacak. Mükemmel son durumu tahmin etmeye çalışmak yerine zarif bir şekilde evrimleşebilen sistemler tasarla.
Developer Experience'a Erken Yatırım Yap
Sistemin entegre edilmesi ve işletilmesi ne kadar kolaysa, o kadar başarılı olur. Performance optimize ederken aylar harcadık, API'yi kullanımı kolaylaştırıyor olmalıydık.
Yaşayan Dokümantasyon Oluştur
O RFC tarihi bir eser olmamalı. Sistemle birlikte evrimleşmeli. Artık RFC'lerimizi "Orijinal Tasarım", "Mevcut Implementation" ve "Öğrenilen Dersler" bölümleriyle yaşayan belgeler olarak tutuyoruz.
Her Seviyede Feedback Loop'ları İnşa Et
Kullanıcı feedback'inden operasyonel metriklere, developer deneyim anketlerine kadar, sürecine feedback loop'ları inşa et. Neyin çalışmadığını ne kadar hızlı öğrenirsen, o kadar hızlı düzeltebilirsin.
Sonuç: Implementasyon Gerçekliğini Kucaklamak
Implementasyon evrimine karşı çalışmak yerine onunla çalışmayı öğrenmek sonuçları iyileştirir. Tertemiz RFC'ler kullanıcı ihtiyaçlarını ele aldıkça doğal olarak karmaşık hale gelir. Güzel mimariler pratik uzantılar geliştirir. Temiz codebase'ler gerekli teknik borç biriktirir. Bu başarılı problem çözmeyi temsil eder, tasarım başarısızlığını değil.
RFC-production boşluğu eliminasyon değil yönetim gerektirir. Etkili engineering sistem uyumunu ve kullanıcı değerini korurken ortaya çıkan gerçekliğe adapte olur.
Bildirim sistemi implementasyonlarını yansıttığımızda, final sistemler nadiren ilk tasarımlarla eşleşir. Tipik olarak daha karmaşıktırlar ve inşa etmesi daha uzun sürer, ama aynı zamanda daha yeteneklidirler ve ilk planlama sırasında belirgin olmayan problemleri çözerler.
RFC yazarken şunu hatırla: sabit spesifikasyonlar tanımlamaktan ziyade implementasyon gerçekliği ile bir konuşma başlatıyorsun. Bu perspektif daha iyi planlama ve daha gerçekçi beklentileri sağlar.
Projelerinde RFC-production evrimini deneyimledin mi? Implementasyon zorluklarından hangi dersleri öğrendin ve tasarım-gerçeklik geçişini yönetmeye hangi stratejiler yardımcı oluyor?