IHS Strategic
Tüm Blog Yazıları
HowTo19 Eylül 2026•5 dk okuma

MongoDB ve Mongoose ile Ölçeklenebilir Veritabanı Mimarisi: Kapsamlı Kurulum Rehberi

MongoDB ve Mongoose kullanarak yüksek trafiğe dayanıklı, optimize edilmiş ve ölçeklenebilir bir veritabanı mimarisi kurmanın adım adım yollarını keşfedin.

S

Sistem Yöneticisi

Kıdemli Yazılım Mimarı

Giriş: Modern Uygulamalarda Ölçeklenebilir Veritabanı Mimarisi

Modern web ve mobil uygulamaların başarısı, artan kullanıcı trafiğini ve büyüyen veri hacmini kesintisiz yönetebilme yeteneğine bağlıdır. Günümüzde bir şirketin dijital strateji hedeflerini gerçekleştirebilmesi için güçlü, esnek ve yüksek erişilebilirlikli bir veri katmanı oluşturması kritik bir zorunluluk haline gelmiştir. NoSQL dünyasının lideri MongoDB ve Node.js ekosisteminin en popüler ODM (Object Data Modeling) aracı olan Mongoose, doğru yapılandırıldığında milyonlarca isteği düşük gecikme süreleriyle işleyebilecek bir altyapı sunar.

Son yıllarda mikroservis mimarileri, bulut yerel (cloud-native) çözümler ve gerçek zamanlı analitik gibi trendler doğrultusunda veritabanı tasarım yaklaşımları da evrilmiştir. Bu rehber içeriğinde; veri modellemeden indeksleme stratejilerine, bağlantı havuzu yönetiminden performans optimizasyonuna kadar ölçeklenebilir bir MongoDB ve Mongoose mimarisi kurmanın tüm adımlarını ele alacağız.

Adım 1: Doğru Veri Modelleme Yaklaşımını Seçme (Embedding vs. Referencing)

MongoDB'de ölçeklenebilirliğin temeli şema tasarımında atılır. İlişkisel veritabanlarının aksine NoSQL dünyasında verileri gömme (embedding) veya referans verme (referencing) arasında stratejik bir denge kurmanız gerekir.

1. Gömülü Belgeler (Embedded Documents / Denormalization)

Veriler sık sık birlikte okunuyorsa ve alt veriler 1:1 ya da sınırlı 1:N (örneğin bir kullanıcının en fazla 5 adresi olması) ilişkisine sahipse embedding tercih edilmelidir. Bu yaklaşım tek sorguda tüm veriyi çekerek ağ gecikmesini minimize eder.

2. Referans Verme (Normalized / Referencing)

Veri kümesi sınırsız büyüyorsa (örneğin bir ürünün binlerce yorumu olması) veya veriler çok sık güncelleniyorsa referans modeli (Normalized) kullanılmalıdır. MongoDB belgelerinin maksimum 16MB sınırına takılmaması için bu ayrım hayati önem taşır.

const mongoose = require('mongoose');
const { Schema } = mongoose;

// Gömülü Alt Şema
const AddressSchema = new Schema({
  street: { type: String, required: true },
  city: { type: String, required: true },
  zipCode: { type: String, required: true }
}, { _id: false });

// Ana Kullanıcı Şeması
const UserSchema = new Schema({
  name: { type: String, required: true, trim: true },
  email: { type: String, required: true, unique: true, lowercase: true, index: true },
  addresses: [AddressSchema], // Embedded
  organizationId: { type: Schema.Types.ObjectId, ref: 'Organization', required: true } // Referenced
}, { 
  timestamps: true,
  versionKey: false 
});

Adım 2: Bağlantı Havuzu (Connection Pooling) ve Sağlam Bağlantı Yönetimi

Yüksek eşzamanlı istek alan sistemlerde her sorgu için yeni bir bağlantı açmak ciddi bir CPU ve bellek yükü oluşturur. Mongoose üzerinde tekil (singleton) bir bağlantı ve optimize edilmiş bir bağlantı havuzu (connection pool) konfigüre edilmelidir.

İpucu: Sunucunuzun çekirdek sayısı ve beklenen eşzamanlı istek hacmine göre maxPoolSize değerini ayarlamak performans tıkanıklıklarını (bottlenecks) önler.
const connectDatabase = async () => {
  const options = {
    maxPoolSize: 50, // Eşzamanlı maksimum bağlantı sayısı
    minPoolSize: 10, // Havuzda hazır tutulacak minimum bağlantı
    serverSelectionTimeoutMS: 5000, // Sunucu yanıt vermezse zaman aşımı
    socketTimeoutMS: 45000, // Soket işlem zaman aşımı
    family: 4 // IPv4 tercih et
  };

  try {
    await mongoose.connect(process.env.MONGODB_URI, options);
    console.log('MongoDB bağlantısı başarıyla kuruldu.');
  } catch (error) {
    console.error('MongoDB bağlantı hatası:', error);
    process.exit(1);
  }
};

