“Şeması yok, hızlı ilerleriz” diyerek MongoDB seçen bir projeyi iki yıl sonra gördüm. Her okuma savunmacıydı: data?.user?.address?.city ?? null. Sebep basitti — hiçbir belge bir diğeriyle tam olarak aynı şekle sahip değildi. Şema kaybolmamıştı; sadece veritabanından çıkıp her okuma kodu satırına dağılmıştı.
”Şemasız” bir yanılgı
Şemasız veri diye bir şey yoktur. Verinin her zaman bir şekli vardır: bir kullanıcının e-postası, bir siparişin kalemleri, bir faturanın tarihi. Soru, şekil olup olmadığı değil; o şeklin nerede tanımlandığı.
İki seçenek var. Şema ya veritabanında durur ve veritabanı tarafından zorlanır; ya da uygulama kodunda durur ve herkesin ona uyduğu varsayılır. “Şemasız” demek, ikincisini seçmektir — şemayı silmek değil, onu zorlanmayan bir yere taşımak.
Şema nereye taşınır
Veritabanı şemayı zorlamayı bıraktığında, o iş ortadan kalkmaz; şu yerlere dağılır:
- Her okumaya. Kod, gelen belgenin beklenen alanlara sahip olduğunu artık varsayamaz; her alanı savunmacı biçimde kontrol eder.
- Her yazmaya. Doğru şekli yazdığınızın garantisi yoktur; yalnızca umut vardır.
- Dağınık doğrulama koduna. Veritabanının tek satırda yaptığı
NOT NULL, tip kontrolü, foreign key — hepsi elle yazılmış kontrollere dönüşür. - Ekibin kafasına. “O alan bazen string, bazen array” bilgisi, dokümante edilmemiş bir kabile bilgisi olur.
Şema bürokrasi değildir; veritabanının sizin yerinize ücretsiz yaptığı doğrulamadır. Onu reddetmek faturayı silmek değil, başka birine kesmektir.
Çarpılan krizler
“Şemasız” rahatlığıyla başlayan projeler er ya da geç şunlara çarpar:
- Veri drift’i. Zamanla belgenin on farklı sürümü aynı koleksiyonda yaşar. 2023’te yazılan kayıt, 2026’da yazılanla aynı şekilde değildir ve hiçbir migration bunu zorlamamıştır.
- Referans bütünlüğü yok. Var olmayan bir kullanıcıya işaret eden bir sipariş, veritabanı tarafından engellenmez. Yetim kayıtlar sessizce birikir.
- Migration bir uygulama işine dönüşür. İlişkisel dünyada tek bir
ALTER TABLEile yapılan şey, burada milyonlarca belgeyi tek tek gezen, batch’lenmesi gereken bir script olur.
Bunlar küçük projede görünmez; tam da projenin büyüdüğü, ekibin değiştiği, kimsenin “o alan neden bazen yok” sorusunu cevaplayamadığı anda patlar.
NoSQL’in gerçekten doğru olduğu yerler
Bu, NoSQL’e karşı bir yazı değil. NoSQL’in gerçek ve haklı kullanımları var:
- Tek bir primary’nin yazma kapasitesini aşan, gerçekten yatay ölçek gerektiren yükler — veri yoğunluklu sistemlerdeki en zor kırılma noktası.
- Doğası gereği gerçekten heterojen belgeler.
- Belirli erişim desenleri — saf key-value, wide-column, graph.
Tuzak NoSQL değil; NoSQL’i bu gerçek güçlerinden biri için değil, sadece “şema istemiyorum” diye seçmektir. Doğru araç, yanlış gerekçe.
Esneklik istiyorsanız PostgreSQL zaten veriyor
“Bazı alanlar esnek olsun” ihtiyacı gerçekse, bunun için tüm bütünlüğü feda etmeniz gerekmez. PostgreSQL’in jsonb sütunu, ilişkisel tablonun bütünlüğü içinde esnek bir belge alanı verir — PostgreSQL her şeye yeter mi yazısında değindiğim gibi. Sabit olan alanlar şema olarak kalır, gerçekten değişken kısım jsonb’de durur. İkisinin en iyisi, hem de tek sistemde.
Şema bir yük değil, bir kalkandır. Onu veritabanından kaldırdığınızda kaybolmaz — yalnızca sizi koruduğu yerden çıkıp, sizi koruyamayacağı yere taşınır.
“Şemasız” diye bir şey yoktur; yalnızca “şemayı kim zorluyor” sorusu vardır.

Yorumlar
Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.