AI Prototipinden Production Şemasına: Veri Modeli ve Migration Stratejisi
Production veri modeli, mevcut JSON'u SQL tablosuna çevirmek değildir. Önce domain gerçeğini tanımlar, sonra mevcut veriyi kaybetmeden o gerçeğe kademeli olarak taşırsınız.
Prototip aşamasında veri modelinin görevi fikri doğrulamaktır. Bir alan JSON içinde tutulabilir, ilişki id yerine metinle kurulabilir, aynı kavram farklı tablolarda farklı isimlerle yaşayabilir. Kullanıcı sayısı ve mutation çeşitliliği arttığında bu esneklik sessiz bir borca dönüşür.
Migration, tablo değiştirme işi değil; eski gerçeklikten yeni gerçekliğe kontrollü geçiş protokolüdür.
1. Önce mevcut şemayı değil domain'i modellemek
Mevcut tablo yapısını production modelinin başlangıç noktası değil, gözlem verisi olarak kullanırım. Kullanıcı hangi varlıklarla çalışıyor? Hangi kayıt kime ait? Hangi ilişki zorunlu? Hangi olay tekrar uygulanamaz? Bu sorular cevaplanmadan normalize etmek yalnızca kolonları yeniden düzenler.
type DomainInvariant = { entity: string; owner: "user" | "workspace" | "system"; uniqueBy: string[]; requiredRelations: string[]; deletion: "restrict" | "cascade" | "soft";};2. Constraint'leri UI varsayımından database garantisine taşımak
Bir form aynı slug'ı iki kez üretmiyor diye slug unique değildir. UI boş project_id göndermiyor diye ilişki zorunlu sayılmaz. Production şemasında kritik doğruları UNIQUE, NOT NULL, FOREIGN KEY, CHECK ve gerektiğinde database function seviyesinde açıkça tanımlarım.
alter table projects alter column owner_id set not null;
alter table projects add constraint projects_owner_slug_unique unique (owner_id, slug);
alter table tasks add constraint tasks_project_fk foreign key (project_id) references projects(id) on delete cascade;3. Kimlik ve sahiplik modelini migration'dan önce çözmek
RLS veya authorization sonradan eklenen bir katman değil, veri modelinin parçasıdır. Kayıt user_id ile mi, workspace_id ile mi, yoksa her ikisiyle mi sahipleniliyor? Bu karar net değilse migration sırasında backfill edilen ownership verisi ileride güvenlik açığına dönüşebilir.
4. Expand → migrate → contract
Canlı sistemlerde tek migration içinde eski kolonu silip yeni kolonu zorunlu yapmak risklidir. Önce yeni yapıyı eklerim, uygulamayı iki yapıyla uyumlu hale getiririm, veriyi backfill ederim, gözlemlerim ve ancak sonra eski alanı kaldırırım.
EXPAND -> yeni kolon / tablo / index ekleMIGRATE -> backfill + doğrula + gerekirse dual-writeCUTOVER -> okumayı yeni modele geçirCONTRACT -> eski alanı ve uyumluluk kodunu kaldır5. Backfill'i bir script değil operasyon olarak düşünmek
Bin satırlık local veri ile milyonlarca production kaydı aynı şekilde taşınmaz. Batch boyutu, lock süresi, retry, idempotency ve gözlemlenebilirlik planlanmalıdır. Backfill yeniden çalıştırıldığında veri bozulmamalı ve hangi kayıtların tamamlandığı görülebilmelidir.
- Migration öncesi veri dağılımını ve null oranlarını ölç.
- Büyük update'leri batch'lere böl.
- Her batch'i idempotent tasarla.
- Yeni constraint'i backfill tamamlanmadan zorunlu kılma.
- Cutover öncesi eski ve yeni modelden okunan sonuçları karşılaştır.
- Rollback'in schema ve application sürümleriyle uyumlu olduğundan emin ol.
6. Index'i tahminle değil query ile tasarlamak
Normalize edilmiş bir model otomatik olarak hızlı değildir. Gerçek sorgu pattern'leri, filtreler, sort alanları ve tenancy sınırları ölçülmelidir. Özellikle owner_id + status + updated_at gibi birlikte kullanılan alanlarda composite index kararı gerçek query planı üzerinden verilmelidir.
7. Rollback yalnızca SQL down migration değildir
Uygulama yeni kolona yazmaya başladıktan sonra eski deployment'a dönmek veri kaybı yaratabilir. Bu yüzden rollback'i deploy, schema ve veri uyumluluğu birlikte düşünerek tasarlarım. Bazı migration'larda gerçek rollback yerine forward-fix daha güvenlidir; önemli olan bunun release'ten önce bilinmesidir.
Production veri modelinin ölçütü
İyi şema yalnızca normalize değildir. Sahiplik açık, invariant'lar database tarafından korunuyor, kritik sorgular ölçülmüş, migration tekrar çalıştırılabilir ve uygulamanın bir önceki sürümüyle uyumluluk süresi tanımlanmışsa model production davranışına yaklaşmıştır.
Prototipten Production'a
Çalışan bir MVP'yi güvenilir ürüne dönüştürmek: production kontrolü, modüler refactor, veri migration'ı, audit, rewrite kararı ve release gate'leri.