// Bağlantı olaylarını izleme
mongoose.connection.on('disconnected', () => {
  console.warn('MongoDB bağlantısı koptu. Yeniden bağlanmaya çalışılıyor...');
});

Adım 3: İndeksleme Stratejileri ve ESR Kuralı

Veritabanı sorgularının hızını belirleyen en önemli faktör indekslerdir. Doğru indeksler olmadan MongoDB, koleksiyondaki her belgeyi taramak (COLLSCAN) zorunda kalır.

  • Tek Alanlı İndeksler (Single Field Index): Sık aranan tekil alanlar (örneğin email, username) için kullanılır.
  • Bileşik İndeksler (Compound Index): Birden fazla alana göre filtreleme ve sıralama yapılıyorsa kullanılır. Burada ESR (Equality, Sort, Range) kuralı izlenmelidir.

ESR Kuralı Şeması:

  1. Equality: Tam eşleşme aranan alanlar en başa konur (örneğin status: 'ACTIVE').
  2. Sort: Sıralama yapılacak alan ikinci sıraya eklenir (örneğin createdAt: -1).
  3. Range: Aralık sorgusu yapılan alan en sona eklenir (örneğin age: { $gte: 18 }).
// ESR Kuralına Uygun Bileşik İndeks Tanımı
UserSchema.index({ status: 1, createdAt: -1, age: 1 });

// Metin Arama İndeksi
UserSchema.index({ name: 'text', biography: 'text' });

Adım 4: Okuma ve Yazma Optimizasyonları (Lean & Aggregation)

Mongoose, varsayılan olarak dönen her belgeyi tam teşekküllü bir Mongoose Document nesnesine dönüştürür (change tracking, getters/setters vb. ile birlikte). Sadece veri okuma işlemi yapılıyorsa bu durum gereksiz bellek tüketimine yol açar.

1. .lean() Kullanımı

Salt okunur sorgularda .lean() metodunu kullanmak sorgu hızını 3 ila 5 kat artırabilir ve RAM kullanımını önemli ölçüde düşürür:

const getActiveUsers = async () => {
  // Mongoose wrapper'ları olmadan saf JS nesnesi döner
  return await User.find({ status: 'ACTIVE' })
    .select('name email addresses')
    .lean();
};

2. Projeksiyon (Field Selection)

İstemciye yalnızca ihtiyaç duyulan alanları göndermek hem veritabanı I/O maliyetini hem de ağ bant genişliği kullanımını optimize eder.

Adım 5: İşlem Yönetimi ve Veri Bütünlüğü (Transactions)

Ölçeklenebilir mimarilerde finansal işlemler veya stok güncellemeleri gibi kritik süreçlerde veri bütünlüğü (ACID) şarttır. MongoDB 4.0+ ile gelen çoklu belge işlemleri (Multi-document Transactions), Mongoose üzerinden yönetilebilir.

const transferBalance = async (senderId, receiverId, amount) => {
  const session = await mongoose.startSession();
  session.startTransaction();

  try {
    await Account.updateOne({ userId: senderId }, { $inc: { balance: -amount } }, { session });
    await Account.updateOne({ userId: receiverId }, { $inc: { balance: amount } }, { session });

    await session.commitTransaction();
  } catch (error) {
    await session.abortTransaction();
    throw error;
  } finally {
    session.endSession();
  }
};

Adım 6: Sharding ve Replica Set Entegrasyonu

Veri miktarınız terabaytları aştığında tek bir sunucunun dikey ölçeklenmesi (Vertical Scaling) maliyet ve donanım sınırlarına takılır. Bu noktada yatay ölçekleme (Horizontal Scaling) stratejileri devreye girer:

  • Replica Sets (Çoğaltma Kümeleri): Veri yedekliliği ve yüksek erişilebilirlik (HA) sağlar. readPreference: 'secondaryPreferred' ayarı ile analitik veya ağır okuma yükleri ikincil düğümlere kaydırılabilir.
  • Sharding (Parçalama): Veriyi birden fazla sunucuya (shard) böler. Doğru bir Shard Key seçmek, verinin dengeli dağıtılması ve sorgu performansının korunması için zorunludur.

Özet ve Sonuç

Ölçeklenebilir bir MongoDB ve Mongoose mimarisi kurmak; yalnızca bir bağlantı dizesi yazmaktan ibaret değildir. Doğru veri modelleme, hedeflenmiş indeksleme, bağlantı havuzu optimizasyonu ve yalın (lean) sorgu stratejilerinin birleşimi, sisteminizin milyonlarca kullanıcıya kesintisiz hizmet vermesini sağlar. Bu teknik rehber içindeki pratikleri uygulayarak, projenizin gelecekteki büyüme gereksinimlerine hazır, yüksek performanslı ve sağlam bir veritabanı altyapısı inşa edebilirsiniz.