CQRS (Command Query Responsibility Segregation), okuma ve yazma işlemlerini ayırarak sistemlerin daha hızlı ve ölçeklenebilir olmasını sağlayan bir mimari desendir. Özellikle yüksek trafikli ve karmaşık iş mantığına sahip projelerde, geleneksel CRUD yapısının sınırlarını aşmak için etkili bir çözümdür. Ancak, her projede uygulanması gerekmez ve gereksiz karmaşıklık yaratabilir.
CQRS (Command Query Responsibility Segregation), modern backend sistemlerde performans ve ölçeklenebilirliğin kritik olduğu durumlarda giderek daha sık kullanılan bir mimari desendir. Kısaca özetlemek gerekirse, CQRS veri okuma ve yazma işlemlerini ayırmayı önerir; klasik CRUD yaklaşımında olduğu gibi her işlemi aynı şekilde ele almak yerine, okuma ve yazma farklı şekilde tasarlanır.
İlk bakışta bu durum karmaşık gibi görünebilir: Zaten çalışan bir şeyi neden ayıralım? Ancak gerçek projelerde okuma ve yazma operasyonlarının gereksinimleri çok farklıdır. Örneğin, bir sistem binlerce okuma isteği alırken, yazma işlemleri çok daha az olabilir. Ya da yazma işlemlerindeki iş kuralları karmaşıklaştıkça, hızlı veri çekimi zorlaşır.
CQRS burada devreye girerek sistemin her bir parçasını ayrı ayrı optimize etmeye olanak tanır: Yazma işlemleri için karmaşık mantık, okuma işlemleri için ise hız ve kullanım kolaylığı ön plana çıkarılır.
CQRS (Command Query Responsibility Segregation), sistemi iki ana parçaya bölen bir desendir:
Ana fikir, okuma ve yazma işlemlerinin aynı veri modeliyle yapılmaması gerektiğidir.
Klasik CRUD mimarisinde her şey tek bir katmandan yürür: Aynı model hem veri oluşturma, hem güncelleme hem de okuma işlemlerini üstlenir. Bu başlangıçta kolaydır, ancak zamanla sınırları ortaya çıkar.
CQRS ise şu yaklaşımı önerir:
Örneğin:
Bu ayrım sayesinde:
Sonuç olarak, tek bir evrensel model yerine iki ayrı model ortaya çıkar:
İki model yapısı, projenin ihtiyaçlarına göre tamamen farklı tasarlanabilir.
CQRS'nin temelinde güçlü bir fikir yatar: Veri değiştirme ve okuma işlemleri hem mantıksal hem de mimari olarak ayrılır. Yani sistem, komutları ve sorguları farklı şekillerde işler.
Komutlar, sistemin durumunu değiştiren işlemlerden sorumludur. Bunlar:
Komutlar her zaman bir değişiklik niyeti taşır:
Örneğin: CreateOrderCommand - sipariş oluşturma komutu.
Önemli: Komutlar veri okumak için kullanılmaz. Görevleri sadece sistemi değiştirmektir.
Sorgular, okuma işlemlerini temsil eder:
Örneğin: GetOrdersQuery - sipariş listesini almak.
CQRS'te sorgular, hızlı veri çekimi için özel olarak hazırlanmış ayrı bir veri modelini kullanabilir:
CQRS'in temel özelliği iki modelin (write model ve read model) olmasıdır:
Write Model:
Read Model:
Örneğin, bir e-ticaret sitesinde:
Asenkronluk nedeniyle, read modeldeki veriler hemen güncellenmeyebilir. Buna eventual consistency (gecikmeli tutarlılık) denir.
Böyle bir yaklaşım esneklik sağlar, fakat daha dikkatli bir mimari gerektirir.
CQRS'in değerini anlamak için onu klasik CRUD (Create, Read, Update, Delete) yaklaşımıyla karşılaştırmak gerekir.
CRUD'da tüm işlemler için tek bir veri modeli kullanılır:
Genellikle:
Örneğin, "Users" tablosu hem yazma hem okuma hem de güncelleme için kullanılır. Özellikle proje başında bu çok pratiktir.
CQRS sorumlulukları ayırır:
Avantajları:
Örneğin:
Özetle:
CQRS tamamen CRUD'un yerine geçmez - daha çok, basit modellerin yetmediği durumlar için sonraki mimari adımı sunar.
CQRS sadece yöntemleri ayırmak değil, aynı zamanda verinin saklanma, işlenme ve iletilme şekline dair bütünsel bir değişikliktir.
Basit CQRS uygulamalarında tek bir veritabanı farklı modellerle kullanılabilir. Daha ileri seviyede ise veri fiziksel olarak ayrılır:
Bu yaklaşım şunları sağlar:
Örneğin:
CQRS'de okuma ve yazma için modeller tamamen farklı olabilir.
Write Model:
Read Model:
Örnek: Karmaşık JOIN'ler yapmak yerine read modelde şu veriler doğrudan tutulabilir:
Bu, sorgu hızını ciddi şekilde artırır.
CQRS'de, modeller arasındaki veri senkronizasyonu anlık değildir.
Böylece eventual consistency ortaya çıkar: Veri geçici olarak eski kalabilir. Bu CQRS için normaldir, ama sistemin buna hazırlıklı olması gerekir.
Tipik bir CQRS sistemi şöyle görünebilir:
Daha büyük sistemlerde ayrıca şunlar eklenebilir:
CQRS'i tüm sistemde bir anda uygulamak şart değildir. Çoğu zaman öncelikle mantıksal ayrım yapılır, fiziksel ayrım veya ileri özellikler ihtiyaca göre eklenir.
CQRS, Event Sourcing deseniyle sıkça birlikte anılır. Her ne kadar farklı desenler olsa da, özellikle karmaşık sistemlerde birbirini tamamlar.
Klasik sistemlerde verinin sadece mevcut durumu saklanır: Örneğin "kullanıcı bakiyesi = 1000". Event Sourcing'de ise durumu oluşturan tüm olaylar tutulur:
Güncel durum, bu olayların toplamı olarak hesaplanır.
Ancak bu yaklaşım mimariyi ciddi şekilde karmaşıklaştırır ve deneyim gerektirir. Her projede gerekli değildir; çoğu zaman tek başına CQRS yeterlidir.
CQRS çok güçlü avantajlar sunar, ancak ek karmaşıklık da getirir. Uygulamadan önce hem avantajları hem dezavantajları iyi değerlendirilmelidir.
CQRS ne "daha iyi" ne de "daha kötü"dür; doğru şartlarda kullanıldığında değer katar.
CQRS her projede uygulanması gereken bir desen değildir. Doğru yerde kullanıldığında avantaj sağlar.
CQRS okuma işlemlerini ayrı bir modele taşıyarak hız ve ölçeklenebilirlik getirir. Ana veritabanındaki yük azalır.
CQRS ile bu mantık izole edilebilir ve anlaşılır hale gelir.
CQRS ile veri yazımı güvenli, veri okuma ise hızlı ve kolay yapılır.
Modern sistem mimarisinde CQRS çok iyi uyum sağlar. Bu yaklaşımı daha derinlemesine keşfetmek için Mikroservisler ve Monolitler: 2025 için Mimari Karşılaştırma başlıklı makaleye göz atabilirsiniz.
Bu gibi durumlarda CQRS gereksiz yere geliştirme sürecini zorlaştırır.
Ana kriter: Eğer CRUD yaklaşımı yük veya karmaşıklık nedeniyle tıkanıyorsa, CQRS düşünülmelidir.
CQRS'e geçiş için tüm sistemi baştan yazmak gerekmez. Çoğu zaman adım adım, problemli alanlardan başlanır.
En mantıklı yol hepsini bir anda değiştirmemektir. Şunlarla başlanabilir:
Bu aşamada bile CQRS'in faydaları görülmeye başlar.
CQRS kod seviyesinde de uygulanabilir:
Örneğin:
Bu, kodun daha iyi yapılandırılmasına ve sorumlulukların ayrılmasına olanak tanır.
Sistem büyüdükçe ek olarak şunlar eklenebilir:
Not: Sadece gereklilik olduğunda bu adımlar atılmalıdır.
CQRS evrimsel bir mimari adımdır; başlangıç noktası değildir. Gücü, parça parça uygulanabilmesindedir.
CQRS, okuma ve yazma işlemlerini ayırarak sistemlerin daha hızlı, esnek ve ölçeklenebilir olmasını sağlayan bir mimari desendir. Özellikle yüksek yük ve karmaşık iş mantığı olan projelerde, klasik CRUD'un sınırlarını aşmak için idealdir.
Bununla birlikte CQRS, her proje için uygun değildir. Basit sistemlerde gereksiz yere karmaşıklık ve hata riski oluşturabilir. Bu yüzden, CQRS'i gerçekten çözüm sunabileceği durumlarda kullanmak gerekir.
Özet seçim rehberi:
En iyi yaklaşım, aceleci olmadan CQRS'i adım adım, fayda sağlayacağı alanlardan başlatarak uygulamaktır.