İçeriğe geç
wedevit

12 Ağustos 2026 · 9 dk okuma · yazılım

İlhan Buğra Aslan

Mikroservise geçmeli miyiz? Monolit, modüler monolit ve doğru karar


Çoğu ekip için doğru cevap, iyi modüllere ayrılmış tek bir uygulamadır. Mikroservis mimarisi bir kod kalitesi çözümü değil, dağıtım bağımsızlığı çözümüdür: birbirinden bağımsız ilerleyen birden fazla ekibiniz varsa ve her biri diğerlerini beklemeden üretime çıkmak zorundaysa karşılığını verir. Sekiz kişilik tek bir ekipte ise aynı karar, bir uygulamanın karmaşıklığını on beş uygulamanın karmaşıklığına çevirir; kod hâlâ aynı ölçüde birbirine bağlıdır, sadece aradaki çağrılar artık ağ üzerinden geçmektedir. Aşağıda kararı verirken bakılacak ölçütler, ara yol olan modüler monolit ve bu geçişi yapıp geri dönen ekiplerin ölçülmüş sonuçları var.

Mikroservis nedir, ne değildir

Tanımın tek ayırt edici maddesi şudur: bir servis, diğerlerinden bağımsız olarak üretime çıkarılabiliyorsa mikroservistir. Küçük olması, ayrı bir depoda durması, konteyner imajı halinde paketlenmesi ya da REST konuşması bir şey ifade etmez. Ölçüt tek: A servisini değiştirip, B ve C'ye dokunmadan, onların ekiplerinden onay almadan, aynı gün yayına alabiliyor musunuz? Cevap hayırsa elinizde mikroservis mimarisi yok, uzaktan çağrılan modüller var.

Ayrılık noktası genellikle veritabanıdır. İki servis aynı tabloya yazıyorsa bağımsız değildir: birinin şema değişikliği diğerini kırar, ikisi birlikte yayınlanmak zorunda kalır. Kendi verisinin sahibi olmayan bir servis, bağımsız dağıtılamaz.

Dağıtık sistem bedava değil

Martin Fowler bu maliyete mikroservis primi diyor ve şu sonuca varıyor: prim önemli bir yük getirdiği için mikroservisler ancak yeterince karmaşık sistemlerde işe yarar. Primin içinde ağ gecikmesi, kısmi hata durumları, dağıtık izleme, servis keşfi, sürüm uyumluluğu ve veri tutarlılığı var. Fowler'ın MonolithFirst yazısındaki gözlem daha da nettir: duyduğu başarılı mikroservis hikayelerinin neredeyse tamamı, büyüyüp taşan bir monolitin parçalanmasıyla başlamış; sıfırdan mikroservis olarak kurulan sistemlerin neredeyse tamamı ciddi sıkıntıya girmiş.

Gerekçesi iki başlıkta toplanıyor. Birincisi, yeni bir uygulamada hangi özelliklerin gerçekten işe yarayacağını bilmiyorsunuz. İkincisi, servis sınırlarını doğru çizmek çok zordur ve servisler arasında işlev taşımak monolit içinde taşımaktan kat kat pahalıdır. Monolitte sınırı yanlış çizdiyseniz bir yeniden düzenlemeyle düzeltirsiniz. Servisler arasında yanlış çizdiyseniz iki ekibi, iki dağıtım hattını ve bir veri göçünü aynı anda koordine etmeniz gerekir.

Bir de faturaya yazılmayan kalem var. Her servis kendi dağıtım hattını, kendi izleme panosunu, kendi gizli anahtar setini ve kendi yama takvimini getirir. Bu iş, servis sayısıyla doğrusal artar.

Bu mimariyi kullanmak için bir eşiği geçmiş olmanız gerekiyor

Fowler mikroservise geçmeden önce üç yeteneğin yerinde olmasını şart koşuyor: yeni bir sunucuyu saatler içinde ayağa kaldırabilmek, hem teknik hem iş metriklerini kapsayan temel izlemeye sahip olmak, ve birkaç saati geçmeyen bir dağıtım hattı işletmek. Bunlar yoksa geçiş denemeyin. İyi haber şu ki üçü de monolit için de değerli yatırımlardır, yani sırayı bozmadan başlayabilirsiniz: küçük ekipler için CI/CD ve izlenebilirlik, SLO ve hata bütçesi yazıları bu iki başlığı ayrıntılandırıyor.

Önce şikayeti doğru teşhis edin

İki tamamen farklı problem aynı cümleyle masaya geliyor: "sistemi bölmemiz lazım." Ayırmak gerekiyor.

Bağlanmışlık şikayetleri: küçük bir değişiklik alakasız yerleri kırıyor, test paketi çok yavaş çalışıyor, yeni geliştirici üç ay boyunca kodda korkarak dolaşıyor. Bunlar modülerlik problemidir. Sistemi servislere bölmek bu problemi çözmez, ağ üzerine yayar.

