Kesintisiz şema değişiklikleri: güvenli kalan ekleyici göçler
Kesintisiz şema değişikliklerini öğrenin: ekleyici göçler, güvenli backfill’ler ve eski istemcileri koruyan kademeli dağıtımlarla kesinti olmadan güncellemeler yapın.

What zero-downtime really means for schema changes
Kesintisiz (zero-downtime) şema değişiklikleri hiçbir şeyin değişmediği anlamına gelmez. Kullanıcılar veritabanı ve uygulamayı güncellerken çalışmaya devam edebilmelidir; başarısızlıklar veya bloklanan iş akışları olmadan.
Kesinti, sisteminizin normal davranmayı bıraktığı herhangi bir andır. Bu 500 hataları, API zaman aşımı, ekranların boş veya yanlış değer göstermesi, arka plan işlerinin çökmesi veya uzun bir migration yüzünden veritabanının okuma kabul edip yazmaları engellemesi şeklinde olabilir.
Bir şema değişikliği yalnızca ana uygulama UI'sini bozmaz. Yaygın hata noktaları şunlardır: eski yanıt biçimini bekleyen API istemcileri, belirli sütunları okuyan veya yazan arka plan işler, doğrudan tablo sorgulayan raporlar, üçüncü taraf entegrasyonlar ve "dün çalışıyordu" gözüken iç yönetici betikleri.
Eski mobil uygulamalar ve önbelleğe alınmış istemciler sıkça sorun olur çünkü onları anında güncellemek mümkün değildir. Bazı kullanıcılar bir uygulama sürümünü haftalarca tutar. Diğerleri aralıklı bağlantı nedeniyle eski istekleri daha sonra tekrar deneyebilir. Hatta servis çalışanı (service worker), CDN veya proxy önbelleği eski kod veya varsayımları tutuyorsa web istemcileri de “eski sürüm” gibi davranabilir.
Gerçek hedef "tek büyük, hızlı biten bir migration" değildir. Hedef, her adımı kendi başına çalışan küçük adımlar dizisidir; böylece farklı istemciler farklı sürümlerde olsa bile sistem çalışır.
Pratik bir tanım: yeni kodu ve yeni şemayı herhangi bir sıra ile dağıtabiliyor olmalısınız ve sistem hâlâ çalışmalı.
Bu bakış açısı, klasik tuzağı önlemenize yardımcı olur: sütun yokken yeni uygulamanın yeni sütunu beklemesi veya eski kodun yeni sütunu işleyememesi gibi. Değişiklikleri önce ekleyici (additive) olarak planlayın, kademeli olarak yayınlayın ve eski yolların hiçbir şey tarafından kullanılmadığından emin olduktan sonra kaldırın.
Start with additive changes that don’t break existing code
Kesintisiz şema değişikliklerine giden en güvenli yol eklemektir, değiştirmek veya silmek değil. Yeni bir sütun veya tablo eklemek nadiren bir şeyi bozar çünkü mevcut kod eski yapıyı okumaya ve yazmaya devam edebilir.
Yeniden adlandırma ve silme risklidir. Bir yeniden adlandırma aslında “yeni ekle + eskiyi kaldır” demektir ve sorun eskiyi kaldırma aşamasında çıkar. Bir yeniden adlandırma gerekiyorsa bunu iki adımlı olarak yapın: önce yeni alanı ekleyin, eski alanı bir süre tutun ve hiç kimsenin ona bağımlı olmadığını doğruladıktan sonra kaldırın.
Sütun eklerken nullable alanlarla başlayın. Nullable bir sütun, eski kodun yeni sütundan habersiz satır eklemesine izin verir. Sonunda NOT NULL istiyorsanız, önce nullable ekleyin, backfill yapın, sonra NOT NULL uygulayın. Varsayılanlar yardımcı olabilir, ama dikkatli olun: bazı veritabanlarında varsayılan eklemek yine de birçok satırı etkileyebilir ve değişikliği yavaşlatabilir.
İndeksler de “güvenli ama bedelsiz değil” eklemelerdendir. Okumaları hızlandırabilirler, ama bir indeks oluşturmak ve sürdürmek yazmaları yavaşlatabilir. Hangi sorgunun bunu kullanacağını kesin olarak bildiğinizde indeks ekleyin ve veritabanınız meşgulse daha sessiz saatlerde yayımlamayı düşünün.
Ekleyici veritabanı göçleri için basit bir kural seti:
- Önce yeni tablolar veya sütunlar ekleyin, eski olanları dokunmadan bırakın.
- Yeni alanları veri dolana kadar opsiyonel (nullable) yapın.
- İstemciler güncellenene kadar eski sorgu ve payload’ların çalışmasını sürdürün.
- Kısıtları (NOT NULL, unique, foreign key) backfill’den sonra uygulamaya erteleyin.
Step-by-step rollout plan that keeps old clients working
Kesintisiz şema değişikliklerini tek bir deploy değil bir rollout olarak ele alın. Amaç, eski ve yeni uygulama sürümlerinin yan yana çalışmasına izin vermek ve veritabanının kademeli olarak yeni yapıya geçmesini sağlamaktır.
Pratik bir sıra:
- Uyumlu şekilde yeni şemayı ekleyin. Yeni sütunlar veya tablolar oluşturun, null kabul edin ve eski kodun sağlayamayacağı sıkı kısıtlardan kaçının. Bir indeks gerekiyorsa, yazmaları bloke etmeyecek şekilde ekleyin.
- Her iki "dili" de konuşabilen backend değişikliklerini dağıtın. API’yi hem eski hem yeni istekleri kabul edecek şekilde güncelleyin. Yeni alanı yazmaya başlayın ama eski alanı da doğru tutun. Bu “çift yazma” (dual write) aşaması mixed client sürümlerini güvende tutar.
- Mevcut veriyi küçük partiler halinde backfill yapın. Yeni sütunu eski satırlar için kademeli doldurun. Parti boyutunu sınırlayın, gerekirse gecikme ekleyin ve yük artarsa durdurabilmek için ilerlemeyi izleyin.
- Kapsama yüksek olduktan sonra okumayı geçin. Çoğu satır backfill olduktan ve güven oluştuktan sonra backend’i yeni alanı tercih edecek şekilde değiştirin. Bir süre eski alana geri dönüş (fallback) bırakın.
- Eski alanı en son kaldırın ve gerçekten kullanılmadığından emin olun. Eski mobil sürümler çoğunlukla ortadan kalkana, loglar eski alan okunmadığını gösterene ve temiz bir rollback planınız olana kadar bekleyin. Sonra eski sütunu ve ilişkili kodu kaldırın.
Örnek: full_name eklediniz ama eski istemciler hâlâ first_name ve last_name gönderiyor. Bir süre backend yazma sırasında full_name oluşturabilir, var olan kullanıcıları backfill yapabilir, sonra varsayılan olarak full_name okunur ama eski payload’lar desteklenir. Benimseme netleşince eski alanları düşürürsünüz.
Backfills without surprises: how to populate new data safely
Backfill, yeni bir sütunu veya tabloyu mevcut satırlar için doldurmaktır. Bu, kesintisiz şema değişikliklerinin en riskli kısmıdır çünkü ağır veritabanı yükü, uzun kilitler ve yarım göçmüş davranışlara neden olabilir.
Backfill’i nasıl çalıştıracağınıza karar verin. Küçük veri setleri için tek seferlik manüel bir runbook yeterli olabilir. Daha büyük veri setlerinde tekrarlanabilir ve güvenle durdurulup devam ettirilebilen bir arka plan işçisi veya zamanlanmış görev tercih edin.
İşi parçalara bölün ki veritabanı üzerindeki baskıyı kontrol edebilin. Milyonlarca satırı tek bir işlemde güncellemeyin. Öngörülebilir parça boyutları ve partiler arasında kısa beklemeler hedefleyin ki normal kullanıcı trafiği etkilenmesin.
Pratik bir desen:
- İndekslenmiş bir anahtar kullanarak küçük bir parti seçin (örneğin, sonraki 1.000 satır).
- Sadece eksik olanları güncelleyin (zaten backfill yapılmış satırları yeniden yazmaktan kaçının).
- Hızlıca commit edin, sonra kısa bir uyku verin.
- İlerlemeyi kaydedin (son işlenmiş ID veya zaman damgası).
- Hata durumunda tekrar deneyin ama baştan başlamayın.
İşi yeniden başlatılabilir yapın. Basit bir ilerleme işaretçisini özel bir tabloda saklayın ve işi tekrar çalıştırmanın veriyi bozmayacağından emin olun. İdempotent güncellemeler (örneğin UPDATE ... WHERE new_field IS NULL) yardımcı olur.
İlerlerken doğrulayın. Yeni değeri eksik olan satır sayısını izleyin ve birkaç sağlamlık kontrolü ekleyin — örneğin: negatif bakiye yok, zaman damgaları beklenen aralıkta, durumlar izin verilen kümede. Rastgele örneklemle gerçek kayıtları spot-check yapın.
Backfill tamamlanmamışken uygulamanın ne yapacağına karar verin. Güvenli bir seçenek fallback okumalarıdır: yeni alan null ise eski değeri hesaplamak veya okumak. Örnek: yeni preferred_language sütunu eklediniz. Backfill bitene kadar API, preferred_language boşsa profilden mevcut dili dönebilir; tamamlandıktan sonra yeni alanı zorunlu kılabilirsiniz.
API compatibility rules for mixed client versions
Bir şema değişikliği yayınlarken tüm istemcileri kontrol etmeniz nadirdir. Web kullanıcıları hızlı güncellenirken eski mobil sürümler haftalarca kalabilir. Bu yüzden geriye dönük uyumlu (backward compatible) API’ler önemlidir, şema migration’ınız “güvenli” olsa bile.
Yeni veriyi önce isteğe bağlı (optional) olarak ele alın. İsteklere ve yanıtlara yeni alanlar ekleyin ama ilk günden zorunlu kılmayın. Eski istemci yeni alanı göndermese bile sunucu isteği kabul etmeli ve dünkü gibi davranmalıdır.
Mevcut alanların anlamını değiştirmekten kaçının. Bir alanın adını değiştirmek, eski adı da çalışır tuttuğunuz sürece sorun çıkarmayabilir. Bir alanı yeni anlam için yeniden kullanmak ise ince kırılmalara yol açar.
Sunucu tarafı varsayılanları güven ağınızdır. preferred_language gibi bir sütun eklediğinizde, eksikse sunucu bir varsayılan atamalıdır. API yanıtı yeni alanı içerebilir; eski istemciler onu yok sayabilmelidir.
Uyumluluğu sağlayan kurallar:
- Yeni alanları önce opsiyonel ekleyin, sonra benimseme yüksek olunca zorunlu kılın.
- Eski davranışı stabil tutun, daha iyi davranışı bir feature flag arkasına alın.
- Sunucu tarafı varsayılanları uygulayın ki eski istemciler yeni alanı göndermezse sorun olmasın.
- Karışık trafiği varsayarak her iki yolu da test edin: “yeni istemci gönderiyor” ve “eski istemci göndermiyor”.
- Hata mesajları ve kodlarını sabit tutun ki izleme birden gürültülenmesin.
Örnek: kayıtta company_size ekliyorsunuz. Backend, alan eksikse “unknown” gibi bir varsayılan atayabilir. Yeni istemciler gerçek değeri gönderir, eski istemciler çalışmaya devam eder ve panolar okunabilir kalır.
When your app regenerates: keeping schema and logic in sync
Platformunuz uygulamayı yeniden üretiyorsa (regenerate), kod ve konfigürasyonun temiz bir yeniden oluşturulmasını elde edersiniz. Bu, şema değişikliklerinde kesintisizliği kolaylaştırır çünkü küçük, ekleyici adımlar atıp sıkça yeniden dağıtabilirsiniz; aylarca yamalar taşımak zorunda kalmazsınız.
Anahtar nokta tek bir kaynak (one source of truth). Eğer veritabanı şeması bir yerde değişip iş mantığı başka yerde değişirse, drift (uyumsuzluk) hızla ortaya çıkar. Değişikliklerin nerede tanımlandığına karar verin ve diğer her şeyi üretilmiş çıktı olarak kabul edin.
Net isimlendirme, kademeli roll-out sırasında kazaları azaltır. Yeni bir alan ekliyorsanız, hangisinin eski istemciler için güvenli olduğu ve hangisinin yeni yol olduğu açık olsun. Örneğin yeni sütunu status_v2 olarak adlandırmak, status_new demekten daha güvenlidir çünkü altı ay sonra bile anlamı net kalır.
What to re-test after each regeneration
Ekleme olsa bile bir yeniden oluşturma gizli bağlılıkları ortaya çıkarabilir. Her yeniden üretim ve deploy sonrası kritik akışların küçük bir setini yeniden kontrol edin:
- Kayıt olma, giriş, parola sıfırlama, token yenileme.
- Temel oluşturma ve güncelleme işlemleri (en çok kullanılanlar).
- Yönetici ve yetki kontrolleri.
- Ödemeler ve webhook’lar (ör. Stripe olayları).
- Bildirimler ve mesajlaşma (e-posta/SMS, Telegram).
Migration adımlarını editörü açmadan önce planlayın: yeni alanı ekle, her iki alanı da destekleyerek deploy et, backfill yap, okumaları değiştir, sonra eski yolu emekliye ayır. Bu sıra şema, mantık ve üretilen kodun birlikte ilerlemesini sağlar; değişiklikler küçük, incelenebilir ve geri alınabilir olur.
Common mistakes that cause outages (and how to avoid them)
Kesintisiz şema değişiklikleri sırasında çıkan çoğu kesinti “sert” veritabanı işleri yüzünden değildir. Sorun, veritabanı, API ve istemciler arasındaki sözleşmeyi yanlış sırayla değiştirmektir.
Yaygın tuzaklar ve daha güvenli hamleler:
- Eski kod hâlâ okurken bir sütun yeniden adlandırmak. Eski sütunu tutun, yeni sütun ekleyin ve bir süre ikisini eşleyin (ikisine de yazın veya bir view kullanın). Yeniden adlandırmayı, kimsenin eski ada bağımlı olmadığını kanıtladıktan sonra yapın.
- Nullable bir alanı çok erken zorunlu yapmak. Sütunu nullable ekleyin, onu her yere yazan kodu yayınlayın, eski satırları backfill edin, sonra son migration ile
NOT NULLuygulayın. - Backfill’i tek büyük işlemde yapıp tabloları kilitlemek. Küçük partilerle backfill yapın, limitler ve duraklamalar ekleyin. İlerlemeyi izleyin ki güvenle sürdürüp durdurabilesiniz.
- Yazımlar yeni veri üretmeden okumaları değiştirmek. Önce yazmaları değiştirin, sonra backfill yapın, sonra okumaları değiştirin. Okumaları önce değiştirirseniz boş ekranlar, yanlış toplamlar veya “alan eksik” hatalarıyla karşılaşırsınız.
- Eski alanları eski istemciler gitmeden silmek. Eski alanları beklediğinizden daha uzun tutun. Sadece metrikler eski sürümlerin fiilen inaktif olduğunu gösterdiğinde ve deprekatasyon penceresini duyurduğunuzda kaldırın.
Uygulamayı yeniden üretiyorsanız, isimleri ve kısıtları “temizleme” isteğiyle her şeyi bir seferde düzelme dürtüsüne direnin. Temizlik son adım olmalıdır, ilk adım değil.
İyi bir kural: bir değişiklik ileriye ve geriye güvenli şekilde alınamıyorsa, üretime hazır değildir.
Monitoring and rollback planning for phased migrations
Kesintisiz şema değişikliklerinin başarısı iki şeye bağlıdır: neyi izlediğiniz ve ne kadar hızlı durdurabildiğiniz.
Gerçek kullanıcı etkisini yansıtan sinyalleri izleyin, sadece “deploy bitti” mesajına bakmayın:
- API hata oranı (özellikle güncel endpoint’lerde 4xx/5xx sıçramaları).
- Yavaş sorgular (dokunduğunuz tablolar için p95 veya p99 sorgu süreleri).
- Yazma gecikmesi (pik trafikte insert/update süreleri).
- Kuyruk derinliği (backfill veya olay işleme için biriken işler).
- Veritabanı CPU/IO baskısı (değişiklik sonrası ani sıçrama).
Çift yazma yapıyorsanız (hem eski hem yeni sütunlara veya tablolara yazma), ikisini karşılaştıran geçici logging ekleyin. Sadece değerler farklı olduğunda loglayın, kayıt ID’si ve kısa bir sebep kodu dahil edin, hacim yüksekse örnekleyin. Migration sonrası bu logların kalıcı gürültü haline gelmemesi için kaldırılmasını hatırlatan bir not bırakın.
Rollback gerçekçi olmalı. Çoğunlukla şemayı geri almaktan ziyade uygulama kodunu geri alırsınız ve ekleyici şemayı olduğu gibi bırakırsınız.
Pratik rollback runbook:
- Uygulama mantığını bilinen son iyi sürüme geri alın.
- Yeni okumaları önce devre dışı bırakın, sonra yeni yazmaları durdurun.
- Yeni tabloları veya sütunları tutun, ama kullanmayı bırakın.
- Backfill’leri metrikler stabil olana kadar duraklatın.
Backfill için saniyeler içinde çevirilebilen bir durdurma anahtarı oluşturun (feature flag, konfigürasyon değeri, iş duraklatma). Ayrıca aşamaları önceden iletişime geçin: çift yazma ne zaman başlar, backfill ne zaman çalışır, okuma ne zaman değişir ve “durdur” nasıl görünür; böylece baskı altında kimse doğaçlama yapmaz.
Quick pre-deploy checklist
Şema değişikliğini yayınlamadan hemen önce durun ve bu kısa kontrol listesini çalıştırın. Bu liste karışık istemci sürümleriyle küçük varsayımların kesintiye dönüşmesini engeller.
- Değişiklik ekleyici, yıkıcı değil. Migration sadece tablolar, sütunlar veya indeksler ekliyor. Eski bir şey kaldırılmıyor, yeniden adlandırılmıyor veya eski yazmaları reddedecek şekilde sertleştirilmiyor.
- Okumalar her iki şekille de çalışıyor. Yeni sunucu kodu hem “yeni alan var” hem de “yeni alan yok” durumlarını hatasız idare ediyor. Opsiyonel değerlerin güvenli varsayılanları var.
- Yazmalar uyumlu kalıyor. Yeni istemciler yeni veriyi gönderebilir, eski istemciler eski payload’ları göndermeye devam edip başarılı olur. Sunucu her iki formatı da kabul edip eski istemcilerin ayrıştırabileceği yanıtlar üretir.
- Backfill başlatıp durdurmaya uygundur. İş partiler halinde çalışır, yeniden başlatılınca veri çoğaltmaz veya bozmaz ve kalan satır sayısı ölçülebilir.
- Silme tarihi belli. Eski alanları veya mantığı güvenle kaldırmak için somut bir kuralınız var (örneğin X gün sonra ve Y% istek güncellenmiş istemcilerden geliyorsa).
Regeneratif bir platform kullanıyorsanız bir ek kontrol daha ekleyin: geçiş yaptığınız tam modelden bir build üretip dağıtın ve üretilen API ile iş mantığının eski kayıtları hâlâ tolere ettiğini doğrulayın. Yaygın bir hata, yeni şemanın yeni zorunluluklar getirdiğini varsaymaktır.
Ayrıca deploy sonrası bir şey yanlış görünürse yapılacak iki hızlı eylemi yazın: neyi izleyeceksiniz (hatalar, zaman aşımı, backfill ilerlemesi) ve önce neyi geri alacaksınız (feature flag kapat, backfill duraklat, sunucu sürümünü geri al). Bu “hızlı tepki vereceğiz” şeklindeki genel planı gerçek bir plana dönüştürür.
Example: adding a new field while older mobile apps are still active
Bir sipariş uygulamanız var. Yeni bir alan delivery_window gerekiyor ve yeni iş kuralları için zorunlu olacak. Sorun, eski iOS ve Android sürümleri hâlâ kullanılıyor ve bu alanı günlerce veya haftalarca göndermeyecekler. Veritabanını hemen zorunlu kılarsanız bu istemciler hata vermeye başlar.
Güvenli yol:
- Aşama 1: Sütunu nullable olarak ekleyin, kısıtlama koymayın. Mevcut okumaları ve yazmaları değiştirmeyin.
- Aşama 2: Çift yazma. Yeni istemciler (veya backend) yeni alanı yazsın. Eski istemciler sütun null olduğu için çalışmaya devam eder.
- Aşama 3: Backfill.
delivery_windowalanını eski satırlar için bir kural ile doldurun (sevkiyat yönteminden çıkarın veya müşteri düzenleyene kadar "her zaman" gibi bir varsayılan atayın). - Aşama 4: Okumaları değiştirin. API ve UI artık önce
delivery_window’ı okusun, ama eksikse çıkarımsal değere geri dönsün. - Aşama 5: Sonradan zorunlu kılın. Benimseme ve backfill tamamlandığında
NOT NULLkoyun ve fallback’i kaldırın.
Her aşamada kullanıcıların hissettiği şey sıkıcı kalır (hedef budur):
- Eski mobil kullanıcılar eksik veri yüzünden sipariş veremeyecek şekilde API tarafından reddedilmez.
- Yeni mobil kullanıcılar yeni alanı görür ve seçimleri tutarlı şekilde kaydedilir.
- Operasyon ve destek, alanın kademeli olarak dolduğunu görür, ani boşluklar olmaz.
Her adım için basit bir izleme kapısı: yeni siparişlerde delivery_window alanının dolu olma yüzdesini takip edin. Bu değer tutarlı şekilde yüksek ve “alan eksik” doğrulama hataları sıfıra yakın olduğunda, backfill’den kısıt koyma aşamasına geçmek genellikle güvenlidir.
Next steps: build a repeatable migration playbook
Bir kerelik dikkatli rollout strateji değildir. Şema değişikliklerini rutin bir işlem gibi ele alın: aynı adımlar, aynı isimlendirme, aynı onaylar. Böylece bir sonraki ekleyici değişiklik bile sıkıcı kalır; uygulama meşgul olsa ve istemciler farklı sürümlerde olsa bile.
Playbook’u kısa tutun. Şunu cevaplamalı: ne ekliyoruz, bunu nasıl güvenli yayınlıyoruz ve eski parçaları ne zaman kaldırıyoruz.
Basit bir şablon:
- Sadece ekle (yeni sütun/tablo/index, opsiyonel yeni API alanı).
- Hem eski hem yeni şekli okuyabilen kodu yayınla.
- Küçük partilerle backfill yap, net bir “bitti” sinyali ile.
- Davranışı feature flag veya konfig ile çevir, redeploy yapma.
- Eski alan/endpoint’leri kesme sadece kesme tarihinden sonra ve doğrulama yapıldıktan sonra.
Düşük riskli bir tabloyla başlayın (yeni opsiyonel durum, notlar alanı) ve playbook’u baştan sona uygulayın: ekleyici değişiklik, backfill, karışık sürüm istemcileri, sonra temizlik. Bu alıştırma izleme, partileme ve iletişimdeki boşlukları büyük bir yeniden tasarıma kalkışmadan önce ortaya çıkarır.
Uzun vadeli karmaşayı önleyen bir alışkanlık: “sonra kaldır” maddelerini gerçek işler gibi takip edin. Geçici bir sütun, uyumluluk kodu veya çift yazma mantığı eklediğinizde hemen bir temizlik bileti oluşturun; sahip belirleyin ve tarih koyun. Yayın notlarında küçük bir “compatibility debt” notu tutun ki görünür kalsın.
Eğer AppMaster ile geliştiriyorsanız, regenerasyonu güvenlik sürecinin bir parçası olarak ele alabilirsiniz: ekleyici şemayı modelleyin, geçiş sırasında hem eski hem yeni alanları ele alacak iş mantığını güncelleyin ve kaynak kod temiz kalsın diye yeniden üretin. Bu iş akışının no-code bir ortamda bile gerçek kaynak kod ürettiği bir örneğini görmek isterseniz, AppMaster (appmaster.io) yine bu tarz iteratif, kademeli teslimata odaklanacak şekilde tasarlanmıştır.
Hedef mükemmellik değil: tekrarlanabilirliktir. Her migration’ın bir planı, ölçümü ve çıkış rampası olmalıdır.
SSS
Kesintisiz çalışma, şema değiştirirken ve kodu dağıtırken kullanıcıların normal şekilde çalışmaya devam edebilmesi demektir. Bu, bariz kesintilerden kaçınmayı içerir; ayrıca boş ekranlar, yanlış değerler, görev çökmesi veya uzun migraasyonların kilitler nedeniyle yazmaları engellemesi gibi sessiz bozulmalardan da kaçınmayı kapsar.
Sisteminizin birçok parçası veritabanı yapısına bağlı olduğu için, sadece migraasyonun başarılı olması yetmez. Arka plan işler, raporlar, yönetici betikleri, entegrasyonlar ve eski mobil uygulamalar yeni kodu dağıttıktan sonra bile hâlâ eski alanları göndermeye veya beklemeye devam edebilir.
Eski mobil sürümler haftalarca aktif kalabilir ve bazı istemciler eski istekleri daha sonra tekrar deneyebilir. API’nizin bir süre hem eski hem yeni yükleri kabul etmesi gerekir ki farklı sürümler sorunsuz birlikte çalışsın.
Ekleme (additive) değişiklikler genellikle eski kodu bozmaz çünkü eski şema yerinde kalır. Yeniden adlandırma ve silme risklidir çünkü eski istemcilerin hâlâ okuduğu veya yazdığı bir şeyi kaldırmak çökme veya başarısız isteklere neden olur.
İlk önce sütunu nullable (boş değer kabul eden) olarak ekleyin, böylece eski kod satır eklemeye devam edebilir. Mevcut satırları toplu şekilde backfill yaptıktan sonra ve yeni yazımlar tutarlı olduktan sonra NOT NULL kısıtını son aşamada uygulayın.
Bunu bir rollout olarak ele alın: uyumlu şemayı ekleyin, hem eski hem yeni sürümleri destekleyen kodu dağıtın, küçük partilerle backfill yapın, okuma tarafını yedekleyecek şekilde değiştirin ve eski alanı yalnızca kullanılmadığını kanıtladıktan sonra kaldırın. Her adım tek başına güvenli olmalıdır.
Küçük işlemlerle, kısa işlemler halinde backfill yapın ki tablolar kilitlenmesin veya yük patlaması yaşanmasın. İşi yeniden başlatılabilir ve idempotent yapın: sadece new_field IS NULL olanları güncelleyin, ilerlemeyi kaydedin ve gerektiğinde durdurup sürdürün.
Yeni alanları ilk etapta isteğe bağlı (optional) yapın ve eksikse sunucu tarafında varsayılanlar uygulayın. Eski davranışı sabit tutun, mevcut alanların anlamını değiştirmekten kaçının ve hem “yeni istemci gönderiyor” hem de “eski istemci göndermiyor” yollarını test edin.
Çoğunlukla uygulama kodunu geri alırsınız, şemayı değil. Yeni okumaları önce devre dışı bırakın, sonra yeni yazımları durdurun. Yeni tabloları/sütunları tutun ama kullanmayın, backfill’leri duraklatın ve metrikler stabil hale gelene kadar bekleyin.
Her aşamada kullanıcıya yansıyan sinyalleri izleyin: hata oranları, yavaş sorgular (p95/p99), yazma gecikmeleri, kuyruk derinliği ve veritabanı CPU/IO basıncı. Yeni alanın kapsaması yüksek ve hatalar düşük olduğunda bir sonraki adıma geçin; temizlik işini ertelemek yerine planlı iş olarak kaydedin.


