AI ile oluşturulan sistemlerde şema değişikliklerini güvenle yönetmeyi öğrenin: sürümleme, geriye dönük uyumlu yayınlar, veri göçleri, test, gözlemlenebilirlik ve geri alma stratejileri.

Bir şema, basitçe verinin biçimi ve her alanın ne anlama geldiği konusunda ortak kabul demektir. AI ile oluşturulan sistemlerde bu anlaşma yalnızca veritabanı tablolarında değil birçok yerde ortaya çıkar—ve ekiplerin beklediğinden daha sık değişir.
Şemalar en az dört katmanda karşınıza çıkar:
Sistemin iki parçası veri değiş tokuşu yapıyorsa, bir şema vardır—hatta kimse bunu yazmamış olsa bile.
AI tarafından üretilen kod geliştirmeyi hızlandırır, ama aynı zamanda değişimi artırır:
id vs userId) birden fazla üretim veya refaktör sonucu ortaya çıkar.Bunun sonucu, üreticiler ile tüketiciler arasında daha sık “sözleşme sürüklenmesi”dir.
Eğer sohbet yoluyla handler’lar, DB erişim katmanları ve entegrasyonlar üretiyorsanız, bu iş akışına baştan itibaren şema disiplini yerleştirmek önemlidir. Koder.ai gibi platformlar sohbet arayüzünden React/Go/PostgreSQL ve Flutter uygulamaları üreterek ekiplerin hızlı ilerlemesine yardımcı olur—ama ne kadar hızlı gönderirseniz, arayüzleri sürümlendirmek, yükleri doğrulamak ve değişiklikleri kasıtlı olarak dağıtmak o kadar önemli olur.
Bu yazı, üretimi stabil tutarken hızlı iterasyon yapmayı sağlayan pratik yöntemlere odaklanır: geriye dönük uyumluluğu korumak, değişiklikleri güvenli şekilde yayınlamak ve verileri sürpriz olmadan taşımak.
Teori ağırlıklı modelleme, formal yöntemler veya satıcıya özel özelliklerin derin detaylarına girmeyeceğiz. Odak, el ile yazılmış, AI destekli veya büyük ölçüde AI tarafından üretilmiş her türlü teknolojide uygulanabilecek örüntüler üzerinedir.
AI tarafından üretilen kod, şema değişikliklerini “normal” hale getirebilir—bu ekiplerin dikkatsiz olmasından değil, sistem girdilerinin daha sık değişmesinden kaynaklanır. Uygulama davranışınız promptlara, model sürümlerine ve üretilen bağlantı kodlarına kısmen bağlıysa, verinin biçimi zaman içinde daha kolay sürüklenir.
Aşağıdaki kalıplar şema sürüklenmesine sık neden olur:
risk_score, explanation, source_url) veya bir kavramı bölmek (ör. address yerine street, city, postal_code).AI tarafından üretilen kod genellikle hızlı çalışır, ama kırılgan varsayımları kodlayabilir:
Kod üretimi hızlı iterasyonu teşvik eder: gerektikçe handler’ları, parser’ları ve veritabanı erişim katmanlarını yeniden üretebilirsiniz. Bu hız faydalıdır, ama aynı zamanda küçük arayüz değişikliklerini tekrar tekrar göndermeyi kolaylaştırır—bazen fark etmeden.
Daha güvenli yaklaşım, her şemayı bir sözleşme olarak görmektir: veritabanı tabloları, API yükleri, olaylar ve hatta yapılandırılmış LLM yanıtları. Bir tüketici buna bağlıysa, onu sürümlendir, doğrula ve kasıtlı olarak değiştir.
Şema değişiklikleri eşit değildir. İlk ve en kullanışlı soru: mevcut tüketiciler herhangi bir değişiklik yapmadan çalışmaya devam edecek mi? Eğer evet ise genellikle ekleyicidir. Hayır ise kırıcıdır ve koordine edilmiş bir dağıtım planı gerekir.
Ekleme değişiklikleri mevcut anlamı değiştirmeden üzerine ek yapar.
Veritabanı örnekleri:
preferred_language).Veritabanı dışı örnekler:
Ekleme yalnızca eski tüketiciler bilinmeyen alanları görmezden geldiği ve yeni alanları zorunlu kılmadığı sürece “güvenlidir”.
Kırıcı değişiklikler, tüketicilerin zaten dayandığı bir şeyi değiştirir veya kaldırır.
Tipik veritabanı kırıcı değişiklikleri:
Veritabanı dışı kırıcı değişiklikler:
Merge etmeden önce belgeleyin:
Bu kısa “etki notu” özellikle AI tarafından üretilen kodun şema değişikliklerini örtük olarak getirdiğinde netlik sağlar.
Sürümleme, diğer sistemlere (ve gelecekteki size) “bu değişti ve risk düzeyi şu” demenin yoludur. Amaç evrak işi değil—istemciler, servisler veya veri pipeline’ları farklı hızlarda güncellenirken sessiz kırılmaları önlemektir.
Gerçekte 1.2.3 yayınlamasanız bile major / minor / patch olarak düşünün:
Ekipleri kurtaran basit kural: mevcut bir alanın anlamını sessizce değiştirmeyin. Eğer status="active" daha önce “ödeyen müşteri” anlamındaysa, onu “hesap var” anlamına çevirmeyin. Yeni bir alan veya yeni sürüm ekleyin.
Pratikte iki seçenekiniz vardır:
/api/v1/orders ve /api/v2/orders):Kırıcı veya yaygın değişikliklerde iyidir. Açık olur ama birden fazla sürümün bakımı ve düplikasyon yaratabilir.
new_field eklemek, old_field korumak):Ekleme mümkünse iyidir. Eski istemciler anlamadıklarını görmezden gelir; yeni istemciler yeni alanı okur. Zamanla eski alanı deprecate edip planlı şekilde kaldırın.
Akışlar, kuyruklar ve webhook’lar için tüketiciler genellikle dağıtım kontrolünüzün dışındadır. Bir şema kaydı (veya uyumluluk kontrolleri olan merkezi bir şema kataloğu) “sadece eklemelere izin ver” gibi kuralları dayatmaya yardımcı olur ve hangi üreticilerin/tüketicilerin hangi sürümlere bağımlı olduğunu görünür yapar.
Şema değişikliklerini göndermenin en güvenli yolu—özellikle birden fazla servis, job ve AI tarafından üretilen bileşen varsa—genişlet → backfill → geçiş → daralt modelidir. Bu, kesintiyi en aza indirir ve bir tüketicinin geride kalmasıyla prod’un bozulmasını önler.
1) Genişlet: Yeni şemayı geriye dönük uyumlu şekilde tanıtın. Mevcut okuma/yazma yolları değişmeden çalışmalı.
2) Backfill: Geçmiş veriler için yeni alanları doldurun (veya mesajları yeniden işleyin) böylece sistem tutarlı hale gelsin.
3) Geçiş: Yazarları ve okuyucuları yeni alan/formatı kullanacak şekilde güncelleyin. Bu, canary veya yüzde bazlı dağıtım gibi kademeli yapılabilir çünkü şema her iki formatı da destekler.
4) Daralt: Hiç kimsenin eski alana bağımlı olmadığından emin olduktan sonra eski alan/formatı kaldırın.
İki aşamalı (genişlet → geçiş) ve üç aşamalı (genişlet → backfill → geçiş) roll-out’lar, yazma ve okuma yollarını bağımsız taşımanızı sağladığı için kesinti süresini azaltır.
Diyelim customer_tier eklemek istiyorsunuz.
customer_tier sütununu nullable olarak ekleyin; varsayılan NULL olsun.customer_tier yazacak şekilde güncelleyin; okuyucular bunu tercih etsin.Her şemayı üreticiler (yazarlar) ile tüketiciler (okuyucular) arasında bir sözleşme olarak görün. AI ile üretilen sistemlerde bu kolayca gözden kaçabilir çünkü yeni kod yolları hızla ortaya çıkar. Rollout’ları açık hale getirin: hangi sürüm ne yazıyor, hangi servisler her iki sürümü de okuyabiliyor ve eski alanların kaldırılacağı kesin tarih nedir yazın.
Veritabanı migrasyonları, üretim verisini ve yapısını güvenli bir durumdan diğerine taşımanın “kılavuzu”dur. AI ile oluşturulan sistemlerde daha da önemlidir çünkü üretilen kod bir sütunun var olduğunu varsayabilir, alanları tutarsız şekilde yeniden adlandırabilir veya mevcut satırları göz önüne almadan kısıtlamaları değiştirebilir.
Migration dosyaları (kaynak kontrolde) “sütun X ekle”, “indeks Y oluştur” veya “A’dan B’ye veri kopyala” gibi açık adımlardır. İncelenir, denetlenir ve staging/production’da yeniden oynatılabilir.
Otomatik migrasyonlar (ORM/framework tarafından oluşturulan) erken geliştirme ve prototipleme için kullanışlıdır, ama üretime dokunan değişikliklerde tehlikeli operasyonlar (sütun silme, tablo yeniden inşa etme) veya beklenmeyen sıralama üretebilir.
Pratik kural: otomatik migrasyonları taslak için kullanın, ama üretimi etkileyen değişiklikler için gözden geçirilmiş migration dosyalarına çevirin.
Migrate işlemlerini mümkün olduğunca idempotent yapın: tekrar çalıştırmak veriyi bozmasın veya yarıda kalmasın. "create if not exists" tercih edin, yeni sütunları önce nullable ekleyin ve veri dönüşümlerini kontrollerle koruyun.
Ayrıca net bir sıraya sahip olun. Her ortam (yerel, CI, staging, prod) aynı migration dizisini uygulamalı. Üretimi manuel SQL ile “düzeltmeyin” unless sonrası bunu bir migration’a kaydedin.
Bazı şema değişiklikleri büyük tabloları kilitleyebilir. Riski azaltmanın yolları:
Multi-tenant veritabanları için tenant başına kontrollü bir döngü ile migrasyon çalıştırın, ilerlemeyi takip edin ve güvenli yeniden denemeler yapın. Shard yapılarında her shard’ı ayrı bir üretim sistemi gibi davranarak adım adım migrate edin, sağlık doğrulaması yapın ve sonra devam edin. Bu patlama alanını sınırlar ve rollback’i mümkün kılar.
Bir backfill, yeni eklenen alanları (veya düzeltilmiş değerleri) mevcut kayıtlar için doldurma işlemidir. Yeniden işleme ise geçmiş veriyi pipeline’dan yeniden geçirmek demektir—genellikle iş kuralları değiştiği, bir hata düzeltildiği veya model/çıktı formatı güncellendiği için yapılır.
Her ikisi de şema değişikliklerinden sonra yaygındır: yeni biçim yalnızca “yeni veriler” için yazılmaya başlanabilir, ama üretim sistemleri dünün verisinin de tutarlı olmasına ihtiyaç duyar.
Çevrimiçi backfill (prod ortamında, kademeli): Küçük partiler halinde kontrollü bir job çalıştırarak kayıtları güncellersiniz; bu, durumu duraklatma ve resume etme imkânı sağlar.
Toplu backfill (offline veya zamanlanmış işler): Büyük parçaları düşük trafik penceresinde işlersiniz. Operasyonel olarak basittir ama DB yükünde ani zirveler yaratabilir ve hatadan kurtulması daha uzun sürebilir.
Okurken tembel backfill: Eski bir kayıt okunduğunda uygulama eksik alanları hesaplayıp yazıyor. Bu maliyeti zamana yayar ve büyük bir job’dan kaçınır, ama ilk okuma daha yavaş olur ve bazı kayıtlar uzun süre dönüştürülmemiş kalabilir.
Pratikte ekipler genellikle bunları kombine eder: nadir kayıtlar için tembel backfill, sık erişilen veri için çevrimiçi job.
Doğrulama açık ve ölçülebilir olmalı:
Ayrıca panolar, arama indeksleri, önbellekler ve güncellenen alanlara bağımlı dışa aktarmaları da doğrulayın.
Backfill hız (hızlı bitirme) ile risk/maliyet (yük, compute, operasyonel iş) arasında takas yapar. Başlangıçta şu soruları netleştirin: “tamam” ne demek, beklenen çalışma süresi, izin verilen maksimum hata oranı ve doğrulama başarısız olursa duraklatma/yeniden deneme/geri alma stratejisi.
Şemalar sadece veritabanlarında yaşamaz. Bir sistem başka birine veri gönderdiğinde—Kafka topic’leri, SQS/RabbitMQ kuyrukları, webhook yükleri, hatta nesne depolamaya yazılan “event”ler—bir sözleşme oluşur. Üreticiler ve tüketiciler bağımsız hareket ettiğinden, bu sözleşmeler tek bir uygulamanın tablolarından daha sık kırılır.
Olay akışları ve webhook’larda, eski tüketicilerin görmezden gelebileceği ve yeni tüketicilerin benimseyebileceği değişiklikleri tercih edin.
Pratik kural: alan ekleyin, kaldırmayın veya yeniden adlandırmayın. Deprecate etmek gerekirse, bir süre daha göndermeye devam edin ve açıkça belgeleyin.
Örnek: OrderCreated olayına isteğe bağlı alanlar ekleyin.
{
"event_type": "OrderCreated",
"order_id": "o_123",
"created_at": "2025-12-01T10:00:00Z",
"currency": "USD",
"discount_code": "WELCOME10"
}
Eski tüketiciler order_id ve created_at alanlarını okur, geri kalanları görmezden gelir.
Üreticinin başkalarını neyin kıracağını tahmin etmesi yerine, tüketiciler hangi alanlara dayandıklarını yayımlasın. Üretici, değişiklikleri göndermeden önce bu beklentilere karşı doğrulama yapsın. Bu, modelin “yardımcı olarak” bir alanı yeniden adlandırabileceği veya tipini değiştirebileceği AI üretilen kod tabanlarında özellikle faydalıdır.
Parser’ları toleranslı yapın:
Kırıcı değişiklik gerektiğinde yeni bir olay türü veya sürümlü ad kullanın (ör. OrderCreated.v2) ve tüm tüketiciler migrate olana kadar paralel çalıştırın.
Bir LLM eklediğinizde, çıktılar hızla yazılı bir şema haline gelebilir—hiç kimse resmi bir spesifikasyon yazmamış olsa bile. Aşağı akıştaki kod “bir summary alanı olacak”, “ilk satır başlık”, veya “madde işaretleri tire ile ayrılır” gibi varsayımlarda bulunur. Bu varsayımlar katılaşır ve model davranışındaki küçük bir kayma bunları veritabanı sütunu yeniden adlandırması gibi kırabilir.
"Güzel metin"i parse etmek yerine, yapılandırılmış çıktılar (genellikle JSON) isteyin ve bunları sistemin geri kalanına sokmadan önce doğrulayın. Bunu "bir sözleşmeye geçme" olarak düşünün.
Pratik yaklaşım:
Bu, LLM yanıtlarının veri pipeline’larına, otomasyona veya kullanıcıya yönelik içeriğe beslendiği durumlarda özellikle önemlidir.
Aynı prompt ile bile çıktı zaman içinde kayabilir: alanlar atlanabilir, ekstra anahtarlar görünebilir ve tipler değişebilir ("42" vs 42, dizi vs string). Bunları bir şema evrimi olayı gibi ele alın.
Etkili hafifletmeler:
Bir prompt bir arayüzdür. Eğer düzenlerseniz, onu sürümlendirin. prompt_v1, prompt_v2 tutun ve kademeli olarak yayınlayın (özellik bayrakları, canary’ler veya tenant bazlı geçişler). Değişiklikleri terfi ettirmeden önce sabit bir değerlendirme setiyle test edin ve aşağı akış tüketicileri adapte olana kadar eski sürümü çalışır tutun. Güvenli dağıtım mekanikleri hakkında daha fazla bilgi için yaklaşımınızı safe-rollouts-expand-contract ile ilişkilendirin.
Şema değişiklikleri genellikle sıkıcı ama pahalı şekillerde başarısız olur: yeni bir sütun bir ortamda eksik olur, bir tüketici eski alanı beklemeye devam eder veya bir migration boş veriyle sorunsuz çalışır ama prod’da zaman aşımına uğrar. Test, bu "sürprizleri" tahmin edilebilir ve düzeltilebilir işe çevirir.
Birim testleri yerel mantığı korur: mapping fonksiyonları, serileştiriciler/deserileştiriciler, doğrulayıcılar ve sorgu oluşturucular. Bir alan yeniden adlandırıldığında veya tipi değiştiğinde birim testler ilgili koda yakın yerde başarısız olmalı.
Entegrasyon testleri uygulamanızın gerçek bağımlılıklarla (gerçek veritabanı motoru, gerçek migration aracı, gerçek mesaj formatları) çalıştığını doğrular. ORM model değişmiş ama migration olmamış gibi sorunlar burada yakalanır.
Uçtan uca testler hizmetler arası iş akışlarını taklit eder: veri oluştur, migrate et, API’ler üzerinden geri oku ve aşağı akış tüketicilerin hala doğru davrandığını doğrula.
Şema evrimi sınırlarda bozulma yaratır. Hem taraflarda çalışacak sözleşme testleri ekleyin:
Migrasyonları deploy edeceğiniz gibi test edin:
Küçük bir fixture seti saklayın:
Bu fixture’lar gerilemeleri görünür kılar, özellikle AI tarafından üretilen kod alan adlarını, istekliliği veya formatı ince ince değiştirdiğinde.
Şema değişiklikleri nadiren dağıtıldıkları anda yüksek sesle başarısız olur. Genellikle başarısızlık, parsing hatalarında artış, bilinmeyen alan uyarıları, eksik veri veya arka plan job’larının geride kalması şeklinde yavaşça görünür. İyi gözlemlenebilirlik, bu zayıf sinyalleri hâlâ rollout’u durdurabileceğiniz zamanda eyleme dönüştürür.
Temel uygulama sağlığının yanında şema-özgü sinyaller ekleyin:
Anahtar nokta, önceki vs sonraki karşılaştırması yapmak ve istemci sürümü, şema sürümü ve trafik segmenti (canary vs stable) bazında dilimlemektir.
İki pano görünümü oluşturun:
Uygulama davranışı panosu
Migration ve arka plan job panosu
Eğer expand/contract rollout yapıyorsanız, eski vs yeni şema ile okuma/yazma ayrımını gösteren bir panel ekleyin ki bir sonraki faza geçmek güvenli olsun.
Verinin düşürüldüğünü veya yanlış okunduğunu gösteren durumlarda sayfa açın:
Ham 500’ler üzerine gürültülü alarmlar yerine, uyarıları şema sürümü ve endpoint gibi etiketlerle ilişkilendirin.
Geçiş sırasında loglara şunları dahil edin:
X-Schema-Version header, mesaj meta verisi alanı)Bu tek detay, farklı servisler veya model sürümleri aynı anda çalışırken "bu payload neden başarısız oldu?" sorusunun yanıtını dakikalar içinde verir.
Şema değişiklikleri iki şekilde başarısız olur: değişiklik kendisi yanlış olabilir veya çevresindeki sistem beklenenden farklı davranır (özellikle AI tarafından üretilen kod ince varsayımları getirdiğinde). Her durumda, her migration göndermeden önce bir geri alma hikâyesi olmalı—hatta bu hikâye “geri alma yok” olsa bile.
"Geri alma yok" seçimi, kolon düşürme, kimlikleri yeniden yazma veya kayıplı normalizasyon gibi geri döndürülemez değişikliklerde geçerli olabilir. Ancak "geri alma yok" bir planın olmadığı anlamına gelmez; forward fix, restore ve containment yönünde bir plan gerektirir.
Özellik bayrakları / konfigürasyon kapıları: Yeni okuyucuları, yazarları ve API alanlarını bir bayrakla sarmalayın ki yeni davranışı redeploy etmeden kapatabilesiniz. Bu, AI tarafından üretilen kod doğru sözdizimsel ama anlamsal olarak yanlış olduğunda özellikle faydalıdır.
Dual-write’ı devre dışı bırakın: Expand/contract aşamasında hem eski hem yeni şemaya yazıyorsanız bir kill switch tutun. Yeni yazma yolunu kapatmak, farkı büyütmeyi durdurur.
Sadece yazarları değil okuyucuları da geri alın: Birçok olay, tüketicilerin yeni alanları veya tabloları erken okumaya başlamasıyla olur. Servisleri önceki şema sürümüne veya yeni alanları yoksayacak şekilde kolayca döndürebilin.
Bazı migrasyonlar temizce geri alınamaz:
Bunlar için yedekten geri yükleme, olaylardan yeniden oynatma veya ham girdilerden yeniden hesaplama planları yapın—ve bu girdilerin gerçekten mevcut olduğunu doğrulayın.
İyi değişim yönetimi geri alma olasılığını nadir yapar—ve geri alma gerektiğinde kurtarmayı sıkıcı işler haline getirir.
Eğer ekibiniz AI destekli hızlı iterasyon yapıyorsa, bu uygulamaları güvenli deneyimi destekleyen araçlarla eşleştirmek faydalıdır. Örneğin, Koder.ai, değişiklik tasarımı için planning mode ve yanlışlıkla bir sözleşmeyi kaydıran değişiklikte hızlı kurtarma için snapshots/rollback özellikleri sunar. Hızlı kod üretimi ile disiplinli şema evrimi birlikte kullanıldığında, üretimi bir test ortamı gibi değerlendirmeden daha hızlı ilerlemenizi sağlar.