Kurumsal BT dünyasında rahatlatıcı bir efsane vardır: On beş yıllık bir çekirdek sistem, eninde sonunda tek bir kahramanca hafta sonunda yıkacağınız bir duvardır. İşi durdurun, Cumartesi gecesi yeni platforma geçin, Pazartesi yeniden doğmuş olarak açın. Uygulamada ise tek seferlik (big-bang) yeniden yazım, bütçelerin ve itibarların ölmeye gittiği yerdir. Çoğu, iki yıl sonra sessizce terk edilir; geriye şirketi hâlâ çalıştıran sisteme bir türlü yetişemeyen paralel bir sistemden başka hiçbir şey bırakmadan.
Bu yüzden ulusal bir perakende zinciri, yaşlanan ERP sistemini emekliye ayırma konusunda bize yardım istediğinde, verdiğimiz ilk taahhüt odadaki herkesi rahatsız eden taahhüt oldu: Onu kapatmayacaktık.
Durum
Müşteri, bölge genelinde yaklaşık 60 mağaza işletiyor ve bunların tamamı, ilk kez yaklaşık on beş yıl önce devreye alınan tek bir monolitik ERP'ye bağlı. Zaman içinde bu sistem her şeyi içine çekmişti — stok, fiyatlandırma, satın alma, sadakat, mağaza mutabakatı, hatta özel yapım bir bordro köprüsü. Her entegrasyon doğrudan onun veritabanına uzanıyordu. Kimse şemaya dokunmaya cesaret edemiyordu, çünkü kimse neyin bozulacağını tam olarak öngöremiyordu ve sistemin en eski köşelerini anlayan iki mühendis çoktan ayrılmıştı.
Sistem hâlâ çalışıyordu. Tuzak da buydu. İşi yeterince iyi yürütüyordu; öyle ki değişim riski her zaman yerinde durmanın maliyetinden daha büyük görünüyordu — ta ki stok sayımı geceleri mağazaların kaldırabileceğinden daha uzun sürmeye başlayana ve bir ödeme işlemcisinin, monolitin fiziksel olarak karşılayamayacağı katı bir son tarih taşıyan kullanımdan kaldırma (deprecation) bildirimi gelene kadar.
Zorluk
Kısıtlar affetmezdi. Bir perakendeci bir geçiş için kapanamaz; her kesinti saati, kasada kaybedilen gelir ve kaybedilen güven demektir. Veri on beş yıl derinliğinde ve tutarsızdı; yıllarca biriken geçici çözümler içine işlemişti. Ve kuruluşun, bir önceki yıl benzer bir şirketin kendi "modernizasyonunun" çökmesini izledikten sonra, anlaşılır biçimde riske iştahı düşüktü. Bize bir inanç sıçraması değil; herhangi bir noktada duraklatılabilen, incelenebilen ve geri alınabilen bir yol gerekiyordu.
Nasıl yaklaştık
Yeniden yazımı hemen eledik ve kademeli boğmaya (incremental strangulation) bağlı kaldık: Yeni sistemi eskisinin etrafında inşa etmek, her seferinde tek bir yeteneği yönlendirmek ve monoliti, geriye kalan kısım sessizce kapatılabilecek hâle gelene dek küçültmek.
- Dokunmadan önce haritalayın. İlk haftaları her entegrasyonu izleyerek ve gerçek veri sözleşmelerini — belgelenmiş olanları değil — yeniden kurgulayarak geçirdik; böylece neyin neye bağlı olduğunu tam olarak bildik.
- Bir dikiş yeri (seam) oluşturun. Monolitin önüne bir API cephesi (facade) koyduk; böylece çağıran taraflar doğrudan veritabanıyla konuşmayı bırakıp bizim kontrol ettiğimiz bir arayüzle konuşmaya başladı.
- Yeteneğe göre boğun. Her alan — önce fiyatlandırma, sonra stok, sonra sadakat — bu cephenin arkasında bir servis olarak yeniden inşa edildi ve asla topluca değil, bağımsız olarak devreye alındı.
- Feature flag'lerle yönlendirin. Her geçiş, saniyeler içinde geri alabileceğimiz bir flag değişikliğiydi; önce tek bir pilot mağaza için, sonra bir bölge, sonra tüm ağ için.
- Sürekli mutabakat sağlayın. Eski ve yeni paralel çalıştı, her gece karşılaştırıldı ve herhangi bir sapma bir sürüm engelleyici (release blocker) olarak ele alındı.
Ne yaptık
En çok sancı yaratan ama patlama yarıçapı en düşük olan alan olan fiyatlandırma ile başladık ve onu, verinin senkronize bir kopyasından okuyan bağımsız bir servis olarak ayağa kaldırdık. Birkaç hafta boyunca gölge modda çalıştı — her fiyatı monolitle birlikte hesaplayarak ve tek bir müşteriyi bile etkilemeden uyuşmazlıkları günlüğe kaydederek. İkisi tutarlı biçimde uyuşmaya başladığında, tek bir pilot mağaza için flag'i değiştirdik, tam bir ticaret haftasını izledik, sonra dağıtımı bölge bölge genişlettik.
Sırada stok, ardından sadakat geldi; her biri aynı ritmi izledi: cephe, gölge, pilot, genişletme. Yol boyunca dikiş yerini sağlamlaştırdık — API katmanına MFA ve düzgün erişim kontrolü ekledik, davranışı gerçekten görebilmek için günlükleri bir SIEM'de merkezileştirdik ve yıllardır sessizce yönetilmeyen mağaza uç noktalarına EDR yerleştirdik. Son alan da taşındığında, monolit tek bir hafta sonunda emekliye ayırdığımız ince bir mutabakat işine indirgenmişti — tüm programın tek planlı kesintisi, o da kısa süreli.
Sonuç
| Metrik | Öncesi | Sonrası |
|---|---|---|
| Geçiş için planlanan kesinti | Tahminen birkaç günlük geçiş | Tek bir hafta sonunun altında, tek kısa pencere |
| Gecelik stok sayımı / toplu iş kapanışı | Gece penceresini aşıyordu | Yaklaşık 3× daha hızlı, pay bırakarak bitti |
| Bir fiyat kuralını değiştirme süresi | Günler, uzman talebiyle | Aynı gün, self-servis |
| Ham veritabanına erişen entegrasyonlar | Neredeyse tamamı | Yaklaşık yarısı emekliye ayrıldı, kalanı API'nin arkasında |
| Geri alınabilir geçiş adımları | Fiilen hiç yok | Her adım flag ile geri alınabilir |
Bu sayıların hiçbiri tek başına çarpıcı değil ve asıl mesele de bu. Programın başarısı, olayların yokluğuyla ölçüldü — kaybedilen bir satış günü yok, stok sayımı krizi yok, manşet yok. Temelleri altından değiştirilirken işletme satış yapmaya devam etti ve mağaza personelinin çoğu bir geçişin yaşandığını hiç bilmedi.
Farkı yaratan neydi
- Geri alınabilirlik, özgüvene üstün gelir. Saniyeler içinde geri alamayacağımız bir geçişe asla güvenmedik. Feature flag'ler, yüksek riskli her kararı düşük riskli, gözlemlenebilir bir deneye dönüştürdü.
- Gölge mod, güveni ucuza kazandırır. Yeniyi ve eskiyi yan yana çalıştırmak, herhangi bir şey canlıya geçmeden önce çıktıları karşılaştırmak, müşterinin kaygısını kanıta dönüştürdü — ve hiçbir planlamanın yakalayamayacağı veri tuhaflıklarını yakaladı.
- Yalnızca kodu değil, dikiş yerini modernize edin. Cephe, eski mimarinin imkânsız kıldığı güvenlik kontrollerini — MFA, merkezî günlükleme, uç nokta koruması — eklemek için doğru yerdi.
Monolit gitti, ama daha kalıcı olan sonuç şu: Bir sonraki değişiklik artık cesaret gerektirmiyor — yalnızca bir flag. Modernizasyon aslında bunun içindir.