Bağımsızlık şikayetleri: iki ekip aynı yayın penceresinde sıraya giriyor, bir modül diğerlerinden kat kat fazla kaynak istiyor, tek bir iş yükü için farklı bir çalışma zamanı veya dil gerekiyor, bir bileşenin erişilebilirlik hedefi diğerlerinden ciddi biçimde farklı. Burada servise ayırmak gerçekten cevap olabilir.

Ölçülebilir tek soru şudur: son üç ayda kaç yayın, başka bir ekibin onayını veya eşzamanlı dağıtımını gerektirdi? Bu sayı sıfıra yakınsa mimariniz sizi yavaşlatmıyor.

Modüler monolit: sınırları koy, süreci bölme

Shopify'ın anlattığı süreç bu ara yolun en iyi belgelenmiş örneği. 2016'da tek uygulama darboğaz haline gelmişti; masum görünen bir değişiklik alakasız testlerde bir yığın hataya yol açabiliyordu. Mikroservise geçmeyi değerlendirip vazgeçtiler ve gerekçelerini tek tek yazdılar: bakılması gereken ayrı test ve dağıtım hatları, servis başına altyapı yükü, servisler arası ağ gecikmesi, ihtiyaç duyulan veriye sınırın ötesinden erişmenin zorluğu, ve bağımlı servisler arasında koordineli dağıtım gerektiren yeniden düzenlemeler.

Bunun yerine tek uygulamanın içine katı sınırlar koydular. 2017 başında yaklaşık 6.000 Ruby sınıfını yazılım kavramlarına göre (model, controller) değil iş alanlarına göre (sipariş, kargo, envanter, faturalama) yeniden düzenlediler; bu tek ve büyük bir otomatik refactor ile yapıldı. Sonra sınır ihlallerini görünür kılmak için Wedge adlı bir iç araç yazdılar, ardından ihlalleri geliştirme aşamasında engelleyen Packwerk geldi. Packwerk iki tür ihlali yakalıyor: bağımlılık ihlali, yani bildirilmemiş bir paketin özel sabitine referans vermek; ve gizlilik ihlali, yani bir paketin özel sabitine dışarıdan referans vermek.

Bu yaklaşımın pratik değeri şudur: modülerliğin faydasını, yani anlaşılır sınırları, net sahipliği ve güvenli değişimi, dağıtık sistem bedelini ödemeden alıyorsunuz. Sınırlar kodda gerçekten zorunlu hale geldikten sonra bir modülü servise çıkarmak neredeyse mekanik bir işe dönüşür. Ters sıra çalışmıyor: sınırlarını çizmediğiniz bir sistemi servislere bölerseniz elinizde kalan şey dağıtık monolit olur.

140 servisten geri dönen ekip

Segment'in 2018'de yayımladığı hikaye bu kararın diğer yönünü gösteriyor. Her veri hedefi için ayrı bir servis ve ayrı bir kuyruk kurmuşlardı; sayı 140'ın üzerine çıktı, her biri kendi deposunda duruyordu. Ortak kütüphaneleri güncellemek 140'tan fazla servisi test edip dağıtmak anlamına geliyordu, o yüzden mühendisler bu yükü taşımamak için farklı sürümlerde kalmayı seçti ve bağımlılık sürümleri kod tabanları arasında birbirinden ayrıştı. Operasyonel yük her yeni hedefle doğrusal arttı; nöbetçi mühendis düşük trafikli bir hedefin yük artışı için gece uyandırılıyordu.

Tek bir servise döndükten sonra ölçtükleri sonuçlar şöyle: ortak kütüphanedeki bir değişiklik için 140'tan fazla dağıtım yerine tek bir dağıtım yeterli oldu ve bunu bir mühendis dakikalar içinde yapabiliyor; hedef başına birkaç dakika süren test paketi, tüm hedefler için milisaniyelere indi; mikroservis döneminde ortak kütüphanelerde bir yıl içinde 32 iyileştirme yapılmışken, dönüşün ardından gelen yıl 46 iyileştirme yapıldı. Ekibin kendi notu da önemli: altyapının bazı bölümlerinde mikroservis iyi çalışıyordu. Karar mimarinin tamamına değil, o iş yüküne verildi.

Prime Video örneği ne kanıtlıyor, ne kanıtlamıyor

2023'te çok dolaşan bir başlık vardı: Amazon mikroservisten monolite döndü, maliyeti yüzde 90 düştü. Gerçek daha dar, ama daha öğretici. Prime Video'da video ve ses kalitesini izleyen ekip, bileşenleri AWS Step Functions ile orkestra edilen dağıtık bir çözüm kurmuştu. İki darboğaz çıktı: durum geçişi sayısı hesap limitlerine dayandı, ve görüntü karelerini geçici olarak S3'te tutmak, çağrı sayısı yüksek olduğu için pahalıydı. Bileşenleri tek bir süreçte birleştirip veriyi bellek içinde taşıdıklarında iki darboğaz da kalktı ve maliyet yüzde 90 azaldı; ölçeklenmek için tek örnek yerine aynı süreci çoğaltarak çalıştırdılar.

Bu bir şirket politikası değişikliği değildi. Tek bir iç iş yükünün, kendisine uygun mimariye taşınmasıydı: veri yoğun ve adımları birbirine sıkı bağlı bir hattı ağ üzerinden parçalara bölmenin bedeli, kazancından büyüktü. Genelleştirilebilir ders şudur: mimari kararı iş yükü seviyesinde verilir, şirket seviyesinde verilmez.

En kötü sonuç dağıtık monolittir

Bu geçişin tipik başarısızlık biçimi ne mikroservis ne monolittir, ikisinin en kötü yanlarının birleşimidir. Belirtileri tanıdık: servisler ayrı ama hepsi aynı anda yayınlanmak zorunda, birden fazla servis aynı veritabanına yazıyor ve bir şema değişikliği zinciri kırıyor, her iş için ekipler arası koordinasyon gerekiyor. Sam Newman'ın verdiği gösterge pratik: şirkette birinin tam zamanlı işi yayın koordinasyonu haline gelmişse dağıtık monolitiniz var.

Ortaya çıkış nedeni genellikle aynıdır. Sistem iş alanlarına göre değil, mevcut kod sınırlarına göre bölünür; yani ne varsa olduğu gibi alınıp ayrı süreçlere dağıtılır. Böyle bir yapı monolitten daha yavaş ilerler, çünkü süreç içi çağrıların yerini ağ çağrıları almıştır ama koordinasyon ihtiyacı hiç azalmamıştır.

Asıl hedef mikroservis değil, bağımsız dağıtılabilirlik

DORA araştırması hedefi mikroservis olarak koymuyor, gevşek bağlı mimari olarak koyuyor ve bunun teknolojiden bağımsız olduğunu belirtiyor: ana bilgisayarla da mikroservisle de mümkün. Ölçütleri soru biçiminde sormak işe yarıyor. Büyük ölçekli tasarım değişikliklerini başka bir ekipten izin almadan yapabiliyor musunuz? İşi ekipler arası ince taneli koordinasyon olmadan bitirebiliyor musunuz? Ürününüzü bağımlı olduğunuz servislerden bağımsız olarak dağıtabiliyor musunuz? Testleri paylaşılan entegre bir ortama ihtiyaç duymadan istediğiniz zaman koşturabiliyor musunuz? Mesai saatlerinde, kayda değer bir kesinti olmadan yayına çıkabiliyor musunuz? Bu beş sorunun cevabı iyi kurulmuş bir monolitte de evet olabilir. Evet olduğu anda mikroservis tartışması kendiliğinden gündemden düşer.

Ölçek tarafında da mimarinin kendi kendine düzen kurmadığını gösteren bir örnek var. Uber 2020'de 2.200 mikroservisi 70 iş alanına gruplayan bir düzen yayımladı; ürün ekipleri onlarca alt servisi tek tek çağırmak yerine alanın geçidini çağırıyor ve yeni bir özelliği devreye almak için gereken temas noktası sayısı düştüğü için devreye alma süresi yüzde 25 ile 50 arasında azaldı. Yani servis sayısı arttıkça kaybedilen yapıyı, bir katman daha ekleyerek geri kazanmak gerekiyor.

Her yeni servis yeni bir yüzey

Servis sayısıyla birlikte güvenlik iş yükü de artıyor: servisler arası kimlik doğrulama, her serviste ayrı gizli anahtar ve erişim bilgisi yönetimi, yamalanması gereken daha fazla temel imaj, incelenmesi gereken daha fazla bağımlılık ağacı, iç ağda konuşan daha fazla uç. Beş servisi elle idare edebilirsiniz, otuz servisi edemezsiniz. Bölmeye karar verdiyseniz servis kimliğini ve sır yönetimini ilk günden merkezî bir yere koyun; sonradan eklemek her servis için ayrı iş çıkarır.

Bu haftaya sığan ilk adım

Karar vermeden önce üç ölçüm yapın. Bir: son 90 günün yayın kayıtlarına bakın, kaçı başka bir ekibin onayını ya da eşzamanlı dağıtımını gerektirdi? İki: modül bazında kaynak profili çıkarın, gerçekten diğerlerinden farklı ölçeklenmesi gereken bir parça var mı, hangisi? Üç: veri sahipliği haritası çizin, hangi tabloya kaç farklı modül yazıyor?

İlk sayı düşükse mimariniz sizi yavaşlatmıyor, sorun başka yerdedir; o durumda teknik borcu ölçmek ve önceliklendirmek daha çok işinize yarar. Üçüncü sayı yüksekse bölmeye hazır değilsiniz, önce veri sahipliğini ayırmanız gerekir. Somut bir başlangıç olarak monolit içinde iş alanlarına göre modül sınırlarını yazın ve bu sınırları statik analizle zorunlu kılın. İlk servisi ayırmaya karar verirseniz kenarda duran, kendi verisine sahip olan ve sık çağrılan bir yeteneği seçin; ayırma sırasını ve geri dönüş penceresini eski yazılımı kademeli yenileme yazısındaki yöntemle planlayın, servisler arasında verinin tutarlı kalması için de entegrasyonlarda veri senkronizasyonu yazısına bakın.


Bu konuda yardıma mı ihtiyacınız var?

iletişime geçtüm yazılar