# Muhammet Şafak > Muhammet Şafak’ın kişisel marka sitesi — polyglot geliştirici ve sistem mimarı. 2008’den bu yana yazılım geliştiren bir mühendisin portfolyosu ve 2014’ten bugüne uzanan dönemsel geliştirme günlüğü. Blog, uygulamalı bir geliştirme günlüğüdür: PHP, Laravel, JavaScript, TypeScript, Go ve web geliştirme üzerine, bir geliştiricinin yıllar içindeki gelişimini yansıtan yazılar ve kariyer üzerine düşünceler. Sitede ayrıca açık kaynak projeler ve profesyonel özgeçmiş bilgileri yer alır. Yazılım mimarisi ve sistem tasarımı üzerine derinlemesine içerikler ise yazarın diğer sitesi sade.dev’dedir. İngilizce sürüm / English version: https://www.muhammetsafak.com.tr/en/llms.txt ## Site - [Ana Sayfa](https://www.muhammetsafak.com.tr/) - [Hakkımda](https://www.muhammetsafak.com.tr/hakkimda/): Muhammet Şafak kimdir, ne yapar. - [Blog](https://www.muhammetsafak.com.tr/blog/): Tüm blog yazıları. - [Portfolyo](https://www.muhammetsafak.com.tr/portfolyo/): Projeler. - [Labs](https://www.muhammetsafak.com.tr/labs/): Yedi geliştirme odağında ürünleşme yolundaki işler; her kaydın bugün ne yaptığı, türü, olgunluğu ve durumu yazılı. - [Research](https://www.muhammetsafak.com.tr/research/): Ölçüm, analiz, tarama ve derleme kayıtları; her kayıtta yöntem, ortam ve geçerlilik tarihi yazılı. - [Sor Bakalım](https://www.muhammetsafak.com.tr/sor-bakalim/): Ziyaretçilerin sorduğu, tek tek yanıtlanan sorular. - [Özgeçmiş](https://www.muhammetsafak.com.tr/ozgecmis/): Deneyim, eğitim, yetenekler. - [İletişim](https://www.muhammetsafak.com.tr/iletisim/) Her yazı ve sorunun düz Markdown sürümü, adresin sonuna `.md` eklenerek alınabilir — örneğin https://www.muhammetsafak.com.tr/blog/php-oldu-mu-2026-tablosu-veriyle.md ## Projeler - [Parantaj](https://www.muhammetsafak.com.tr/portfolyo/parantaj/): Kişisel ve kurumsal finansal yönetim platformu. Gelir-gider takibi, bütçe planlama, detaylı raporlama ve çoklu hesap yönetimi sunar. - [BabelQueue](https://www.muhammetsafak.com.tr/portfolyo/babelqueue/): BabelQueue, farklı dillerde yazılmış servislerin aynı kuyruğu serileştirme kilidine takılmadan paylaşmasını sağlayan, dilden bağımsız bir mesaj kuyruğu standardıdır. PHP'nin serialize()'ı gibi dile özgü formatlar yerine; her dilin doğal olarak okuyabildiği, schema_version 1'de dondurulmuş katı bir JSON zarfı tanımlar. Redis ve RabbitMQ üzerinde, sidecar ya da broker eklentisi olmadan, %2'nin altında ek yükle çalışır. - [CommitBrief](https://www.muhammetsafak.com.tr/portfolyo/commitbrief/): CommitBrief, git diff'leri üzerinde LLM destekli yerel kod incelemesi yapan, sağlayıcıdan bağımsız bir Go CLI aracıdır. Staged/unstaged değişikliklerden tek bir commit'e ya da PR tarzı üç noktalı aralıklara kadar her kapsamı; terminalden çıkmadan, diff'i dışarı sızdırmadan ve özelleştirilebilir proje kurallarıyla denetler. - [InitPHP](https://www.muhammetsafak.com.tr/portfolyo/initphp/): 30+ modüler PHP kütüphanesi (Router, Database, Cache, Mailer, Socket, ...) ile minimalist bir MVC çatısını (Framework3) tek bir ekosistem altında yayınladım; tim paketler Composer/Packagist'te MIT lisansıyla erişilebilir. Kod tabanı PHP-FIG standartlarına uyumlu; tip güvenliği, PHPUnit testleri, kapsamlı dökümanlar ve örneklerle destekleniyor. - [SignalLock](https://www.muhammetsafak.com.tr/portfolyo/signallock/): SignalLock, yanından ayrıldığında cihazını — yanında taşıdığın bir Bluetooth cihazını kullanarak — otomatik kilitleyen, gizlilik odaklı bir menü çubuğu uygulamasıdır. - [Looplio](https://www.muhammetsafak.com.tr/portfolyo/looplio/): Looplio — tekrar eden işleri, bakımları ve kontrolleri yeniden kullanılabilir şablonlar ve otomatik oluşturulan checklist'ler hâline getiren periyodik otomasyon platformu (Web + iOS + Android). - [sakinkal](https://www.muhammetsafak.com.tr/portfolyo/sakinkal/): sakinkal, Türkiye'de kriz hazırlığını korkudan ve abartıdan arındıran; rasyonel, kanıta dayalı ve çevrimdışı erişilebilir bir hazırlık kaynağıdır. Karmaşık bilgiyi herkesin uygulayabileceği net adımlara, kontrol listelerine ve rehberlere indirger. 'Panik yok, hazırlık var.' — kâr amacı gütmeyen, reklamsız, misyon odaklı bir yayın. - [TB1MSK](https://www.muhammetsafak.com.tr/portfolyo/tb1msk/): TB1MSK, lisanslı amatör telsiz operatörü olarak çağrı işaretim ve kişisel istasyon/kimlik sitemdir; ikinci aşamada amatör telsiz üzerine Türkçe içerik ürettiğim bir blog. Çatalca/İstanbul (KN41ff) merkezli istasyonumla VHF/UHF bantlarında FM, tekrarlayıcı ve APRS kullanıyor; acil durum haberleşmesi ve portatif operasyona odaklanıyorum. Radyo ile yazılımın kesişiminde: 'Havada sinyal, masada kod.' - [Erkekse](https://www.muhammetsafak.com.tr/portfolyo/erkekse/): Erkeklere özel moda, stil, bakım, yaşam ve sağlık tavsiyelerinin paylaşıldığı bir platformdur. Abonelik sistemi ile aylık olarak yayınlanan bir online dergi ile birlikte abonelerine özel içerikler ve kapsamlı rehberler sunuyor. ## Labs — Geliştirme - **AI destekli geliştirme** — LLM'in geliştirme sürecine girdiği yer: kod inceleme, statik analizle model karışımı, prompt yerine deterministik süzgeçler. - **Dağıtık sistem & mesajlaşma** — Kuyruklar, outbox, idempotent tüketim ve dilden bağımsız mesaj sözleşmeleri. - **Geliştirici araçları & CI** — CLI'lar, mimari sınırların derlemede zorlanması, kod sağlığını ölçen otomasyon. - **Eğitim ve Araştırma** — Bilgiyi öğretilebilir ve araştırılabilir kılan platformlar: sıralı müfredat, kaynak metin, dile duyarlı tam metin arama ve ölçme. - **Otomasyon & veri işleme** — Periyodik işler, entegrasyon hatları ve operasyonel veri akışları. - **Güvenlik & doğrulanabilirlik** — Sunucunun doğrudan göremediği olayların — fiziksel yakınlık, istemcide hesaplanan sonuç — kanıtlanabilir hâle getirilmesi. - **Topluluk & platform** — Topluluğun forumun dağınıklığına düşmeden bölünmesi: konu-özelinde kulüpler, paylaşılan veri modeli, web ve mobilin paralel yürümesi. - [academia.sh: teori ile sahadan gelen problem aynı derste durabilir mi?](https://www.muhammetsafak.com.tr/labs/academia/) [geliştiriliyor]: Ücretsiz ve herkese açık, metin merkezli bir öğrenme platformu; ders kitabının teorisiyle sektörde gerçekten karşılaşılan problemleri tek ders akışında tutuyor. — Şu an ne yapıyor: Ücretsiz ve kayıt duvarı olmayan bir öğrenme platformu olarak yayında: alan-müfredat-kurs-ünite-ders hiyerarşisi, tam metin arama, ilerleme takibi ve doğrulanabilir sertifika çalışıyor. Bilgisayar bilimleri müfredatını okumak isteyen herkes bugün kullanabilir. — Tür: web uygulaması — Olgunluk: beta — Odak: Eğitim ve Araştırma - [Qurandia: numarası tutmayan iki veri setini metnin parmak iziyle eşleştirmek](https://www.muhammetsafak.com.tr/labs/qurandia/) [geliştiriliyor]: Kur'an okumak, anlamak ve öğrenmek isteyenler için açık ve ücretsiz bir kaynak; Kur'an ve hadis merkezli araştırmayı tek çatı altında topluyor. — Şu an ne yapıyor: Kur'an ve hadis metinlerini birlikte okumaya ve aramaya açık, ücretsiz bir kaynak olarak yayında; harf düzeyinde parmak izi eşlemesi hadis koleksiyonlarında %91–99 kapsam veriyor. Kaynağa doğrudan bakmak isteyen okuyucu ve araştırmacı bugün kullanabilir. — Tür: web uygulaması — Olgunluk: alpha — Odak: Eğitim ve Araştırma - [Swipenor: skoru istemci hesaplarsa sunucu neye güvenir?](https://www.muhammetsafak.com.tr/labs/swipenor/) [geliştiriliyor]: Kaydırmalı doğru/yanlış bilgi yarışması; asıl mesele oyun değil, istemcinin ürettiği skoru imzayla doğrulanabilir kılmak. — Şu an ne yapıyor: Kaydırmalı doğru/yanlış bilgi yarışması bir mobil uygulama olarak çekirdek döngüsüyle uçtan uca çalışıyor; skoru istemci üretse de server_nonce ve HMAC imzasıyla sunucu tarafında doğrulanıyor. swipenor.com uygulamanın tanıtım sayfasıdır, oyunun kendisi değil. — Tür: mobil uygulama — Olgunluk: beta — Odak: Güvenlik & doğrulanabilirlik - [Garajdaş: model-özelinde topluluk, forumun dağınıklığı olmadan](https://www.muhammetsafak.com.tr/labs/garajdas/) [geliştiriliyor]: Her araç marka-modelinin kendi kulübü olduğu, ICE ile EV'yi aynı çatıda tutan Reddit-benzeri topluluk platformu; API, web ve mobil paralel yürüyor. — Şu an ne yapıyor: Her araç marka-modelinin kendi kulübü olduğu topluluk platformu; kimlik, içerik, bildirim ve moderasyon akışları tek şemalı API üzerinde yürüyor, web ve mobil istemciler aynı şemayı paylaşıyor. Aracının modeline özel bir topluluk arayan kullanıcı bugün katılabilir. — Tür: web uygulaması, mobil uygulama — Olgunluk: beta — Odak: Topluluk & platform - [SentryFixer: Sentry hatasını koda karşı okuyup düzeltme planı çıkarmak](https://www.muhammetsafak.com.tr/labs/sentryfixer/) [kararlı]: Bir Sentry issue'sunu çalışan koda karşı analiz eden, düzeltme planını diff ve regresyon testiyle sunan, onay almadan tek bir dosyaya dokunmayan Claude Code skill'i. — Şu an ne yapıyor: Bir Sentry issue'sunu çalışan koda karşı okuyup kök neden analizi ve düzeltme planı çıkarıyor; onay alınmadan tek bir dosyaya dokunmuyor. Claude Code kullanan ve prodüksiyon hatasını triyaj etmek isteyen herkes skill'i kurabilir. — Tür: açık kaynak — Olgunluk: sürüm adayı — Odak: AI destekli geliştirme - [Devrazzi: geliştirici haberini model katmanlarına eletmek](https://www.muhammetsafak.com.tr/labs/devrazzi/) [kararlı]: Yazılım ve AI haberini yerel Ollama ile eleyip üst katmanlarda DeepSeek, Gemini, OpenAI ve Claude'a devreden, TR/EN sentezi uçtan uca otomatik üretip yayınlayan içerik hattı. — Şu an ne yapıyor: Yazılım ve AI haberini yerel Ollama ile eleyip üst katmanlarda büyük modellere devrediyor, TR/EN sentezi kendi üretip yayınlıyor; web ve App Store sürümü canlı. Günlük geliştirici haberini tek akıştan takip etmek isteyen okuyabilir. — Tür: web uygulaması, mobil uygulama — Olgunluk: sürüm adayı — Odak: Otomasyon & veri işleme - [Aynı kuyruğu iki dilin serileştirme kilidine takılmadan paylaşması](https://www.muhammetsafak.com.tr/labs/babelqueue-lab/) [ürün oldu]: Dile özgü serileştirme yerine dondurulmuş bir JSON zarfı; polyglot kuyruk standardı BabelQueue'ya dönüştü. — Şu an ne yapıyor: Dondurulmuş JSON zarfı dört dilde — PHP, Python, Go, Node.js — aynı baytları okutuyor; sidecar ya da broker eklentisi gerekmiyor. Polyglot kuyruk kuran ekipler spesifikasyonu ve SDK'ları bugün kullanabilir. — Tür: açık kaynak — Odak: Dağıtık sistem & mesajlaşma - [Bluetooth yakınlığıyla ekran kilidi: 'var/yok' yetmiyor](https://www.muhammetsafak.com.tr/labs/signallock-lab/) [ürün oldu]: Yanındaki cihaz uzaklaşınca bilgisayarı kilitleyen yakınlık kilidi; menü çubuğu uygulaması SignalLock'a dönüştü. — Şu an ne yapıyor: Yanındaki cihaz uzaklaşınca macOS ekranını kilitliyor; karar ham "var/yok" sinyaline değil bir yakınlık değerlendirmesine dayandığı için sinyal dalgalanması yanlış kilit üretmiyor. Menü çubuğu uygulaması yayında, indirilip kullanılabilir. — Tür: açık kaynak — Odak: Güvenlik & doğrulanabilirlik - [Diff'i dışarı sızdırmadan yerel kod incelemesi](https://www.muhammetsafak.com.tr/labs/commitbrief-lab/) [ürün oldu]: Diff'i makineden çıkarmadan bir modele denetleten, sağlayıcıdan bağımsız Go CLI; CommitBrief ürününe dönüştü. — Şu an ne yapıyor: Diff hiç makineden çıkmadan yerel kod incelemesi yapıyor; `Provider` arayüzü sayesinde Anthropic, OpenAI, Gemini ve Ollama aynı sözleşmeyle takılıyor. İmzalı binary'ler yayında — diff'ini bir bulut sağlayıcısına vermek istemeyen herkes kurabilir. — Tür: açık kaynak — Odak: AI destekli geliştirme - [Kişisel ve kurumsal finansın aynı veri modelinde durması](https://www.muhammetsafak.com.tr/labs/parantaj-lab/) [ürün oldu]: Çok hesaplı gelir-gider takibini tek modelde toplayan finans çekirdeği; web + iOS + Android'de çalışan Parantaj'a dönüştü. — Şu an ne yapıyor: Tek hesap/işlem modeli çoklu hesap yönetimini, bütçeyi, hedefleri ve raporlamayı aynı çekirdekte taşıyor; web, iOS ve Android istemcileri yayında. Kişisel ve kurumsal finansını tek yerden takip etmek isteyen kullanabilir. — Tür: açık kaynak, web uygulaması, mobil uygulama — Odak: Otomasyon & veri işleme - [Tek başına da çalışan, birlikte de çalışan PHP paketleri](https://www.muhammetsafak.com.tr/labs/initphp-lab/) [ürün oldu]: Framework'e bağlanmadan çalışan modüler PHP kütüphaneleri; 39 paketlik InitPHP ekosistemine ve Framework3'e dönüştü. — Şu an ne yapıyor: 39 paketlik bir PHP kütüphane ailesi: Router, Database, Cache, Mailer, Socket ve diğerleri hem tek başına hem birlikte çalışıyor, hepsi Composer/Packagist üzerinden MIT lisansıyla dağıtılıyor. Framework'e bağlanmadan parça kullanmak isteyen PHP geliştiricisi bugün kurabilir. — Tür: açık kaynak — Odak: Geliştirici araçları & CI ## Research — Kayıtlar Bu bölümün tamamı düz Markdown olarak: https://www.muhammetsafak.com.tr/research.md - **Dil & çalışma zamanı** — Sürüm yükseltmelerinin, derleyici ve çalışma zamanı ayarlarının aynı iş üzerindeki farkı: JIT, opcache, GC ve bellek davranışı. Ölçümün yanında sürüm notu ve RFC çözümlemesi de buraya girer. - **Veritabanı & sorgu** — Index stratejisi, sorgu planı ve bağlantı yönetiminin gerçek veri hacmi altında ödediği bedel. Ölçümün yanında şema kararı ve migration sırası çözümlemesi de buraya girer. - **Servis & yük** — HTTP servisinin yük altındaki gecikme dağılımı, doyma noktası ve kuyruk davranışı — ortalama değil p95/p99. Ölçümün yanında backpressure, circuit breaker ve kuyruklama gibi örüntülerin çözümlemesi de buraya girer. - **Araç karşılaştırması** — Aynı işi yapan iki aracın ölçülebilir farkı: derleme süresi, çıktı boyutu, bellek ve geliştirici döngüsü. Ölçümün yanında ekosistem taraması — bakım durumu, sürüm sıklığı, topluluk büyüklüğü — de buraya girer. - **Arayüz performansı** — Gönderilen JS, ilk boya ve etkileşim gecikmesi; bir kolaylığın kullanıcıya kaç kilobayta mal olduğu. Ölçümün yanında tarayıcı desteği ve API kararlılığı çözümlemesi de buraya girer. - **Maliyet & kaynak** — Bir kararın faturaya yansıyan tarafı: CPU-saat, bant genişliği, depolama ve istek başına gerçek maliyet. Ölçümün yanında fiyatlandırma modeli çözümlemesi de buraya girer. - [Partial index on beş dakikada üç yüz seksen kat şişti — ve autovacuum bir kez bile gelmedi](https://www.muhammetsafak.com.tr/research/kuyruk-tablosunda-bloat-ve-autovacuum/): Sürekli churn altındaki bir kuyruk tablosunda partial index'in küçüklüğü kalıcı mı, ve varsayılan autovacuum ayarları ona yetişiyor mu? — Tür: Ölçüm — Bulgu: Canlı küme beş bin satırda sabit dururken partial index 0,1 MB'dan 38,2 MB'a çıktı — üç yüz seksen kat. Küçüklüğü canlı satır sayısından geliyor, şişme hızı iş hacminden, ve ikisi arasında hiçbir bağ yok. Composite index oransal olarak daha az şişti (%42) ama mutlak olarak daha çok (+126 MB) ve şişerken belleğe sığmayı bıraktı: gecikmesi 0,52 ms'den 61 saniyeye çıktı, kuyruğu 126 bine tırmandı. On beş dakikada 1,75 milyon ölü satır birikti ve autovacuum **bir kez bile koşmadı** — varsayılan eşik tablonun tamamına göre ölçekleniyor (50 + 0,2 × 10 milyon ≈ 2 milyon), churn ise küçük canlı kümede oluyor. — Metrikler: Partial index, 15 dakikada: 0,1 → 38,2 MB (380×) · Composite index, aynı sürede: 301 → 427 MB (+%42) · Autovacuum koşma sayısı: 0 · Composite gecikmesi, 900. saniye: 61.533 ms — Yöntem: Partial index ölçümüyle aynı tezgâh, aynı Postgres 17 ayarları, aynı 10 milyon ölü + 5.000 canlı satırlık tablo. Üç fark var, üçü de bu soruyu sorabilmek için zorunlu. Tüketici satırı `pending`'e geri koymuyor, `done` işaretliyor — sınanan iddia satırın index'ten DÜŞMESİYLE ilgili ve hiç düşmeyen satırda ölçülemez. Yanında sabit varış hızında (2.000/sn) bir üretici koşuyor, yani tablo önceki kaydın eksik ilan etmek zorunda kaldığı insert trafiğini de görüyor. Ve talep, `\gset` yerine alt sorgulu `UPDATE` biçiminde: kısıtsız bir tüketici kuyruğu bir saniyenin altında boşaltıyor ve `\gset` boş sonuçta istemciyi öldürüyor. Tüketici de üretici hızına bağlandı, böylece kuyruk derinliği sabit kalıyor — ve sabit kaldığı örneklenerek doğrulanıyor, varsayılmıyor. On beş saniyede bir tablo boyutu, index boyutu, kuyruk derinliği, ölü satır sayısı ve autovacuum sayaçları kaydedildi; strateji başına 60 örnek. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-22 — Veritabanı & sorgu - [Laravel'in preload eğrisi: 123 dosya, 1.912 dosyadan sekiz kat fazla kazandırıyor](https://www.muhammetsafak.com.tr/research/laravel-preload-egrisi/): Laravel için elle seçilmiş bir preload nereye kadar iner, ve her dilim ne kadar açılış bedeline mal olur? — Tür: Ölçüm — Bulgu: Eğri hacimle orantılı değil. İlk 1.592 dosya (Laravel çekirdeği) 30 ms kazandırıyor ve açılışa 1,2 saniye ekliyor. Sonraki 1.094 Symfony dosyası 9,5 ms kazandırıyor, bedava. Ondan sonraki **123 dosya** (psr, carbon) 15,7 ms kazandırıyor — kendinden önceki 1.094 dosyadan fazla. Ve son 1.912 dosya yalnız 1,8 ms kazandırıp açılışa 1,2 saniye daha yazıyor. Yani önceki kaydın tavan olarak ölçtüğü "hepsini derle", eğrinin başlangıç noktası dışındaki en kötü fiyat/performans bölgesi: 2.809 dosyada durmak 12,77 ms ve 1.514 ms açılış verirken, 4.721 dosya 10,96 ms için 2.691 ms istiyor. — Metrikler: Tatlı nokta: 2.809 dosya: 12,77 ms (−%81) · Aynı noktanın açılış bedeli: +1.132 ms · 123 dosyalık dilimin kazancı: 15,7 ms · Son 1.912 dosyanın kazancı: 1,8 ms — Yöntem: opcache ölçümüyle aynı imajlar, aynı PHP 8.4 derlemesi, aynı ölçüm noktası — konteynerin sunduğu ilk istek. Küratörlük elle seçilmiş bir sınıf listesi değil, Composer classmap'i üzerinde bir **yol filtresi**: elle seçilmiş liste tekrar edilemez, filtre edilebilir. Beş varyant kasıtlı olarak iç içe (framework ⊂ +symfony ⊂ +psr/carbon ⊂ hepsi), böylece eğri "şunu da ekleyince" diye okunuyor, dört bağımsız nokta olarak değil. Her varyant için taze konteyner, üç tekrar, medyan. Preload php-fpm'in master sürecinde koştuğu için bedeli konteynerin ilk 200 yanıtı verene kadar geçen sürede ölçülüyor; bu pencere nginx'in açılışını da içeriyor ama beş varyantta da aynı sabit. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-22 — Dil & çalışma zamanı - [Partial index kuyruk tablosunu kırk bir kat küçültüyor — planner onu seçtiği sürece](https://www.muhammetsafak.com.tr/research/partial-index-kuyruk-tablosu/): Milyonlarca ölü satır biriken bir Postgres kuyruk tablosunda partial index ne kazandırıyor, ve planner onu ne zaman seçmiyor? — Tür: Ölçüm — Bulgu: 10 milyon ölü satırda partial index saniyede 11.537 iş çıkarıyor, index'siz tablo 7. Composite index'le hız farkı küçük (%6,9) ama boyut farkı değil: 7,6 MB'a karşı 310,4 MB, ve partial tabloyla birlikte büyümüyor çünkü yalnız 5.000 canlı satırı indeksliyor. Asıl bulgu bunların hiçbiri: planner hazırlanmış bir deyimde generic plana geçtiği anda partial index tamamen devre dışı kalıyor — 11.752 tps 7'ye, 0,68 ms 1,1 saniyeye düşüyor. Bin altı yüz yetmiş üç kat. Aynı koşulda composite index etkilenmiyor. — Metrikler: Partial index, 10M ölü satır: 11.537 tps · Aynı tablo, index yokken: 7 tps · Index boyutu, partial / composite: 7,6 / 310,4 MB · Generic plana geçince: 11.752 → 7 tps (−1.673×) — Yöntem: Postgres 17, tek konteyner, sabitlenmiş ayarlar (shared_buffers 1 GB, work_mem 64 MB, autovacuum açık — kapatmak sayıları güzelleştirir ve cevabı bozardı). `jobs` tablosunda canlı küme her kademede sabit 5.000 `pending` satır; ölü satır 100 bin, 1 milyon ve 10 milyon. Her boyut bir kez seed edilip **template veritabanı** olarak donduruluyor ve her koşu ondan kopyalanıyor: her stratejiyi yeniden seed etmek ölçümlerden uzun sürer ve her seferinde farklı karışmış bir tablo verir, yani sayılar stratejinin etkisini değil seed'in gürültüsünü taşırdı. Seed yüklerken `ORDER BY random()` ile karıştırıyor — sıralı tek geçiş, fiziksel düzeni `created_at`'e eşitleyip her index taramasını neredeyse sıralı okumaya çevirir ve dört stratejiyi de eşit biçimde kayırır. Tüketici pgbench: Postgres'le geliyor, gecikmeyi ortalama değil yüzdelikle veriyor, ve standart araç olduğu için tartışma tezgâha değil index'e kalıyor. 8 istemci, 30 saniye, üç tekrar, medyan. Talep edilen satır `done` yerine yeni bir `created_at` ile `pending`'e dönüyor: kuyruğunu kurutan bir tüketici koşunun ikinci yarısında boş tablo ölçerdi. Her koşuda throughput'un yanında `EXPLAIN` planı, index boyutu, gerçekleşen index tarama sayısı ve bırakılan ölü satır kaydediliyor — tek başına throughput, seçilmiş index ile yok sayılmış index'i ayırt edemez. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-22 — Veritabanı & sorgu - [Postgres partial index'i generic plana çevirmedi: kırk çalıştırma, kırk custom plan](https://www.muhammetsafak.com.tr/research/planner-generic-plana-ne-zaman-geciyor/): Hazırlanmış bir deyimde Postgres partial index'li sorguyu kendiliğinden generic plana çeviriyor mu — yoksa bin altı yüz yetmiş üç katlık uçuruma ancak elle mi düşülüyor? — Tür: Ölçüm — Bulgu: Postgres geçişi reddediyor. Partial index'te kırk çalıştırmanın kırkı da custom plan — sayaç 40/0. Reddetmesinin sebebi tam olarak felaketin kendisi: generic plan partial index'i kullanamaz, bu yüzden tahmini maliyeti yüksek çıkar ve planner onu seçmez. Composite index ise ders kitabındaki gibi altıncı çalıştırmada geçiyor (5/35) ve hiçbir şey kaybetmiyor. Yani bin altı yüz yetmiş üç katlık uçurum gerçek ama çitli: ona düşmek için `plan_cache_mode = force_generic_plan` yazmak gerekiyor. — Metrikler: Partial index, generic plan: 0 / 40 çalıştırma · Composite index, geçiş: 6. çalıştırma · Partial, ilk 5 → son 5: 0,36 → 0,20 ms · Uçuruma düşmek için gereken: force_generic_plan — Yöntem: Aynı tezgâh, aynı 10 milyon ölü + 5.000 canlı satırlık tablo, üç index stratejisi. Her strateji için tek bir psql oturumunda tek bir hazırlanmış deyim kırk kez çalıştırıldı ve her çalıştırmadan sonra `pg_prepared_statements` sorgulandı — sayaçlar oturuma özgü olduğu için bu ölçüm pgbench'ten yapılamaz. Karar zamanlamadan çıkarsanmıyor, sayaçtan okunuyor: `custom_plans` ve `generic_plans` alanları planner'ın o çalıştırmada ne seçtiğini doğrudan söylüyor. Zamanlamalar çift geliyor (deyimin kendisi, sonra sayaç sorgusu) ve ayrıştırıcı yalnız ilkini alıyor. psql'in hizalı çıktısı sayaç değerini boşlukla dolduruyor; çıktı bu yüzden hizasız moda alındı — ilk koşu bu yüzden boş seri üretmişti. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-22 — Veritabanı & sorgu - [Chart.js'i nasıl import ettiğin, ziyaretçiye kaç kilobayt gönderdiğini belirliyor](https://www.muhammetsafak.com.tr/research/chartjs-import-stratejisi/): `chart.js/auto` ile seçmeli `Chart.register()` arasındaki fark, gerçek bir üretim derlemesinde kaç kilobayt? — Tür: Ölçüm — Bulgu: Seçmeli register, `chart.js/auto` yerine 9,7 kB gzip tasarruf ettiriyor (67,8 → 58,1 kB, %14,3). Asıl büyük düşüş kütüphanenin kendisinde değil, hiç kullanılmayan controller'ları dışarıda bırakmakta: yalnız çubuk grafiği kaydeden bir sayfa 46,0 kB'a iniyor — auto'nun üçte ikisi. — Metrikler: Seçmeli register: 58,1 kB (-14,3%) · chart.js/auto: 67,8 kB · Yalnız çubuk: 46,0 kB (-33,9%) · Sayfanın ada maliyeti: 65,3 kB — Yöntem: Aynı depo, aynı grafik bileşeni ve aynı içerik dosyasıyla dört ayrı `npx astro build` koşuldu; her koşuda yalnız `chart-render.ts`'in import/register satırları değiştirildi. Ölçülen şey Rolldown'ın ürettiği `dist/_astro/chart-render.*.js` parçasının `gzip -9` boyutudur. Derleme deterministik olduğu için tek koşu yeterli: aynı girdi aynı baytı üretti, dört strateji de iki kez koşulup aynı sonuç doğrulandı. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-19 — Arayüz performansı - [opcache preload deploy faturasını on dört kata kadar siliyor — ama yedi framework'ün beşi onu size vermiyor](https://www.muhammetsafak.com.tr/research/opcache-preload-deploy-faturasi/): `opcache.preload` açıkken yedi PHP framework'ünün deploy sonrası ilk isteği ne kadar sürüyor, bu kazanç neye mal oluyor, ve kimler ona erişebiliyor? — Tür: Ölçüm — Bulgu: Preload, soğuk ilk isteği 3,5 ile 14,2 kat arasında kısaltıyor: Symfony 35,58 ms'den 2,50 ms'ye, yani Phalcon'un çıplak seviyesine iniyor. Ama yedi adayın yalnız ikisi (Symfony, CodeIgniter) resmî bir preload dosyası yayınlıyor; kalan beşinde kazanç masada duruyor ve kullanıcının kendi yazmasını bekliyor. Yazmak da göründüğü kadar kolay değil: classmap'ten körlemesine üretilen preload Symfony'yi hiç ayağa kaldırmıyor, CodeIgniter'da ise elle seçilmiş resmî dosyadan (3,13 ms) daha kötü sonuç veriyor (5,29 ms). Ve bedel kaybolmuyor: Laravel'in classmap preload'ı ziyaretçiden aldığı 62 ms'yi php-fpm'in ayağa kalkışına 2.340 ms olarak yazıyor. — Metrikler: Symfony, soğuk ilk istek: 2,50 ms (−%93) · Resmî preload taşıyan aday: 2 / 7 · Laravel classmap, fpm bedeli: +2.340 ms · Elle seçim vs hepsini derle: 3,13 → 5,29 ms — Yöntem: Ayak izi ve yük ölçümleriyle birebir aynı imajlar, aynı PHP 8.4 derlemesi, aynı nginx + php-fpm yığını. Hiçbir imaj yeniden derlenmedi: opcache `conf.d`'yi sırayla okuduğu için çalışma anında mount edilen bir `02-*.ini`, imaja gömülü `00-bench-opcache.ini`'yi eziyor. Aday başına üç varyant koşuldu — preload yok, framework'ün kendi dosyası (konteyner içinde aranarak bulunur, elle yazılmaz), ve Composer classmap'indeki her sınıfı `opcache_compile_file` ile derleyen tek tip bir dosya. Her varyant için taze konteyner ayağa kaldırıldı ve **konteynerin sunduğu ilk istek** ölçüldü; hazırlık yoklamasının kendisi o istektir, çünkü ayrı bir yoklama ilk isteği harcayıp geriye sıcak bir ölçüm bırakıyor. Üç tekrar, medyan raporlanıyor. Preload'ın bedeli php-fpm'in ilk 200 yanıtı verene kadar geçen süreyle ölçülüyor; bu pencere nginx'in kendi açılışını da içeriyor ama üç varyantta da aynı sabit. Doğrulama: `preload yok` varyantı 20 Ağustos'ta yayınlanan bağımsız koşunun soğuk sayılarını ±%6 içinde yeniden üretiyor. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-22 — Dil & çalışma zamanı - [PHP ekosistemi yeni sürümü beklemiyor — ama desteklediğini de söylemiyor](https://www.muhammetsafak.com.tr/research/php-surum-destegi-beyani/): Bir PHP sürümü çıktıktan sonra en çok kurulan 500 Composer paketi onu desteklediğini ne zaman beyan ediyor, ve o beyan ne kadar bilgi taşıyor? — Tür: Tarama — Bulgu: Kurulumların %43,5'i üst sınırı hiç yazmayan bir kısıtla geliyor — `symfony/console` bugün `>=8.4.1` diyor, yani PHP 12'yi de desteklediğini iddia ediyor. Üst sınır yazan 280 paketin 247'si taahhüdünü sürüm daha doğmadan vermiş: `guzzlehttp/guzzle` 8.4'ü Ekim 2020'de, dört yıl önceden kapsamış. Geriye gerçekten bekleyen 33 paket kalıyor, medyanları 325 gün. Ham sayılar sürümden sürüme düşüp 'ekosistem hızlanıyor' diye okunuyor; eşit gözlem penceresinde bakınca trend tersine dönüyor (238 → 215 → 325 gün). — Metrikler: Üst sınırsız kısıtla gelen kurulum: %43,5 · Önceden taahhüt eden: 247 / 280 paket · Gerçekten bekleyenlerin medyanı: 325 gün · Eşit pencerede 8.2 → 8.4: 238 → 325 gün (+%37) — Yöntem: Packagist'in popülerlik uçlarından en çok kurulan 500 paket alındı, her birinin bütün kararlı sürümleri `repo.packagist.org/p2` metadata ucundan çekildi ve her sürümün taşıdığı `require.php` kısıtı okundu. Kısıtlar el yazımı bir okuyucuyla çözülüyor: npm'in `semver`'i Composer'la aynı sözdizimini farklı okuyor (`~8.1` Composer'da `>=8.1 <9.0`, semver'de `>=8.1.0 <8.2.0`), o yüzden ödünç alınmadı; okuyucu çözemediği kısıtı yutmuyor, fırlatıyor ve koşu sayıyor (bu turda 0). Bir kaydın hangi kovaya düştüğü üç elemeden geçiyor: sürümden sonra doğan paketler dışarıda (beklemiş olamazlar), kısıtsız sürümler her PHP'yi kabul ediyor sayılıyor (Composer'ı engellemiyorlar), ve gecikme yalnız üst sınır yazan kısıtlarda ölçülüyor. Sürümler arası karşılaştırma en kısa gözlem penceresine (639 gün) kırpılıyor. Tarama deterministik: aynı gün tekrar koşulduğunda aynı sayıları veriyor. — Güven: Yüksek güven — Doğrulama tarihi: 2026-08-22 — Dil & çalışma zamanı - [Bir PHP framework'ünü kurmanın sabit maliyeti: disk boyutu hiçbir şey söylemiyor](https://www.muhammetsafak.com.tr/research/php-framework-ayak-izi/): Yedi PHP framework'ü kurulduğunda diskte kaç megabayt, istek başına kaç dosya ve ilk istekte kaç milisaniye tutuyor — ve bu sayılardan hangisi gerçekten yük altındaki hızı öngörüyor? — Tür: Ölçüm — Bulgu: Disk boyutu hiçbir şey öngörmüyor: Yii2 en büyük vendor'a sahip (34,1 MB) ama istek başına yalnız 62 dosya yüklüyor — sahanın en azlarından. İstek başına dosya sayısı da öngörmüyor: CodeIgniter 96 dosya yükleyip 6.431 istek/sn veriyor, Symfony 224 dosya yükleyip 13.067 veriyor. Gerçekten ayrışan tek şey opcache soğukken ödenen ilk istek: Phalcon 2,2 ms, Laravel 72,2 ms — otuz üç kat. Bu, her deploy'dan sonra ilk ziyaretçinin ödediği derleme faturasıdır ve framework başına birkaç kilobayt değil, onlarca milisaniye tutuyor. — Metrikler: Soğuk ilk istek, en yavaş: 72,2 ms · Soğuk ilk istek, en hızlı: 2,2 ms · En büyük vendor: 34,1 MB · En çok yüklenen dosya: 359 — Yöntem: Yük ölçümüyle aynı imajlar, aynı PHP 8.4.24 derlemesi ve aynı production kurulumu. Her aday için taze bir konteyner ayağa kaldırıldı ve ölçülenler: `composer.lock` paket sayısı, `du -sb vendor`, `find vendor -type f | wc -l`, taze konteynerin karşıladığı **ilk** isteğin süresi (opcache boş — soğuk), ardından 5 saniyelik ısıtmadan sonra aynı isteğin süresi (sıcak), o istekte `get_included_files()` sayısı ve `memory_get_peak_usage(false)`. Boot süresi front controller'ın ilk satırından yanıt üretimine kadar ölçülüyor. `composer install` süresi, paket önbelleği önceden ısıtılmış bir konteynerde `--no-dev --optimize-autoloader --classmap-authoritative` bayraklarıyla üç kez koşulup medyanı alındı; ölçülen şey indirme hızı değil kurulum işi. Sayaçların hepsi deterministik ve tekrar edildiğinde aynı çıkıyor; tek gürültülü değer kurulum süresidir. — Güven: Yüksek güven — Ölçüm tarihi: 2026-08-20 — Araç karşılaştırması - [Yedi PHP framework'ü aynı yükte ölçtüm: fark, istek gerçek iş yaptıkça küçülüyor](https://www.muhammetsafak.com.tr/research/php-framework-yuk-testi/): Aynı donanımda, aynı PHP sürümünde ve aynı yedi rotayla, Laravel, Symfony, CodeIgniter, Yii2, Phalcon, Laminas ve Slim saniyede kaç isteği ne gecikmeyle karşılıyor? — Tür: Ölçüm — Bulgu: Boş bir rotada en hızlı ile en yavaş arasında 4,4 kat var (Slim 25.975, Laravel 5.966 istek/sn). Ama istek gerçek iş yapmaya başlayınca fark kapanıyor: veritabanından tek satır çeken bir istekte 3,7 kata, yirmi satır çekende 3,5 kata iniyor. Phalcon boş rotada üçüncüyken veritabanı isteğinde beşinciye düşüyor — C eklentisi olmak, sorgu beklerken bir işe yaramıyor. Asıl pahalı olan şey framework seçimi değil: Laravel'in kendi varsayılan web middleware grubu, aynı yanıtı 5.858'den 2.176 istek/sn'ye düşürüyor — yani tek bir varsayılan, framework'ler arasındaki farkın çoğundan daha pahalı. — Metrikler: Boş rota, en hızlı: 25.975 istek/sn · Boş rota, en yavaş: 5.966 istek/sn · Fark: boş rota → veritabanı: 4,4× → 3,7× · Laravel web grubu: −%63 — Yöntem: Yedi aday tek bir PHP 8.4.24 derlemesinde, birebir aynı opcache/php.ini/php-fpm havuzunda (pm=static, 8 worker) ve tek bir nginx server bloğunda koştu. Her aday kendi resmî iskeletinde, kendi dokümante ettiği production kurulumuyla (route/config/view cache, APP_ENV=prod, YII_DEBUG=false, Volt önderlenmiş) ve aynı composer bayraklarıyla kuruldu. Yedisi de tam elli rota kaydediyor; parametreli rota her zaman 47. sırada. Ölçüm sırasında yalnız tek bir aday koşuyor; php-fpm 0-3, nginx 4-5, MySQL 6-7 ve yük üreteci 8-11 çekirdeklerinde, ayrık. Her senaryo 64 bağlantıyla 15 saniye, 9 tekrar; adayların sırası her turda karıştırılıyor. Her ölçümün önünde ve arkasında, PHP'ye hiç uğramayan sabit bir nginx referansı örneklenerek o anda makinenin verdiği kapasite kaydediliyor. Raporlanan değer tekrarların en iyisidir: makine sakinleştirilemediği için girişim throughput'u yalnız aşağı çekebilir, donanım tavanının üstüne çıkaramaz. Toplam 546 yük ölçümü, 150 host örneklemesi, sıfır non-200 yanıt. — Güven: Orta güven — Ölçüm tarihi: 2026-08-20 — Servis & yük ## Sor Bakalım — Soru & Cevap Ziyaretçiler soruyor, yazar tek tek yanıtlıyor. Her kayıt tek bir soruya ayrılmış, kendi içinde anlamlı bir sayfadır. - [readonly value object'lerimde "withX" tarzı kopyalama metotlarını nasıl temiz yazarım?](https://www.muhammetsafak.com.tr/sor-bakalim/readonly-value-objectlerimde-withx-tarzi-kopyalama-metotlarini-nasil-temiz-yazarim/): readonly'de mutasyon yoktur; withX metodu property'yi değiştiremez, yeni bir instance dönmelidir. Taşınabilir yol new self + named arguments, PHP 8.5'te clone($this, [...]). - [Senior'dan staff'a geçişte işin doğası nasıl değişiyor?](https://www.muhammetsafak.com.tr/sor-bakalim/seniordan-staffa-geciste-isin-dogasi-nasil-degisiyor/): İş, iyi kod yazmaktan organizasyonun teknik kararlarını doğru yöne çevirmeye kayar. Etkinizi kendi commit'lerinizle değil başkalarının çıktısıyla ölçersiniz. - [Correlation ID'yi HTTP isteğinden kuyruğa düşen job'lara kadar nasıl taşımalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/correlation-idyi-http-isteginden-kuyruga-dusen-joblara-kadar-nasil-tasimaliyim/): ID'yi mesajın gövdesine değil taşıma metadata'sına (SQS message attribute) koyun ve her sınırda context'e enjekte edin. Kendi header'ınızı uydurmayın, W3C traceparent kullanın. - [Container'ı non-root çalıştırınca mount edilen storage dizinine yazamıyorum, izinleri nasıl çözerim?](https://www.muhammetsafak.com.tr/sor-bakalim/containeri-non-root-calistirinca-mount-edilen-storage-dizinine-yazamiyorum-izinleri-nasil/): Sorun izin bitlerinde değil, UID eşleşmesinde: mount'un sahibi ile container kullanıcısının UID'si uyuşmuyor. Çözüm chmod 777 değil, sahipliği hizalamak. - [OpenAPI şemasını önce mi yazmalıyım yoksa koddan mı üretmeliyim?](https://www.muhammetsafak.com.tr/sor-bakalim/openapi-semasini-once-mi-yazmaliyim-yoksa-koddan-mi-uretmeliyim/): Asıl sorun spec değil, drift. İster contract-first gidin ister koddan üretin; drift'i bitiren tek şey CI'da spec'i koda karşı doğrulamak ve tek doğru kaynak yapmaktır. - [Sadece 'pending' satırları taranan bir kuyruk tablosunda partial index kullanmalı mıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/sadece-pending-satirlari-taranan-bir-kuyruk-tablosunda-partial-index-kullanmali-miyim/): Evet — bu partial index'in ders kitabı örneği. WHERE status='pending' yalnızca birkaç bin satırı indeksler; küçük, cache-dostu, milyonlarca ölü satırı atlar. ORDER BY kolonunu da koyup SKIP LOCKED ile eşleyin. - [İç içe geçmiş servis çağrılarında context iptalini doğru şekilde nasıl yayarım?](https://www.muhammetsafak.com.tr/sor-bakalim/ic-ice-gecmis-servis-cagrilarinda-context-iptalini-dogru-sekilde-nasil-yayarim/): r.Context()'i her downstream çağrıya geçirin: QueryContext, NewRequestWithContext. Zincirin bir yerinde context.Background() kullanırsanız iptal kopar. Yaşaması gereken side-effect'ler için WithoutCancel. - [Integer cent olarak sakladığım para alanları için custom cast mı yoksa accessor/mutator mı kullanmalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/integer-cent-olarak-sakladigim-para-alanlari-icin-custom-cast-mi-yoksa/): Custom cast kullanın — VO ↔ kolon eşlemesi için tam da o var. Tek CastsAttributes sınıfı her modelde çalışır; accessor'lar model başına tekrar demektir. DB'de integer cent, modelde immutable Money. - [Tip güvenli koleksiyonlar için PHPStan generics mi kullanmalıyım, yoksa her tür için ayrı sınıf mı yazmalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/tip-guvenli-koleksiyonlar-icin-phpstan-generics-mi-kullanmaliyim-yoksa-her-tur/): PHP'de runtime generics yok; PHPStan generics tam da bunun için. Çoğu durumda list docblock'ları + katı PHPStan yeter. Davranış gerektiğinde tek bir generic Collection yazın. - [Orta seviyeden senior'a geçerken beklenen "daha geniş etki"yi nasıl gösteririm?](https://www.muhammetsafak.com.tr/sor-bakalim/orta-seviyeden-seniora-gecerken-beklenen-daha-genis-etki-yi-nasil-gosteririm/): "Daha geniş etki" daha büyük feature demek değil; etkinizin yazdığınız kodun ötesine, ekibe ve sistemlere ulaşmasıdır. Sahipsiz, bulanık bir problemi uçtan uca üstlenin. - [Loglarımda WARN ile ERROR seviyelerini ne zaman kullanacağıma dair net bir kural nasıl belirlerim?](https://www.muhammetsafak.com.tr/sor-bakalim/loglarimda-warn-ile-error-seviyelerini-ne-zaman-kullanacagima-dair-net-bir/): Tek kural: bu satır gece 3'te fire olduğunda birinin uyanması gerekir mi? Evetse ERROR, hayırsa WARN. ERROR kırdığınız bir sözdür; alert'i yalnızca ERROR'a bağlayın. - [Container'daki healthcheck'i Dockerfile'a mı yazmalıyım yoksa Kubernetes probe'larına mı bırakmalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/containerdaki-healthchecki-dockerfilea-mi-yazmaliyim-yoksa-kubernetes-probelarina-mi-birakmaliyim/): Kubernetes'te readiness/liveness'ı probe'lar sahiplenir; Dockerfile HEALTHCHECK'i kubelet tasarım gereği yok sayar. Ama Compose/düz Docker için HEALTHCHECK'i tutun, ikisini de aynı endpoint'e bağlayın. - [Public API'mde bir endpoint'i kullanımdan kaldırırken sunset sürecini nasıl yönetmeliyim?](https://www.muhammetsafak.com.tr/sor-bakalim/public-apimde-bir-endpointi-kullanimdan-kaldirirken-sunset-surecini-nasil-yonetmeliyim/): Para ödeyen partner'ların kullandığı bir endpoint'i asla sessizce kaldırmayın. Duyurulmuş, tarihli, ölçülen bir sunset yürütün: iletişim, response başlıklarıyla sinyal, kullanımı sıfıra izleme, sonra kaldırma. - [Sürekli güncellenen bir sessions tablosunda staging'de Index Scan alan sorgu production'da neden Seq Scan'e düşüyor, EXPLAIN ile nasıl teşhis ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/surekli-guncellenen-bir-sessions-tablosunda-stagingde-index-scan-alan-sorgu-productionda/): Aynı sorgu farklı plan alıyorsa, planner'ın maliyet tahmini farklıdır. Çok yazılan bir sessions tablosunda sorun neredeyse her zaman bayat istatistik + tablo bloat'udur, eksik index değil. - [Goroutine sızıntılarını uzun süre çalışan bir Go servisinde nasıl tespit edip önlerim?](https://www.muhammetsafak.com.tr/sor-bakalim/goroutine-sizintilarini-uzun-sure-calisan-bir-go-servisinde-nasil-tespit-edip/): Sürekli tırmanan goroutine sayısı = bir channel/lock/IO üzerinde sonsuza dek bloklanmış, iptal yolu olmayan goroutine'ler. Önce pprof ile dökümü alın, sonra spawn noktasının context'e uymasını sağlayın. - [Eloquent'te N+1'i erken yakalamak için Model::preventLazyLoading'i yalnızca lokalde mi yoksa production'da da mı açmalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/eloquentte-n-1i-erken-yakalamak-icin-model-preventlazyloadingi-yalnizca-lokalde-mi/): Lokal ve CI'da tam katı (throw) açın; production'da açık tutun ama fatal fırlatmak yerine log'layan bir handler'a bağlayın. Ham hâliyle production'a soğuk açmak latent bug'ları outage'a çevirir. - [PHP durum sabitlerimi backed enum'a taşımak kod tabanıma ne kazandırır, neyi zorlaştırır?](https://www.muhammetsafak.com.tr/sor-bakalim/php-durum-sabitlerimi-backed-enuma-tasimak-kod-tabanima-ne-kazandirir-neyi/): Aktif geliştirdiğiniz bir modül için değer: tip güvenliği, davranışı değerle taşıma ve aynı integer'larla DB uyumu kazanırsınız; bedeli sınırlardaki cast ve esneklik kaybıdır. - [API sunucumu Cloudflare Tunnel arkasına alıp 443'ü internete kapatmalı mıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/api-sunucusunu-cloudflare-tunnel-arkasina-mi-almali/): Evet, geçerli bir desen — Cloudflare Zero Trust de benzerini öneriyor. Ama tek yol bağımlılığını kabul etmek, uygulamayı 0.0.0.0'a bind etmemek, Cloudflare limitleri için queue kullanmak ve trusted proxy'leri ayarlamak şart. - [Hata oranı artınca otomatik rollback yapan (self-healing) deploy altyapısını nasıl tasarlarım?](https://www.muhammetsafak.com.tr/sor-bakalim/hata-artisinda-otomatik-rollback-ve-kendi-kendini-iyilestiren-deploy/): İnsanı dashboard başında bekletme — metrikleri deploy'a göm. Pattern: progressive delivery + otomatik analiz. Deploy sonrası canary ağırlığında bir bake süresi boyunca 5xx/latency'yi eşiğe karşı sorgula; aşılırsa son kararlı sürüme otomatik dön ve insanı uyar. - [Fintek API'ı için Canary mi, Blue-Green deployment mı?](https://www.muhammetsafak.com.tr/sor-bakalim/canary-mi-blue-green-mi-fintek-api-icin-deploy-stratejisi/): Rutin sürümlerde Canary'yi varsayılan yap (en küçük blast radius), instant rollback istediğin büyük cutover'lar için Blue-Green'i sakla. Asıl kilit nokta veritabanı: her iki strateji de geriye uyumlu (expand/contract) şema değişikliği şart koşar. - [CI/CD'de OIDC ve IAM Role ile şifresiz (secretless) AWS erişimini nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/ci-cd-de-secret-yonetimi-ve-oidc-ile-sifresiz-erisim/): GitHub Secrets'taki uzun ömürlü AWS anahtarlarını yok et. OIDC ile GitHub Actions'ı AWS IAM'de identity provider yap; trust policy'si repo/branch'e scope'lu bir role oluştur; workflow runtime'da kısa ömürlü STS credential alır — hiçbir yerde saklanan secret yok. - [CI/CD'de veritabanı göçlerini (migrations) güvenli nasıl çalıştırırım?](https://www.muhammetsafak.com.tr/sor-bakalim/ci-cd-de-veritabani-goclerini-guvenli-calistirmak/): Problem, şema değişikliğini eski kod hâlâ canlıyken deploy'a bağlamak. Çözüm: geriye uyumlu (expand/contract) migration'lar, app deploy'undan ayrılmış; kolonu nullable ekle, backfill'i ayrı throttle'lı adımda yap, eski'yi sonraki sürümde sil. - [DeployerPHP zero-downtime deploy'da OPcache'ten gelen 500 hatalarını nasıl engellerim?](https://www.muhammetsafak.com.tr/sor-bakalim/deployerphp-ile-sifir-kesinti-deploy-ve-opcache-temizligi/): Symlink değişimi atomik ama OPcache dosya yolundan beslenir; `current` yolu değişmediği için worker'lar eski bytecode'u sunmaya devam eder. Çözüm: symlink'i çevir, sonra PHP-FPM'i graceful reload et (restart değil), gerekirse `opcache_reset`. Octane'de kod bellekte tutulduğu için `octane:reload` şart. - [Docker imaj boyutunu multi-stage build ve distroless ile nasıl küçültürüm?](https://www.muhammetsafak.com.tr/sor-bakalim/docker-imaj-boyutunu-multi-stage-ve-distroless-ile-kucultmek/): 1.2 GB imaj, tüm build toolchain'ini üretime taşır — yavaş ve geniş saldırı yüzeyi. Multi-stage build ile derleme araçlarını ilk aşamada bırak; Go için final aşama `scratch`/distroless (birkaç MB), PHP için `fpm-alpine` + `vendor/`. Non-root çalış. - [Gitflow'dan Trunk-Based'e geçerken feature flag mimarisini nasıl konumlandırırım?](https://www.muhammetsafak.com.tr/sor-bakalim/gitflow-mu-trunk-based-mi-ve-feature-flag-mimarisi/): Gitflow'un uzun ömürlü dalları sürüklenir; merge'ler bu yüzden acı verir. Trunk-Based küçük değişiklikleri sürekli main'e alır, ama ancak bitmemiş özellik kullanıcıya ulaşamazsa işe yarar — feature flag'lerin işi tam budur. Deploy'u release'den ayırırsın. - [Go CLI aracını GoReleaser ve Homebrew ile çoklu platforma nasıl dağıtırım?](https://www.muhammetsafak.com.tr/sor-bakalim/go-cli-aracini-goreleaser-ve-homebrew-ile-dagitmak/): Bu tam olarak GoReleaser'ın işi. Tag push'unda tetiklenen bir GitHub Actions workflow'u cross-compile eder, GitHub Release'i yayımlar ve `brews:` bloğuyla Homebrew tap formülünü otomatik günceller. Kullanıcı `brew install` ile kurar. - [Hassas finansal veriyi şifrelerken anahtarı .env'de tutmak neden riskli — KMS/Vault ne sağlar?](https://www.muhammetsafak.com.tr/sor-bakalim/hassas-finansal-veriyi-sifrelemek-ve-anahtar-yonetimi-kms/): Anahtar `.env`'de, verinin yanındaysa sunucuyu ele geçiren saldırgan hem veriyi hem anahtarı alır; şifreleme neredeyse hiçbir şey kazandırmaz. KMS/Vault anahtarı veriden ayırır ve ham anahtarı uygulamaya hiç vermez (envelope encryption). TC kimlik/kart için tokenization tercih et; rotasyon + audit. - [Self-hosted CI/CD runner'larını nasıl izole eder, her çalışmadan sonra temizlenen (ephemeral) ortamı nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/self-hosted-ci-cd-runner-izolasyonu-ve-ephemeral-ortam/): Root ve Docker soketine sahip kalıcı bir runner, sunucu ele geçirilmesini bekleyen bir açıktır. İki ilke: ephemerality (her job taze, atılır bir ortamda çalışıp yok edilir) ve izolasyon (gerçek Docker soketi/root verme, unprivileged container/VM). Fork PR'larını çalıştırma. - [Terraform state'i S3 + DynamoDB locking ile nasıl güvenli yönetirim?](https://www.muhammetsafak.com.tr/sor-bakalim/terraform-state-yonetimi-s3-ve-dynamodb-ile-locking/): Local state + 3 kişi = bozulma ve race. State'i remote backend'e taşı: S3 (versiyonlu, şifreli) state dosyası için, DynamoDB ise state locking için. Apply'dan önce kilit alınır, ikinci apply bekler. Ortam başına ayrı state ve CI'dan apply. - [WAL arşivleme ve PITR ile felaketten saniyeler öncesine nasıl dönerim?](https://www.muhammetsafak.com.tr/sor-bakalim/veritabani-pitr-ve-wal-arsivleme-ile-felaket-oncesine-donmek/): Gecelik dump 18 saatlik RPO demek — üretimde kabul edilemez. PITR kapatır: periyodik base backup al, WAL'ı sürekli S3'e arşivle, kurtarırken base'i geri yükle ve `recovery_target_time` ile hatalı `DELETE`'in 3 saniye öncesine kadar replay et. pgBackRest/WAL-G kullan, restore'u prova et. - [Canlı tabloda dual-write ile sıfır kayıplı şema geçişini nasıl koordine ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/canli-tabloda-dual-write-ile-sifir-kayipli-sema-gecisi/): Bloklayan `ALTER TABLE` 20M satırı kilitler. Expand/contract yap: yeni kolonları nullable ekle, kod hem eski hem yeniye yazsın (dual-write), geçmişi throttled batch'lerle backfill et + doğrula, okumayı yeni şemaya geçir, sonra eskiyi düşür. Her adım bağımsız deploy edilebilir ve geri alınabilir. - [Zaman serisi verisi için TimescaleDB mi, InfluxDB mu?](https://www.muhammetsafak.com.tr/sor-bakalim/zaman-serisi-verisi-timescaledb-mi-influxdb-mu/): Günde 100M satır düz MySQL'de patlar: B-tree indeks ve tam tablo agregasyonu RAM'e sığmaz. SQL'de düşünüyor ve agregasyon istiyorsan TimescaleDB (hypertable + continuous aggregate + sıkıştırma) düşük sürtünmeli kazanç. InfluxDB yalnızca ayrı bir metrik stack istiyorsan. - [Redis'te canlı leaderboard için neden Sorted Set kullanmalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/redis-veri-tipleri-leaderboard-icin-sorted-set/): Skorları düz String'de tutup uygulamada sıralama — bu milyonlarca anahtar üzerinde okuma başına O(N log N). Sorted Set (ZSET) kullan: `ZADD` O(log N) güncelleme, `ZREVRANGE 0 99` zaten sıralı ilk 100, `ZREVRANK` O(log N) sıra. Yazarken sıralı tutar, okuma neredeyse sabit. - [CQRS'i ne zaman uygulamalı ve okuma/yazma modellerini nasıl senkronlamalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/cqrs-ne-zaman-uygulanir-ve-okuma-yazma-senkronizasyonu/): Önce en ucuz sürümü dene: read-replica ekle, raporlamayı oraya taşı — kilitlenme çoğu zaman bununla biter. Tam CQRS'i yalnızca sorgu şekilleri tek şemaya sığmayacak kadar ayrıştığında kur; modelleri outbox pattern'le event-driven senkronla, dual-write yapma, eventual consistency'yi kabul et. - [Bakiye güncellemede race condition: Pessimistic Lock mı, Redlock mı?](https://www.muhammetsafak.com.tr/sor-bakalim/bakiye-guncellemede-race-condition-pessimistic-lock-mu-redlock-mu/): Para için invariant'ı DB'de tut. Atomik koşullu `UPDATE ... SET balance = balance - 40 WHERE id = ? AND balance >= 40` ya da `SELECT ... FOR UPDATE` kullan. Redlock yalnızca tek bir DB satırı olmayan kaynaklar için; bakiyeyi DB zaten koruyabiliyorken dağıtık kilide güvenme. - [Esnek ürün nitelikleri için NoSQL mu, PostgreSQL mi seçmeliyim?](https://www.muhammetsafak.com.tr/sor-bakalim/esnek-urun-nitelikleri-icin-nosql-mu-postgresql-mi/): Sırf nitelikler değişkenler diye MongoDB'ye koşma — bu NoSQL tuzağıdır. İlişkisel çekirdeği (ürün, fiyat, sipariş) PostgreSQL'de tut, değişken nitelikleri GIN index'li bir `JSONB` kolonuna koy. Raporlama ihtiyacın tek başına Mongo'ya bölmeye karşı argüman. - [Kuyrukta poison pill (zehirli mesaj) ve Dead Letter Queue'yu nasıl yönetirim?](https://www.muhammetsafak.com.tr/sor-bakalim/kuyrukta-poison-pill-ve-dead-letter-queue-yonetimi/): Retry'ı sınırla: `tries`/`maxExceptions` + `backoff` ver, son hatada işi yeniden kuyruğa atma, `failed_jobs`'a düşür — Laravel'in yerleşik DLQ'su odur. Üstüne alert kur, `queue:retry` ile replay et. Asla sınırsız retry yapma. - [Health check tasarımı: Liveness ve Readiness ayrımını nasıl yaparım?](https://www.muhammetsafak.com.tr/sor-bakalim/health-check-tasarimi-liveness-ve-readiness-ayrimi/): Liveness 'süreç takıldı mı?' sorusudur — ucuz ve bağımlılıksız tut (DB'yi burada kontrol etme). Readiness 'şu an istek alabilir miyim?' sorusudur — kritik bağımlılıkları kontrol et ama sonucu birkaç saniye cache'le. Liveness fail → restart, readiness fail → trafiği kes. Probe'lar DB'yi DDoS'lamasın. - [PostgreSQL tablo partitioning'e sıfır kesinti ile nasıl geçerim?](https://www.muhammetsafak.com.tr/sor-bakalim/postgresql-tablo-partitioning-sifir-kesinti-ile-gecis/): `created_at`'e göre aylık RANGE declarative partitioning kullan. Sıfır kesinti için yeni parçalı tabloyu kur, geçmişi batch'ler hâlinde backfill et, uygulama yazmaya devam ederken isimleri tek transaction'da takasla. UNIQUE/PK ve FK'ler partition anahtarını içermek zorunda. - [Veritabanı deadlock'larını önlemek için hangi kurallara dikkat etmeliyim?](https://www.muhammetsafak.com.tr/sor-bakalim/veritabani-deadlock-tespiti-ve-onleme-kurallari/): Deadlock bir kilit-sıralama döngüsüdür. Kilitleri her zaman aynı global sırada al (örn. artan PK), transaction'ları kısa ve dar tut, en az satıra hedefli `FOR UPDATE` uygula. Yine de olacağını bekle: DB bir kurbanı abort eder, sen idempotent yapıp backoff ile retry et. - [Go HTTP sunucusunda panic'i recovery middleware ile nasıl yönetirim?](https://www.muhammetsafak.com.tr/sor-bakalim/go-da-panic-yonetimi-ve-recovery-middleware/): Her isteği `defer recover()` ile saran, stack'i + request id'yi loglayan, generic 500 dönen ve metrik basan bir middleware'i zincirin en dışına koy. Ama recover yalnızca aynı goroutine'i yakalar: handler içinde `go func()` açıyorsan o goroutine'in kendi recover'ı olmalı. - [Felaket kurtarma: RTO ve RPO'ya göre aktif-pasif senaryoyu nasıl kurgularım?](https://www.muhammetsafak.com.tr/sor-bakalim/felaket-kurtarma-rto-rpo-ve-aktif-pasif-senaryo/): RPO 5dk sürekli replikasyon demek (cross-region streaming + PITR), RTO 30dk hazır bekleyen sıcak yedek (IaC ile önceden kurulu, S3 CRR, Route 53 failover) demek. Aktif-pasif bu sayılara doğru tercih. Ama plan test edilmezse tahmindir — düzenli prova yap. - [Log storm ve disk dolma krizini nasıl önlerim?](https://www.muhammetsafak.com.tr/sor-bakalim/log-storm-ve-disk-dolma-krizini-onlemek/): İki katmanı birden düzelt: uygulamada tekrarlı logu throttle/sample et ('×10.000' diye tek satır), retry'a backoff koy; sunucuda logrotate ile boyut/sayı sınırı uygula ve logu kök diske değil ayrı bir volume'a yaz. Sınırsız loglamayı bir bug gibi gör. - [Dağıtık brute force ve DDoS'a karşı akıllı rate limiting'i nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/dagitik-brute-force-ve-ddos-icin-akilli-rate-limiting/): Sadece IP'ye göre limitleme dönen proxy'lere yenik düşer. Redis tabanlı sliding-window'u kullanıcı adı + IP + subnet/ASN + UA + ülke gibi çok boyutta anahtarla; hesap kilidi ve CAPTCHA ekle, gerçek volumetrik DDoS'u edge'e (Cloudflare) it. Login yolu fail-closed olsun. - [Graceful degradation: kritik olmayan servisleri yük altında nasıl izole ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/graceful-degradation-kritik-olmayan-servisleri-izole-etmek/): Neyin kritik (gez, sepet, ödeme) neyin lüks (öneri, benzer ürün, yorum) olduğuna önceden karar ver; lüksleri feature flag + kısa timeout arkasına al. Yük altında kill-switch onları kapatsın ya da mock veri dönsün. %98 CPU'da doğaçlama yapma, provayı önceden yap. - [Dağıtık sistemde Saga Pattern ile eventual consistency'i nasıl tasarlarım?](https://www.muhammetsafak.com.tr/sor-bakalim/dagitik-sistemde-saga-pattern-ile-eventual-consistency/): Tek atomik işlemi, her biri telafi (compensating) aksiyonu olan yerel işlemler dizisine böl. Orchestrator merkezi koordinatör adımları kuyruktan sürsün, hata olunca telafileri ters sırayla çalıştırsın. Her adımı idempotent yap, outbox ile yayınla. - [PostgreSQL split-brain'i quorum ve mutabakat ile nasıl önlerim?](https://www.muhammetsafak.com.tr/sor-bakalim/postgresql-split-brain-quorum-ve-mutabakat-ile-onlemek/): Bir node yalnızca çoğunluğa (quorum) sahipse primary olabilsin. Failover'ı elle yazma; Patroni + etcd/Consul (Raft) kullan, çoğunluktan kopan eski primary kendini düşürsün (fencing). Tek sayıda oy veren üye koy. - [Üçüncü parti API bağımlılığında Circuit Breaker'ı nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/ucuncu-parti-api-icin-circuit-breaker-deseni/): Yavaş bağımlılığı sürekli çağırmayı bırak: CLOSED'da say, OPEN'da hızlıca fallback dön, HALF-OPEN'da deneme isteğiyle yokla. Ama asıl katil 30 saniyelik timeout — breaker'ı kısa timeout, bulkhead ve fallback ile birlikte kur. - [CDN'de asset sürümleme: hash'leme ve cache stratejisini nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/cdn-asset-surumleme-hashleme-ve-cache-stratejisi/): Query-string busting güvenilmez — bazı CDN'ler query'yi cache key'de yok sayar. Sağlam desen content-hash'li dosya adı (`app.a8f9b2.js`): içerik değişmedikçe ad sabit, sonsuza kadar `immutable` cache'lersin. Asla uzun cache'lenmemesi gereken tek şey, bu hash'lere işaret eden HTML. - [Elasticsearch'te 'search-as-you-type' performansını edge n-gram ile nasıl optimize ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/elasticsearch-anlik-arama-edge-ngram-ile-optimizasyon/): `wildcard`/`regexp` sorgu zamanında tarama yapar, inverted index'i kullanmaz ve 10M dokümanda CPU'yu yakar. İşi index zamanına taşı: `edge_ngram` ile önekleri yazma anında üret, autocomplete düz bir term lookup'a (milisaniye) dönsün. - [2-5 GB dosyaları PHP belleğini şişirmeden stream ile nasıl indirtirim?](https://www.muhammetsafak.com.tr/sor-bakalim/buyuk-dosyalari-php-bellegini-sismeden-stream-ile-indirmek/): `file_get_contents`/`Storage::get` dosyayı tümüyle RAM'e yükler — 2-5 GB'da ölümcül. Önce baytı PHP'den hiç geçirme: presigned S3 URL ya da `X-Sendfile`. Mecbursan `Storage::readStream` + `StreamedResponse` ile chunk-by-chunk bas, bellek birkaç MB'da sabit kalsın. - [HTTP/2 ve HTTP/3 (QUIC) API performansını nasıl etkiler?](https://www.muhammetsafak.com.tr/sor-bakalim/http-2-ve-http-3-quic-api-performansina-etkisi/): HTTP/2'yi hemen aç — çoklamayla tek ekrandaki 4-5 paralel isteğin tek bağlantıya iner, domain sharding'e gerek kalmaz. Mobil kitle için HTTP/3 (QUIC) asıl kazanç; TCP HOL blocking'i ortadan kaldırır ve handshake'i hızlandırır. - [PgBouncer'da Session/Transaction/Statement modlarından hangisini seçmeliyim?](https://www.muhammetsafak.com.tr/sor-bakalim/pgbouncer-session-transaction-statement-modu-ve-prepared-statement/): Web/mikroservis filosunda Transaction modu — sunucu bağlantısını her transaction sonunda havuza iade eder, en yüksek yeniden kullanımı verir. Bedeli: protokol seviyesi prepared statement'ları ve session state'i bozar. Çözüm: client-side prepared'ı kapat ya da PgBouncer 1.21+ kullan; `default_pool_size`'ı makul tut. - [Yeni bir projeye mikroservislerle mi başlamalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/yeni-projeye-mikroservisle-mi-baslamali/): Sıfırdan başlayan çoğu proje için cevap hayır: monolitle başla, sınırları net çiz, ölçek ihtiyacı gerçek olduğunda servisleri ayır. - [Autoscaling scale-in sırasında SIGTERM ile graceful shutdown'ı nasıl sağlarım?](https://www.muhammetsafak.com.tr/sor-bakalim/autoscaling-sirasinda-sigterm-ile-graceful-shutdown/): Sorun uygulamanın SIGTERM'de drain etmemesi. Yaşam döngüsünü düzelt: önce LB'den çık, yeni istek almayı kes, mevcut işleri bir deadline içinde bitir, sonra çık. Go'da `server.Shutdown(ctx)`, Octane'de graceful reload; platformun grace süresini en uzun drain'inle hizala. - [PostgreSQL'de composite index kolon sırasını nasıl seçerim?](https://www.muhammetsafak.com.tr/sor-bakalim/postgresql-composite-index-kolon-sirasi-nasil-secilir/): Bu sorgu için tek bir composite index kur: önce eşitlik kolonları (`user_id`, `status`), sonra ORDER BY kolonu en sona (`created_at DESC`). Böylece index hem filtreyi hem sıralamayı karşılar, Bitmap merge + Sort biter. Üstüne binen tekli indeksleri sil. - [Redis cache stampede'i (thundering herd) nasıl önlerim — mutex lock mı, XFetch mi?](https://www.muhammetsafak.com.tr/sor-bakalim/redis-cache-stampede-mutex-lock-mu-xfetch-mi/): Asıl sorun, anahtarın aynı saniyede uçurumdan düşmesi. İki tamamlayıcı çözüm: tek seferlik mutex lock ile yalnızca ilk isteğin DB'ye gitmesi, ve probabilistic early expiration (XFetch) ile sürünün tek ana toplanmaması. TTL'lere jitter ekle, stale-while-revalidate ile kullanıcıyı bekletme. Çoğu durumda single-flight + jitter yeter; XFetch'i recompute pahalıysa kullan. - [Go'da GC baskısını sync.Pool ve escape analizi ile nasıl azaltırım?](https://www.muhammetsafak.com.tr/sor-bakalim/go-da-gc-baskisini-sync-pool-ve-escape-analizi-ile-azaltmak/): GC duraklamaları bir semptom; asıl düşman tahsis hızı. Hot path'te kısa ömürlü buffer/struct'ları `sync.Pool` ile tekrar kullan, escape analizini (`-gcflags=-m`) çalıştırıp heap'e kaçanları stack'te tut. `pprof` ile önce/sonra ölç. `GOGC`/`GOMEMLIMIT` ayarı GC'yi seyrekleştirir ama saniyede 50k tahsisi düzeltmez. - [Laravel Octane (FrankenPHP) altında bellek sızıntısını nasıl debug ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/laravel-octane-frankenphp-bellek-sizintisi-nasil-debug-edilir/): Tahmin etme, ölç. Octane'de worker uzun ömürlü olduğu için istekler arasında biriken her şey sızar: büyüyen static cache'ler, request state tutan singleton'lar, her istekte yeniden bağlanan servisler. Önce sızıntıyı bisect ile yakala, sonra stateful tarafı Octane hook'larında sıfırla. `max_requests` çözüm değil, emniyet supabı. - [Multi-tenant SaaS'te veritabanı izolasyonu: ayrı DB mi, şema mı, tenant_id mi?](https://www.muhammetsafak.com.tr/sor-bakalim/multi-tenant-saas-veritabani-izolasyon-stratejisi/): 10.000 tenant'ta database-per-tenant operasyonel olarak ölçeklenmez (10k migration, 10k pool, 10k backup). Pragmatik cevap: her yerde `tenant_id` olan shared DB + Postgres Row-Level Security ile izolasyonu DB'ye gömmek. ORM scope'u savunma katmanı; whale tenant'ı sonra kendi DB'sine taşıma yolunu açık tut. - [Ödeme webhook'u aynı bildirimi tekrar gönderiyor; idempotency'i nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/webhook-mukerrer-bildirim-idempotency-ve-hmac/): İki ayrı mesele. Kimlik doğrulama: HMAC imzasını RAW body üzerinde constant-time karşılaştır, geçmezse reddet. Idempotency: provider'ın event id'sini UNIQUE constraint ile sakla, transaction içinde check-or-insert yap — bir-kez garantisini app değil DB verir. İmza doğrula → hızlı 200 dön → işi kuyruğa al. - [PHP monolitten ödeme modülünü Strangler Fig ile nasıl koparırım?](https://www.muhammetsafak.com.tr/sor-bakalim/monolitten-mikroservise-strangler-fig-ile-kademeli-gecis/): Önüne facade/gateway koy, trafiği ağırlıkla (5/20/100) kaydır, monolit fallback olsun. Yeni Go servisini önce SHADOW çalıştır. Zor kısım routing değil, veri: tabloları paylaşma, ayrı store + anti-corruption layer + outbox/events ile tutarlılık. Sadece sınırı zaten temiz olan modülü kopar. - [Cloudflare Workers + KV ile edge cache kurarsam invalidation'ı nasıl yaparım?](https://www.muhammetsafak.com.tr/sor-bakalim/cloudflare-workers-kv-ile-edge-cache-ve-invalidation/): Sadece TTL'e güvenme — eventual'dır ve eski fiyat servis eder. Invalidation'ı push-based yap: origin'de fiyat değişince aynı transaction/outbox içinde Cloudflare API'ına yazıp KV'yi güncelle ya da key'i sil. KV'yi kaynak değil cache gör; versiyonlu key + kısa TTL emniyet ağı. - [Mikroservislerde dağıtık izlemeyi (OpenTelemetry) nasıl kurarım?](https://www.muhammetsafak.com.tr/sor-bakalim/mikroserviste-dagitik-izleme-opentelemetry-ile-nasil-kurulur/): W3C Trace Context (`traceparent`/`tracestate`) üzerinde standartlaş; her servis gelen header'dan context'i EXTRACT, giden çağrıya INJECT etsin. Kuyruklarda aynı `traceparent`'ı mesaj header'ı olarak taşı ve worker'da yeniden çıkar — herkesin unuttuğu parça budur. trace_id'yi elle örme, SDK'nın context propagation'ına bırak. - [WireGuard ile Docker ağları çakışıyor, routing'i nasıl stabilize ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/wireguard-ile-docker-agi-ip-cakismasi-ve-routing/): Kök neden çakışan RFC1918 aralıkları. Docker'ın havuzunu (`daemon.json` → `default-address-pools`) WireGuard alt ağıyla çakışmayan bir bloğa sabitle, WireGuard'a dar `AllowedIPs` ver (sadece DB subnet'i, `0.0.0.0/0` değil). Rotaları `ip route` ile değil systemd-networkd/netplan ile kalıcı yap. - [LLM sağlayıcısını (Ollama → Bedrock/OpenAI) nasıl soyutlamalıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/ollama-dan-uretimde-bedrock-openai-a-gecerken-llm-soyutlamasi/): Sağlayıcıyı değil yeteneğini soyutla: `complete(prompt, opts): Result` gibi dar bir port/adapter (Strategy) ve config'le seçilen birkaç implementasyon. Farkları açık timeout, ucuz fallback ve kenarda token bütçesiyle tolere et; jenerik bir 'AI framework'e şişirme. - [Yerel diskteki dosyaları S3'e taşırken EFS ara çözüm olur mu?](https://www.muhammetsafak.com.tr/sor-bakalim/yerel-diskten-s3-e-gecerken-efs-ara-cozum-mu/): Hedef olarak EFS bir tuzak: 'yerel disk' engelini kaldırır ama ağ dosya sistemiyle kötü gecikme, yüksek maliyet ve aynı bağımlılığı bırakır. Doğru hamle object-storage adaptörü — Laravel'de zaten Flysystem var, `Storage::disk()`'e geç ve ham path'leri at. - [Laravel ve Go servisleri arasında mesaj şeması için Protobuf mu, JSON Schema mı?](https://www.muhammetsafak.com.tr/sor-bakalim/laravel-ve-go-arasinda-mesaj-semasi-protobuf-mu-json-schema-mi/): Asıl mesele wire format değil, contract-first çalışmak. Tipi zorlamak, performans ve iki dile codegen istiyorsan Protobuf + schema registry; JSON-native ve insan-okur kalmak istiyorsan JSON Schema. Asıl hata noktan gevşek PHP array'i — sınırda tipli bir DTO'ya deserialize et. - [Logları OpenSearch'e gönderirken Fluent Bit ile arasına Kafka/Redis buffer koymalı mıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/loglari-opensearch-e-gonderirken-araya-kafka-buffer-koymali-miyim/): Evet, ama önce Fluent Bit'in kendi filesystem buffer'ını aç. Yetmezse Kafka (disk tabanlı, replay, at-least-once); Redis listesini yalnızca kaybını göze alabildiğin loglarda kullan. Uygulamayı log yazarken asla bloklatma. ## Blog — Diller - [Go ile yazdığım bir komut satırı aracını paketlemek ve dağıtmak](https://www.muhammetsafak.com.tr/blog/go-ile-komut-satiri-aracini-paketlemek-ve-dagitmak/): Bir Go CLI aracını yazmak işin yarısı; onu sürümlemek, çapraz derlemek ve başkalarının kolayca kurabileceği biçimde dağıtmak diğer yarısı. - [TypeScript'in yeni derleyicisi ve build hızının önemi](https://www.muhammetsafak.com.tr/blog/typescriptin-yeni-derleyicisi-ve-build-hizi/): TypeScript derleyicisinin Go'ya port edilmesi ve hızlı geri bildirim döngüsünün bir geliştirici için neden bu kadar değerli olduğu. - [PHP Öldü mü? 2026 Tablosu, Veriyle](https://www.muhammetsafak.com.tr/blog/php-oldu-mu-2026-tablosu-veriyle/): 18 yıllık bir PHP geliştiricisinin gözünden — W3Techs, Stack Overflow, JetBrains ve Packagist verileriyle PHP'nin 2026 fotoğrafı, ve dilin görmezden gelinen zayıflıkları. - [PHP'de Sabit, Enum ve Readonly: 10 Aracın Tek Karar Ağacı](https://www.muhammetsafak.com.tr/blog/php-sabit-enum-readonly-sekiz-aracin-karar-agaci/): define'dan asymmetric visibility'ye — modern PHP'de değişmezliği doğru kurmak için üç eksende bir mental model ve somut karar matrisi. - [2026'da PHP ile uygulama geliştirmek: ekosistemin hali](https://www.muhammetsafak.com.tr/blog/2026da-php-ile-uygulama-gelistirmek-ekosistemin-hali/): PHP'nin 2026'daki gerçek durumu: dil olgunluğu, ekosistem sağlığı ve 'öldü' söyleminin neden hâlâ yanlış olduğu. - [PHP 8.5 yolda: dilin olgunlaşan yüzü](https://www.muhammetsafak.com.tr/blog/php-85-yolda-dilin-olgunlasan-yuzu/): PHP 8.5 henüz çıkmadı; ama gündemde olan önerilere bakarak on yılı aşkın bir dilin nasıl evrildiğini okuyorum. - [Go'nun standart kütüphanesiyle ne kadar uzağa gidilir](https://www.muhammetsafak.com.tr/blog/gonun-standart-kutuphanesiyle-ne-kadar-uzaga-gidilir/): Go'nun zengin standart kütüphanesinin gerçekte ne kadar yol kat ettirdiğini, harici bağımlılık ekleme kararını somut örneklerle tartıyorum. - [PHP 8.4 yolda: property hook'lar ve asimetrik görünürlük](https://www.muhammetsafak.com.tr/blog/php-8-4-yolda-property-hooklar-ve-asimetrik-gorunurluk/): PHP 8.4 ile gelen property hook'lar ve asimetrik görünürlük; bu eklemelerin sınıf modellemesini nasıl değiştireceği. - [Go'da test yazmak: tablo testleri (table-driven tests)](https://www.muhammetsafak.com.tr/blog/go-da-test-yazmak-tablo-testleri-table-driven-tests/): Go'nun standart test kütüphanesi ve tablo testi (table-driven test) desenini uygulamalı olarak kavramak; dilin sade test felsefesini benimsemek. - [PHP 8.3: typed class constants ve gelen eklemeler](https://www.muhammetsafak.com.tr/blog/php-8-3-typed-class-constants-ve-gelen-eklemeler/): PHP 8.3 ile gelen tipli sınıf sabitleri, json_validate, #[Override] ve dinamik sabit erişimi; dilin tutarlılık yönündeki adımları. - [TypeScript'te tip düzeyinde programlama: utility types](https://www.muhammetsafak.com.tr/blog/typescriptte-tip-duzeyinde-programlama-utility-types/): TypeScript'in yerleşik utility type'ları ve tip dönüştürme mekanizmaları: tip sistemini bir araç olarak ileri düzeyde kullanmak. - [PHP'de tasarım desenlerini abartmadan kullanmak](https://www.muhammetsafak.com.tr/blog/phpde-tasarim-desenlerini-abartmadan-kullanmak/): Tasarım desenleri amaç değil araç. PHP'de hangi deseni ne zaman kullanmak gerektiği ve ne zaman gereksiz karmaşıklık yarattığı üzerine. - [PHP de Trait Nedir? Ne İçin Kullanılır?](https://www.muhammetsafak.com.tr/blog/php-trait-nedir-ne-icin-kullanilir/): PHP'de trait nedir, ne için kullanılır? Çoklu kalıtım ihtiyacını trait'lerle çözmeyi örneklerle anlatıyorum. - [PHP 8.2 yolda: readonly sınıflar ve yeni tipler](https://www.muhammetsafak.com.tr/blog/php-8-2-yolda-readonly-siniflar-ve-yeni-tipler/): PHP 8.2 ile gelen readonly sınıflar, DNF tipler ve tek başına tip bildirimleri; bu eklemelerin domain modellemesine etkisi. - [Kod tabanında isimlendirme: bir mimari mesele](https://www.muhammetsafak.com.tr/blog/kod-tabaninda-isimlendirme-bir-mimari-mesele/): İsimlendirme neden salt stil meselesi değil, tasarım kararının kendisidir. Yıllar içinde gözlemlediğim örüntüler. - [TypeScript ile uçtan uca tip güvenliği: API'den arayüze](https://www.muhammetsafak.com.tr/blog/typescript-ile-uctan-uca-tip-guvenligi-apiden-arayuze/): Tip sözleşmesini backend API'den frontend arayüzüne kırılmadan taşımak ve bu süreçteki pratik yöntemler. - [Python ile otomasyon: tekrarlayan işleri betiğe dökmek](https://www.muhammetsafak.com.tr/blog/python-ile-otomasyon-tekrarlayan-isleri-betege-dokmek/): Manuel iş akışlarını güvenilir Python betiklerine taşımak: hangi işler betiklenmeye değer ve bunu nasıl doğru yaparsınız. - [Modern PHP'de value object tasarlamak](https://www.muhammetsafak.com.tr/blog/modern-phpde-deger-nesneleri-value-object-tasarlamak/): İlkel tipler yerine anlamı koda gömmek: PHP'de value object tasarımının neden ve nasılı üzerine. - [Go 1.18 generic'ler: uzun bekleyişin sonuna doğru](https://www.muhammetsafak.com.tr/blog/go-1-18-genericler-uzun-bekleyisin-sonuna-dogru/): Go 1.18 ile gelen generic desteği bir dilin nasıl yeniden şekillenebileceğini gösteriyor. İlk izlenimler ve trade-off'lar. - [PHP 8.1 yolda: enum'lar ve readonly ile daha güvenli modeller](https://www.muhammetsafak.com.tr/blog/php-8-1-yolda-enumlar-ve-readonly-ile-daha-guvenli-modeller/): PHP 8.1 henüz çıkmadı; ama gelen enum ve readonly özelliklerinin domain modellemesine nasıl etki edeceğini inceliyorum. - [PHP'de Veri Türleri Dönüşümü ve Tür Dayatma İşlemleri](https://www.muhammetsafak.com.tr/blog/php-veri-turleri-donusumu-tur-dayatma-islemleri/): PHP'de veri türü dönüşümü ve tür dayatma: gettype, settype, var_dump ve dönüşüm işlemleri. - [TypeScript'te generic'ler ve tip çıkarımı](https://www.muhammetsafak.com.tr/blog/typescriptte-genericler-ve-tip-cikarimi/): TypeScript'te generic'leri kullanarak yeniden kullanılabilir, tip-güvenli soyutlamalar kurmak ve tip çıkarımından yararlanmak. - [Go'da hata yönetimi: error değeriyle yaşamak](https://www.muhammetsafak.com.tr/blog/goda-hata-yonetimi-error-degeriyle-yasamak/): İstisna (exception) mekanizması olmayan Go'da hata yönetimini dil deyimi olarak benimsemenin pratik yolu. - [PHP'de enum ihtiyacı: 8.1 öncesi çözümler](https://www.muhammetsafak.com.tr/blog/phpde-enum-ihtiyaci-8-1-oncesi-cozumler/): PHP 8.1 native enum getirmeden önce sabit kümeleri nasıl temsil ediyorduk ve her yaklaşımın trade-off'ları nelerdi. - [PHP 8.0 ile kod yazmak: attribute'lar ve nullsafe operatör](https://www.muhammetsafak.com.tr/blog/php-8-0-ile-kod-yazmak-attribute-lar-ve-nullsafe-operator/): PHP 8.0 çıktı. Attribute'ları ve nullsafe operatörü gerçek kodda nasıl kullandığımı, ne kazandırdığını paylaşıyorum. - [PHP 8.0'a hazırlık: union types, match, named arguments](https://www.muhammetsafak.com.tr/blog/php-8-0-a-hazirlik-union-types-match-named-arguments/): PHP 8.0 henüz çıkmadı ama RFC'ler ve beta sürümleri okunabilir. Üç önemli özelliği şimdiden anlamak için notlarımı paylaşıyorum. - [Python ile veri işleme betikleri yazmak](https://www.muhammetsafak.com.tr/blog/python-ile-veri-isleme-betikleri-yazmak/): Tekrarlayan dönüştürme işlerini Python'a devretmenin pratik gerekçesini ve somut betik örneklerini paylaşıyorum. - [PHP'de İstisnalar ve Hata Yönetimi](https://www.muhammetsafak.com.tr/blog/php-istisna-hata-yonetimi/): PHP'de istisnalar (exception) ve hata yönetimi: try-catch-finally yapıları ve özel istisnalar. - [Go'da HTTP servisi yazmak: standart kütüphane yeter mi](https://www.muhammetsafak.com.tr/blog/go-da-http-servisi-yazmak-standart-kutuphane-yeter-mi/): Go'nun net/http paketiyle küçük bir HTTP servisi kurarken neyin geldiğini, neyin gelmediğini ve framework eşiğini tartışıyorum. - [PHP 7.4 ile gelen typed properties ve ok fonksiyonları](https://www.muhammetsafak.com.tr/blog/php-7-4-ile-gelen-typed-properties-ve-ok-fonksiyonlari/): PHP 7.4 Kasım 2019'da yayınlandı. Typed properties ve arrow function'lar, dilin tip sistemini ve sözdizimini önemli ölçüde güçlendiriyor. - [Go'da eşzamanlılık: goroutine ve channel pratiği](https://www.muhammetsafak.com.tr/blog/goda-eszamanlilik-goroutine-ve-channel-pratigi/): Go'nun eşzamanlılık modelini — goroutine ve channel'ı — uygulamalı kavramak. PHP'nin süreç modelinden gelince ne değişiyor? - [TypeScript'e geçiş: JavaScript'te tip güvenliği](https://www.muhammetsafak.com.tr/blog/typescripte-gecis-javascriptte-tip-guvenligi/): Büyüyen bir frontend kod tabanını TypeScript ile korumaya başlamanın pratik deneyimi: ne kazandım, ne kaybettim ve ne zaman gerçekten değer verdi? - [Go'da ilk CLI aracımı yazmak](https://www.muhammetsafak.com.tr/blog/goda-ilk-cli-aracimi-yazmak/): Yeni öğrendiğim Go dilini gerçek bir CLI aracı yazarak pekiştirdim. Dilin pratikteki hissini, standart kütüphaneyle ne kadar uzağa gidilebildiğini anlatıyorum. - [PHP 7.3: esnek heredoc ve liste atamaları](https://www.muhammetsafak.com.tr/blog/php-7-3-esnek-heredoc-ve-liste-atamalari/): PHP 7.3'ün getirdiği esnek heredoc sözdizimi ve liste atamalarının okunabilirliğe katkısını gerçek örneklerle değerlendiriyorum. - [JavaScript'te async/await ile okunur asenkron kod](https://www.muhammetsafak.com.tr/blog/javascriptte-async-await-ile-okunur-asenkron-kod/): Promise zincirlerinin yerini alan async/await sözdiziminin JavaScript'teki asenkron kodu nasıl okunabilir kıldığını örneklerle açıklıyorum. - [PHP 7.2 ve modern PHP alışkanlıkları](https://www.muhammetsafak.com.tr/blog/php-7-2-ve-modern-php-aliskanlikari/): PHP 7.2 ile gelen yenilikleri ve dilin bugün geldiği noktayı günlük kod yazım alışkanlıklarıma nasıl yansıttığımı anlatıyorum. - [JavaScript'te Promise ve asenkron akış](https://www.muhammetsafak.com.tr/blog/javascriptte-promise-ve-asenkron-akis/): JavaScript'te Promise nedir, callback yığınından nasıl kurtulunur; then, catch zincirleme ve temel asenkron akış kalıpları. - [PHP'de closure ve use ile değişken yakalama](https://www.muhammetsafak.com.tr/blog/phpde-closure-ve-use-ile-degisken-yakalama/): PHP'de closure (anonim fonksiyon) nedir, use anahtar kelimesiyle değişken yakalama nasıl çalışır; günlük kullanım örnekleri. - [PHP 7.1: nullable tipler ve void dönüş tipi](https://www.muhammetsafak.com.tr/blog/php-7-1-nullable-tipler-ve-void-donus-tipi/): PHP 7.1 ile gelen nullable tip bildirimleri ve void dönüş tipi, fonksiyon imzalarını daha okunur ve net kılıyor. - [PHP'de arayüz (interface) ve bağımlılık enjeksiyonu pratiği](https://www.muhammetsafak.com.tr/blog/php-de-arayuz-interface-ve-bagimlilik-enjeksiyonu-pratigi/): PHP'de interface tanımlayarak ve bağımlılık enjeksiyonu uygulayarak sınıfları nasıl gevşek bağlı hale getirdiğimi örneklerle aktarıyorum. - [SOLID'i PHP'de pratiğe dökmek: tek sorumluluk ilkesi](https://www.muhammetsafak.com.tr/blog/solid-i-php-de-pratige-dokmek-tek-sorumluluk-ilkesi/): SOLID'in SRP ilkesini soyut kalmadan PHP sınıflarına nasıl uyguladığımı somut örneklerle anlatıyorum. - [PHP 7'de skaler tip bildirimleri ve dönüş tipleri](https://www.muhammetsafak.com.tr/blog/php-7-de-skaler-tip-bildirimleri-ve-donus-tipleri/): PHP 7 ile gelen skaler tip bildirimleri ve dönüş tipi tanımlamalarını pratikte nasıl kullandığımı anlatıyorum. - [PHP 7.0: yıllardır beklenen sürümle gelen hız ve tip bildirimleri](https://www.muhammetsafak.com.tr/blog/php-7-0-yillarca-beklenen-surum-hiz-ve-tip-bildirimleri/): PHP 7.0 bu hafta yayımlandı. Performans artışı, skaler tip bildirimleri ve dönüş tipleriyle ilk izlenimlerimi paylaşıyorum. - [ES6 ile tanışma: let, const ve ok fonksiyonları](https://www.muhammetsafak.com.tr/blog/es6-ile-tanisma-let-const-ve-ok-fonksiyonlari/): JavaScript'in yeni standardı ES6 ile gelen let, const, ok fonksiyonu ve şablon dizelerini örneklerle anlattım. - [PHP 5.6 yenilikleri: variadic fonksiyonlar ve ** operatörü](https://www.muhammetsafak.com.tr/blog/php-5-6-yenilikleri-variadic-fonksiyonlar-ve-ust-uste-operatoru/): PHP 5.6 ile gelen değişken sayıda argüman (variadic) desteği ve üs alma operatörünü örneklerle anlattım. - [MVC'yi gerçekten anlamak: controller'ı şişirmeyi bırakmak](https://www.muhammetsafak.com.tr/blog/mvci-gercekten-anlamak-controlleri-sisirmeyi-birakmak/): MVC'nin her katmanının gerçekte ne iş yaptığını ve controller'ı nasıl ince tutabileceğinizi anlatıyorum. - [PHP 5.5 generator (yield) ile büyük veri kümelerini gezmek](https://www.muhammetsafak.com.tr/blog/php-55-generator-yield-ile-buyuk-veri-kumelerini-gezmek/): Belleği şişirmeden büyük döngüler kurmanın dil düzeyindeki yolu: PHP 5.5 generator ve yield kullanımı. - [PHP'de namespace ile kodu düzenli tutmak](https://www.muhammetsafak.com.tr/blog/phpde-namespace-ile-kodu-duzenli-tutmak/): İsim çakışmalarını bitiren, kütüphane çağına uygun kod organizasyonu: PHP namespace kullanımı ve use ifadesi. - [PSR-4 ve otomatik yükleme: include zincirinden kurtulmak](https://www.muhammetsafak.com.tr/blog/psr-4-ve-otomatik-yukleme-include-zincirinden-kurtulmak/): Sınıfları elle dahil etmeyi bırakıp standart otomatik yüklemeye geçmek: PSR-0 ve PSR-4 farkı, Composer entegrasyonu. ## Blog — Framework & Kütüphane - [Laravel'le on iki yıl: bir framework'le büyümek](https://www.muhammetsafak.com.tr/blog/laravelle-on-iki-yil-bir-frameworkle-buyumek/): 2014'ten 2026'ya Laravel ile geçirilen on iki yıl: bir araçla birlikte olgunlaşmanın, onu aşmanın ve yeniden benimsemenin hikâyesi. - [Laravel 12: sürüm ritmi olgunlaşırken](https://www.muhammetsafak.com.tr/blog/laravel-12-surum-ritmi-olgunlasirken/): Laravel 12 ile gelen değişiklikleri ve framework'ün yıllık sürüm temposunun proje planlamasına etkisini değerlendiriyorum. - [Laravel 11 ile gelen yeni, ince iskelet yapısı](https://www.muhammetsafak.com.tr/blog/laravel-11-ile-gelen-yeni-ince-iskelet-yapisi/): Laravel 11'in sadeleşen iskelet yapısı, kaldırılan varsayılanlar ve bunların günlük geliştirme pratiklerine somut etkisi. - [Laravel Queue ve Supervisor ile Asenkron İşlemler](https://www.muhammetsafak.com.tr/blog/laravel-queue-ve-supervisor-ile-asenkron-islemler/): Laravel'de Queue ve Supervisor ile asenkron iş kuyruğu kurulumu ve arka plan işlemleri. - [Laravel 10: daha sıkı tipler ve Process katmanı](https://www.muhammetsafak.com.tr/blog/laravel-10-daha-siki-tipler-ve-surec-process-katmani/): Laravel 10'un getirdiği tip disiplini ve yeni Process facade'i: framework'ün olgunlaşan kod tabanını günlük geliştirmeye yansıtmak. - [Laravel 9: yeni sürüm ritmi ve PHP 8 uyumu](https://www.muhammetsafak.com.tr/blog/laravel-9-yeni-surum-ritmi-ve-php-8-uyumu/): Laravel 9 ile yerleşen yıllık sürüm temposunun proje planlamasına etkisi ve PHP 8 uyumunun kod tabanına yansımaları. - [Laravel Octane: kalıcı süreçle gelen performans](https://www.muhammetsafak.com.tr/blog/laravel-octane-kalici-surecle-gelen-performans/): Laravel Octane'in istek başına önyükleme maliyetini nasıl ortadan kaldırdığı ve bunun beraberinde getirdiği trade-off'lar. - [Laravel'de eylem (action) sınıflarıyla controller'ı inceltmek](https://www.muhammetsafak.com.tr/blog/laravelde-eylem-action-siniflariyla-controlleri-inceltmek/): İş mantığını controller'dan tek amaçlı action sınıflarına taşıyarak nasıl daha test edilebilir ve bakımı kolay kod yazılır. - [Inertia.js ile monolitten modern arayüze](https://www.muhammetsafak.com.tr/blog/inertia-js-ile-monolitten-modern-arayuze/): Inertia.js'in ayrı bir API yazmadan SPA hissi verme modelini, Laravel ile entegrasyonunu ve ne zaman doğru seçim olduğunu anlatıyorum. - [Laravel 8: model factory'leri ve yeni dizin yapısı](https://www.muhammetsafak.com.tr/blog/laravel-8-model-factory-leri-ve-yeni-dizin-yapisi/): Laravel 8'in sınıf tabanlı factory yapısını ve yeni dizin düzenini, test ve tohum verisi üretimi odağıyla anlatıyorum. - [Laravel Livewire ile JavaScript yazmadan etkileşim](https://www.muhammetsafak.com.tr/blog/laravel-livewire-ile-javascript-yazmadan-etkilesim/): Livewire'ın sunucu odaklı etkileşim modelini, hangi durumlarda doğru seçim olduğunu ve sınırlarını anlatıyorum. - [Laravel 6 ve LTS'in anlamı: sürüm stratejisi](https://www.muhammetsafak.com.tr/blog/laravel-6-ve-ltsin-anlami-surum-stratejisi/): Laravel 6 LTS sürümü ne anlama geliyor? Uzun süreli destek kararını proje ömrüne göre değerlendirmek ve sürüm stratejisi nasıl olmalı? - [Laravel'de servis sağlayıcı ve container'ı doğru kullanmak](https://www.muhammetsafak.com.tr/blog/laravelde-servis-saglayici-ve-containeri-dogru-kullanmak/): Laravel'in bağımlılık çözüm mekanizmasını gerçekten anlamak: servis sağlayıcı ve IoC container'ı doğru kullanmanın pratik rehberi. - [Laravel 5.4 ve Blade ile bileşen düşünmek](https://www.muhammetsafak.com.tr/blog/laravel-5-4-ve-blade-ile-bilesen-dusunmek/): Laravel 5.4'te Blade şablon motoruna gelen @component direktifi ile görünümleri yeniden kullanılabilir parçalara bölmek. - [Laravel'de olaylar (events) ve dinleyiciler](https://www.muhammetsafak.com.tr/blog/laravel-de-olaylar-events-ve-dinleyiciler/): Laravel'in olay sistemiyle yan etkileri ana akıştan nasıl ayırdığımı ve pratikte ne kazandığımı örneklerle anlatıyorum. - [Laravel 5.2: çoklu kimlik doğrulama ve route grupları](https://www.muhammetsafak.com.tr/blog/laravel-5-2-coklu-kimlik-dogrulama-ve-route-gruplari/): Laravel 5.2 ile birden fazla kullanıcı tipini tek uygulamada nasıl yönettiğimi; guard ve route gruplarını anlatıyorum. - [Laravel middleware ile isteklere ortak davranış eklemek](https://www.muhammetsafak.com.tr/blog/laravel-middleware-ile-isteklere-ortak-davranis-eklemek/): Laravel'de middleware nedir, nasıl yazılır ve kimlik doğrulama gibi kesişen ihtiyaçları nasıl tek yerde toplarım anlattım. - [Eloquent ilişkileri: hasMany, belongsTo ve eager loading](https://www.muhammetsafak.com.tr/blog/eloquent-iliskileri-hasmany-belongsto-ve-eager-loading/): Laravel Eloquent'te hasMany ve belongsTo ilişkilerini kurmayı ve N+1 sorgusunu eager loading ile çözmeyi anlattım. - [Laravel 5'e geçiş: yeni dizin yapısı ve .env](https://www.muhammetsafak.com.tr/blog/laravel-5e-gecis-yeni-dizin-yapisi-ve-env/): Laravel 4'ten 5'e geçerken dizin yapısı, .env dosyası ve uygulama yapısındaki değişiklikleri anlattım. - [Eloquent ORM ile veritabanı işlemlerini sadeleştirmek](https://www.muhammetsafak.com.tr/blog/eloquent-orm-ile-veritabani-islemlerini-sadestirmek/): SQL'i elle yazmaktan model tabanlı erişime: Laravel Eloquent ORM'in uygulama tarafından görünümü ve günlük kullanımı. - [Blade şablon motoru: tekrar eden HTML'i bitirmek](https://www.muhammetsafak.com.tr/blog/blade-sablon-motoru-tekrar-eden-htmli-bitirmek/): Görünüm katmanını mantıktan ayırmanın pratik kazancı: Blade layout, section ve partial kullanımı. - [Laravel 4 ile ilk projeme başlarken](https://www.muhammetsafak.com.tr/blog/laravel-4-ile-ilk-projeme-baslarken/): Ham PHP'den bir framework'e geçişin getirdiği düzen: Laravel 4 ile ilk izlenimler, kurulum ve temel yapı. ## Blog — Web Geliştirme - [Basic Authentication](https://www.muhammetsafak.com.tr/blog/basic-authentication/): HTTP Basic Authentication nedir, nasıl çalışır ve ne zaman kullanılır? Temel kimlik doğrulama yönteminin işleyişi. - [JWT Authentication](https://www.muhammetsafak.com.tr/blog/jwt-authentication/): JWT (JSON Web Token) ile kimlik doğrulama: token yapısı, çalışma mantığı ve tipik kullanım senaryoları. - [API'de idempotency: aynı isteği güvenle tekrar etmek](https://www.muhammetsafak.com.tr/blog/api-de-idempotency-ayni-istegi-guvenle-tekrar-etmek/): Tekrarlanan API isteklerinin yan etki üretmemesini tasarlamak; idempotency anahtarları ve uygulama katmanında pratik çözümler. - [Laravel'de gerçek zamanlı özellikler: WebSocket ve broadcasting](https://www.muhammetsafak.com.tr/blog/laravelde-gercek-zamanli-ozellikler-websocket-ve-broadcasting/): Laravel Broadcasting ile anlık güncelleme eklemek: olay tabanlı yayın, Pusher entegrasyonu ve istemci tarafında dinlemek. - [API'leri OpenAPI ile belgelemek](https://www.muhammetsafak.com.tr/blog/apileri-openapi-ile-belgelemek/): Belgeyi koddan türetmek ve istemcilerle tek doğru kaynağı paylaşmak: OpenAPI spesifikasyonunu günlük geliştirme akışına entegre etmek. - [API tasarımını sözleşme öncelikli (contract-first) yürütmek](https://www.muhammetsafak.com.tr/blog/api-tasarimini-sozlesme-oncelikli-contract-first-yurutmek/): Önce sözleşme, sonra kod yaklaşımının ekipler arası beklentiyi nasıl hizaladığı ve pratikte ne anlama geldiği. - [REST'ten sonra: GraphQL'i denemek](https://www.muhammetsafak.com.tr/blog/restten-sonra-graphqli-denemek/): Gerçek bir over-fetching sorununu GraphQL ile çözerken REST'in nerede yeterli, GraphQL'in nerede anlam kazandığını tartıyorum. - [API hata sözleşmesi: istemciye anlamlı hata döndürmek](https://www.muhammetsafak.com.tr/blog/api-hata-sozlesmesi-istemciye-anlamli-hata-dondurmek/): API hata yanıtlarını tutarlı bir sözleşmeye bağlamak, istemci geliştirmeyi ve hata ayıklamayı nasıl kolaylaştırır. - [Laravel 7 ve Sanctum ile SPA kimlik doğrulama](https://www.muhammetsafak.com.tr/blog/laravel-7-ve-sanctum-ile-spa-kimlik-dogrulama/): Laravel Sanctum'un SPA kimlik doğrulamasını nasıl çözdüğünü, token tabanlı yaklaşımdan farkını somut örneklerle anlatıyorum. - [API yanıtlarını standartlaştırmak: tutarlı bir sözleşme](https://www.muhammetsafak.com.tr/blog/api-yanitlarini-standartlastirmak-tutarli-bir-sozlesme/): Her uçta aynı yanıt yapısını döndürmek istemci kodunu nasıl sadeleştirir ve hataları nasıl öngörülebilir kılar? - [API tasarımında sürümleme (versioning) kararları](https://www.muhammetsafak.com.tr/blog/api-tasariminda-surumleme-versioning-kararlari/): İstemcileri kırmadan bir API'yi nasıl evrimleştirirsiniz? Sürümleme stratejilerini trade-off'larıyla karşılaştırıyor, gerçek deneyimlerimi paylaşıyorum. - [Laravel'de zamanlanmış görevler (task scheduling)](https://www.muhammetsafak.com.tr/blog/laravelde-zamanlanmis-gorevler-task-scheduling/): Laravel'in görev zamanlayıcısıyla sunucudaki tek bir cron satırından birden çok görevi kod içinde okunur biçimde nasıl planladığımı anlatıyorum. - [Laravel'de çok dilli (i18n) uygulama](https://www.muhammetsafak.com.tr/blog/laravelde-cok-dilli-i18n-uygulama/): Laravel'de çok dilli destek eklemek için dil dosyalarını düzenlemek, metinleri koddan ayırmak ve dil geçişini yönetmek üzerine pratik notlar. - [Laravel'de bildirimler (notifications): e-posta ve SMS](https://www.muhammetsafak.com.tr/blog/laravelde-bildirimler-notifications-e-posta-ve-sms/): Laravel Notification sınıflarıyla aynı bildirim mantığını e-posta, SMS gibi birden çok kanaldan nasıl gönderdiğimi anlatıyorum. - [Laravel API kaynak (resource) sınıflarıyla yanıt biçimlemek](https://www.muhammetsafak.com.tr/blog/laravel-api-kaynak-resource-siniflariyla-yanit-bicimlemek/): Laravel API Resource sınıflarıyla veritabanı modelini istemciye doğrudan sızdırmadan temiz yanıtlar nasıl üretilir, örneklerle anlatıyorum. - [Laravel policy ve gate ile yetkilendirme](https://www.muhammetsafak.com.tr/blog/laravel-policy-ve-gate-ile-yetkilendirme/): Laravel'de Gate ve Policy ile yetkilendirme mantığını tek yerde toplamak; 'kim neyi yapabilir' kararlarını temiz kurmak. - [Üçüncü parti API tüketmek: Guzzle ile HTTP istemcisi](https://www.muhammetsafak.com.tr/blog/ucuncu-parti-api-tuketmek-guzzle-ile-http-istemcisi/): PHP'de Guzzle HTTP istemcisi ile dış servislere bağlanmak; timeout, hata yönetimi ve güvenilir istek yapısı kurmak. - [Laravel ile e-posta gönderimi ve şablonları](https://www.muhammetsafak.com.tr/blog/laravel-ile-e-posta-gonderimi-ve-sablonlari/): Laravel Mailable sınıfı ve Blade e-posta şablonları ile işlemsel e-postaları güvenilir ve bakımı kolay şekilde kurmak. - [REST API'de sayfalama, filtreleme ve sıralama](https://www.muhammetsafak.com.tr/blog/rest-api-de-sayfalama-filtreleme-ve-siralama/): Büyüyen veri kümelerini istemciye yönetilebilir sunmak için API'de sayfalama, filtreleme ve sıralama parametrelerini nasıl tasarladığımı anlatıyorum. - [Laravel ile dosya yükleme ve görsel işleme](https://www.muhammetsafak.com.tr/blog/laravel-ile-dosya-yukleme-ve-gorsel-isleme/): Laravel'de dosya yükleme, doğrulama ve görseli yeniden boyutlandırma adımlarını kapsayan uçtan uca akışı anlatıyorum. - [Laravel ile JSON API uçları yazmak](https://www.muhammetsafak.com.tr/blog/laravel-ile-json-api-uclari-yazmak/): Laravel'de arayüzden bağımsız JSON API uç noktaları oluşturmanın pratik yollarını anlattım. - [RESTful API tasarımının temelleri](https://www.muhammetsafak.com.tr/blog/restful-api-tasariminin-temelleri/): Kaynak, HTTP yöntemi ve durum kodu üçgeninde bir API'yi tahmin edilebilir kılmanın pratik kurallarını anlattım. - [Laravel ile form doğrulama (validation) pratiği](https://www.muhammetsafak.com.tr/blog/laravel-ile-form-dogrulama-validation-pratigi/): Kullanıcı girdisini güvenle karşılamanın tekrar edilebilir kalıbı: Laravel doğrulama kuralları ve hata mesajları. ## Blog — Arayüz - [Modern CSS'i yeniden keşfetmek](https://www.muhammetsafak.com.tr/blog/modern-cssi-yeniden-kesfetmek/): Yıllarca JavaScript ve önişlemciyle çözdüğümüz şeyler artık CSS'in kendisinde: container query, :has() ve yerel nesting. - [React 19 ve form'ların yeni hali (actions)](https://www.muhammetsafak.com.tr/blog/react-19-ve-formlarin-yeni-hali-actions/): React 19'un kararlı sürümüyle gelen form actions modelini, mevcut yaklaşımlarla kıyaslayarak değerlendiriyorum. - [Tailwind CSS 4: yeni motor ve yapılandırma](https://www.muhammetsafak.com.tr/blog/tailwind-css-4-yeni-motor-ve-yapilandirma/): Tailwind CSS 4 ile gelen Oxide motoru ve CSS-öncelikli yapılandırma yaklaşımını, büyük bir sürüm geçişinin gerektirdiği sakinlikle değerlendiriyorum. - [Frontend'de durum yönetimi: Pinia ile Vuex sonrası](https://www.muhammetsafak.com.tr/blog/frontendde-durum-yonetimi-pinia-ile-vuex-sonrasi/): Vue ekosisteminde Pinia'nın Vuex'in yerini alması: daha az şablon kod, daha iyi TypeScript desteği ve olgunlaşan durum yönetimi anlayışı. - [React 18 ve concurrent render](https://www.muhammetsafak.com.tr/blog/react-18-ve-eszamanli-concurrent-render/): React 18'in eşzamanlı render modeli uygulamanın hangi davranışlarını değiştiriyor ve bu değişimi pratikte nasıl karşılamak gerekiyor. - [Tek sayfa uygulamada SEO sorunu ve SSR seçenekleri](https://www.muhammetsafak.com.tr/blog/tek-sayfa-uygulamada-seo-sorunu-ve-ssr-secenekleri/): İstemci taraflı render'ın arama motorları için yarattığı görünürlük sorununu ve sunucu taraflı render seçeneklerini karşılaştırıyorum. - [Vue 3 Composition API: neden ve ne zaman](https://www.muhammetsafak.com.tr/blog/vue-3-composition-api-neden-ve-ne-zaman/): Vue 3 ile gelen Composition API'nin Options API'ye göre ne getirdiğini, ne zaman tercih edilmesi gerektiğini somut örneklerle tartışıyorum. - [Alpine.js: küçük etkileşimler için hafif bir seçim](https://www.muhammetsafak.com.tr/blog/alpine-js-kucuk-etkilesimler-icin-hafif-bir-secim/): Alpine.js'i ne zaman seçmeli, ne zaman seçmemeli? Tam framework gerektirmeyen arayüz ihtiyaçları için doğru ölçeği tartışıyorum. - [Tailwind CSS: utility-first yaklaşımına neden geçtim](https://www.muhammetsafak.com.tr/blog/tailwind-css-utility-first-yaklasimina-neden-gectim/): Tailwind CSS v1.0 ile utility-first CSS paradigmasını neden benimsedim, hangi trade-off'larla karşılaştım ve ne zaman gerçekten işe yarıyor? - [React hooks ile bileşen yazmanın değişen yüzü](https://www.muhammetsafak.com.tr/blog/react-hooks-ile-bilesen-yazmanin-degisen-yuzu/): React 16.8 ile gelen hooks API'si, sınıf bileşeninden fonksiyon bileşenine geçişi nasıl değiştirdi? Avantajları ve dikkat edilmesi gereken noktalar. - [Frontend'de Axios ile API tüketmek](https://www.muhammetsafak.com.tr/blog/frontendde-axios-ile-api-tuketmek/): Axios kütüphanesiyle istek/yanıt katmanını arayüzde temiz tutmak için interceptor, hata yönetimi ve ortak yapılandırma üzerine pratik notlar. - [Vue ile bileşen tabanlı arayüz mimarisine geçiş](https://www.muhammetsafak.com.tr/blog/vue-ile-bilesen-tabanli-arayuz-mimarisine-gecis/): Sayfa odaklı düşünmekten bileşen (component) odaklı düşünmeye geçişi ve Vue.js'in bunu pratikte nasıl sağladığını anlatıyorum. - [Responsive tasarım: mobil öncelikli CSS](https://www.muhammetsafak.com.tr/blog/responsive-tasarim-mobil-oncelikli-css/): Mobil öncelikli (mobile-first) CSS yaklaşımı nedir, media query ile tek arayüzü farklı ekran boyutlarında düzgün tutmak nasıl sağlanır. - [Vuex ile Vue uygulamasında durum yönetimi](https://www.muhammetsafak.com.tr/blog/vuex-ile-vue-uygulamasinda-durum-yonetimi/): Vuex ile bileşenler arası paylaşılan durumu tek bir kaynakta toplamak; state, mutation, action ve getter kavramları. - [Sass ile sürdürülebilir CSS yazmak](https://www.muhammetsafak.com.tr/blog/sass-ile-surdurulebilir-css-yazmak/): Büyüyen stil dosyalarını Sass değişkenleri, iç içe kurallar ve parçalara bölme ile nasıl düzene soktuğumu anlatıyorum. - [Vue Router ile tek sayfa uygulama (SPA) mantığı](https://www.muhammetsafak.com.tr/blog/vue-router-ile-tek-sayfa-uygulama-spa-mantigi/): Vue Router ile sayfa geçişlerini istemci tarafına taşırken karşılaştığım temel kavramları ve pratik kurulumu aktarıyorum. - [Vue.js ile ilk reaktif bileşen](https://www.muhammetsafak.com.tr/blog/vue-js-ile-ilk-reaktif-bilesen/): jQuery ile DOM manipülasyonundan Vue.js'in veri odaklı yaklaşımına geçiş deneyimimi ve ilk reaktif bileşeni nasıl yazdığımı anlatıyorum. - [Bootstrap 3 ile hızlı ve tutarlı arayüz kurmak](https://www.muhammetsafak.com.tr/blog/bootstrap-3-ile-hizli-ve-tutarli-arayuz-kurmak/): Tasarımcı olmadan düzgün görünen arayüz üretmenin yolu: Bootstrap 3 grid sistemi ve hazır bileşenler. - [jQuery ile AJAX: sayfayı yenilemeden veri göndermek](https://www.muhammetsafak.com.tr/blog/jquery-ile-ajax-sayfayi-yenilemeden-veri-gondermek/): Form gönderimini sayfa yüklemeden ayırmanın 2014'teki standardı: jQuery $.ajax kullanımı ve pratik örnekler. ## Blog — Araçlar & Teknolojiler - [Partial index'i hız için seçmeyin](https://medium.com/@muhammetsafak/partial-indexi-hiz-icin-secmeyin-d47f71da2b30): 10 milyon ölü satırlı bir Postgres kuyruk tablosunda dört index stratejisini ölçtüm: kazanan beklediğim gerekçeyle kazanmadı ve tek bir ayar onu 1.673 kat yavaşlattı. - [Production'da Git: Senior'ın Pratik Rehberi](https://www.muhammetsafak.com.tr/blog/production-git-senior-pratik-rehberi/): Workflow seçiminden bisect ile bug avına, rebase disiplininden worktree ve signed commit'lere — Git'i bir yıllarca kullandıktan sonra fark ettiklerim. - [Biri Github Actions mı dedi?](https://www.muhammetsafak.com.tr/blog/biri-github-actions-mi-dedi/): GitHub Actions ile CI/CD'ye giriş: iş akışları (workflow) nasıl kurulur ve süreçler nasıl otomatikleştirilir? - [ElasticSearch ve Kibana ile Büyük Veriye Giriş](https://www.muhammetsafak.com.tr/blog/elasticsearch-ve-kibana-ile-buyuk-veriye-giris/): Elasticsearch ve Kibana ile büyük veriye giriş: metin arama, analiz ve görselleştirmenin temelleri. - [RabbitMQ (PHP ile)](https://www.muhammetsafak.com.tr/blog/php-rabbitmq/): PHP ile RabbitMQ kullanımı: mesaj kuyruğu oluşturma, mesaj gönderme (publish) ve tüketme (consume). - [Docker sanallaştırma: kurulum ve temel kullanım](https://www.muhammetsafak.com.tr/blog/docker-sanallastirma-teknolojisi-kurulum-kullanim/): Docker'ın container mimarisini, temel komutlarını ve volume/network kavramlarını uygulamalı olarak anlatan bir başlangıç rehberi. - [Laravel'de test yazma alışkanlığı: Pest'e geçiş](https://www.muhammetsafak.com.tr/blog/laravelde-test-yazma-aliskanligi-peste-gecis/): PHPUnit'ten Pest'e geçerken test yazmayı külfetten alışkanlığa çeviren sözdizimi ve yapı farklarını anlatıyorum. - [MySQL Depolama Motorları (InnoDB vs MyISAM)](https://www.muhammetsafak.com.tr/blog/mysql-depolama-motorlari-innodb-vs-myisam/): MySQL depolama motorları: InnoDB ile MyISAM arasındaki farklar, avantajlar ve hangi durumda hangisi seçilmeli? - [Vite ile geliştirme sunucusunu saniyelere indirmek](https://www.muhammetsafak.com.tr/blog/vite-ile-gelistirme-sunucusunu-saniyelere-indirmek/): Webpack tabanlı bir geliştirme ortamından Vite'a geçince derleme sürelerinin neden bu kadar kısaldığını inceliyorum. - [Vue bileşenlerini test etmek](https://www.muhammetsafak.com.tr/blog/vue-bilesenleri-test-etmek/): Vue bileşenlerinin arayüz davranışını otomatik olarak doğrulamanın pratik yolu: Vue Test Utils ile gerçek senaryolar üzerinden test yazımı. - [npm ve modern JavaScript paket ekosistemi](https://www.muhammetsafak.com.tr/blog/npm-ve-modern-javascript-paket-ekosistemi/): npm ile JavaScript bağımlılıklarını yönetmek, package.json dosyasını doğru yapılandırmak ve paket ekosisteminde karşılaşılan pratik sorunları anlatıyorum. - [PHPUnit ile ilk testlerimi yazmak](https://www.muhammetsafak.com.tr/blog/phpunit-ile-ilk-testlerimi-yazmak/): PHPUnit kurulumundan başlayarak ilk birim testlerimi nasıl yazdığımı, hangi şeylerin işe yaradığını ve hangi tuzaklara düştüğümü anlatıyorum. - [Git akışı: branch, merge ve pull request disiplini](https://www.muhammetsafak.com.tr/blog/git-akisi-branch-merge-ve-pull-request-disiplini/): Git ile dallanma (branching) alışkanlıkları, merge stratejileri ve pull request ile izlenebilir bir değişiklik geçmişi kurmak. - [Laravel Mix ile varlık derlemeyi basitleştirmek](https://www.muhammetsafak.com.tr/blog/laravel-mix-ile-varlik-derlemeyi-basitlestirmek/): Laravel Mix, Webpack yapılandırması yazmadan JavaScript ve CSS varlıklarını derlemenizi sağlayan akıcı bir API sunuyor. - [Postman ile API geliştirmeyi hızlandırmak](https://www.muhammetsafak.com.tr/blog/postman-ile-api-gelistirmeyi-hizlandirmak/): API uçlarını tarayıcı olmadan denemek, koleksiyonlar oluşturmak ve Postman'i iş akışına dahil etmek hakkında öğrendiklerimi paylaşıyorum. - [Webpack'e geçiş: Gulp'tan modül paketlemeye](https://www.muhammetsafak.com.tr/blog/webpack-e-gecis-gulp-tan-modul-paketlemeye/): Gulp ile kurduğum derleme hattını neden terk ettiğimi ve Webpack'e geçerken karşılaştığım zorlukları ve kazanımları aktarıyorum. - [Composer ile kendi paketimi Packagist'te yayımlamak](https://www.muhammetsafak.com.tr/blog/composer-ile-kendi-paketimi-packagistte-yayimlamak/): Bir PHP paketini sıfırdan yapılandırıp Packagist'e göndererek başkalarının kullanımına açtım; adımları aktarıyorum. - [Gulp ile front-end derleme hattı kurmak](https://www.muhammetsafak.com.tr/blog/gulp-ile-front-end-derleme-hatti-kurmak/): Gulp ile Sass derleme, JavaScript birleştirme ve tarayıcı yenilemeyi otomatikleştiren bir front-end iş akışı kurdum. - [Laravel Homestead ile herkeste aynı geliştirme ortamı](https://www.muhammetsafak.com.tr/blog/laravel-homestead-ile-herkeste-ayni-gelistirme-ortami/): Laravel Homestead'ı kurup ekipte 'bende çalışıyordu' sorununu nasıl çözdüğümü adım adım anlattım. - [Git'e geçiş: FTP ile dosya atmayı bırakmak](https://www.muhammetsafak.com.tr/blog/gite-gecis-ftp-ile-dosya-atmayi-birakmak/): Sürüm kontrolüyle gelen güven: FTP'den Git'e geçişin değiştirdiği geliştirme alışkanlığı, temel commit ve branch kullanımı. - [Composer'a geçiş: PHP bağımlılıklarını elle yönetmeyi bırakmak](https://www.muhammetsafak.com.tr/blog/composera-gecis-php-bagimliliklarini-elle-yonetmeyi-birakmak/): require yığınından modern bağımlılık yönetimine geçişin pratiği: composer.json, autoload ve paket kurma. ## Blog — Günlük - [Kriz anı: şirketin karakteri orada belli olur](https://www.muhammetsafak.com.tr/blog/kriz-ani-sirketin-karakteri-orada-belli-olur/): Production yandığında sorulan ilk soru şirketin kültürünü yıllarca belirler. Krizin insan tarafı: korku, sessizlik ve altı hafta sonra gerçekten değişen şey. - [Toplantı, raporlama ve görünürlük tiyatrosu](https://www.muhammetsafak.com.tr/blog/toplanti-raporlama-ve-gorunurluk-tiyatrosu/): Statü toplantısı bir bilgi aracı değil, bir sigortadır. Toplantının neden var olduğunu ciddiye alan bir eleştiri ve üç ayrı masadan bakış. - [Performans, terfi ve zam: sistem olsa da olmasa da bir pazarlık var](https://www.muhammetsafak.com.tr/blog/performans-terfi-ve-zam-sistem-olsa-da-olmasa-da-bir-pazarlik-var/): Zam kurumsalda bir tabloya, patron şirketinde bir hatıraya bağlıdır. Sistemin varlığı sonucu değiştirmiyor; sadece pazarlığın dilini değiştiriyor. - [Sıfırdan hızlı, mevcut sistemde yavaş: agent çağında brownfield'in gerçek maliyeti](https://www.muhammetsafak.com.tr/blog/sifirdan-hizli-mevcut-sistemde-yavas/): Agent'la günlerde biten iş, yıllardır çalışan bir sistemde bir hafta sürüyor. Çünkü orada asıl maliyet kod üretmek değil; kuralı bulmak ve doğrulamak. - [Bilgi nasıl akar: koridor mu, doküman mı?](https://www.muhammetsafak.com.tr/blog/bilgi-nasil-akar-koridor-mu-dokuman-mi/): Bilgi bir kişinin kafasında da kalsa, kimsenin okumadığı bir wiki'de de dursa aynı yere çıkıyor: kararın gerekçesi erişilemez. İnsan tarafından bir bakış. - [Aynı mesaj, farklı sonuç: event-driven mimaride determinizm](https://www.muhammetsafak.com.tr/blog/event-driven-mimaride-determinizm/): Event-driven mimaride aynı mesaj neden farklı sonuç üretir? Gerçek bir fatura akışından: determinizmi bozan gizli girdiler ve geri kazandıran dört hamle. - [Rol sınırları: iş tanımı olmayan yerde herkes her şeydir](https://www.muhammetsafak.com.tr/blog/rol-sinirlari-is-tanimi-olmayan-yerde-herkes-her-seydir/): Rol boşluğu bireysel fedakârlıkla kapatıldığı anda görünmez olur, görünmeyen arıza da asla düzelmez. Sınır çizmenin yolu ve üç masadan bakış. - [Süreç ne zaman zırh, ne zaman pranga?](https://www.muhammetsafak.com.tr/blog/surec-ne-zaman-zirh-ne-zaman-pranga/): Süreç bir erdem değil, ödediğiniz bir koordinasyon vergisi. Ne zaman eklenmeli, neden hiç kaldırılmıyor ve üç ayrı masadan nasıl görünüyor? - [Karar nasıl alınır: onay zinciri mi, tek imza mı?](https://www.muhammetsafak.com.tr/blog/karar-nasil-alinir-onay-zinciri-mi-tek-imza-mi/): Şirketler kararı hızlandırmayı ya da yavaşlatmayı değil, yanlış kararı yanlış hızda almayı beceriyor. Tersinirlik çerçevesi ve üç ayrı masadan bakış. - [Kurumsal mı, patron şirketi mi? Ayıran şey büyüklük değil](https://www.muhammetsafak.com.tr/blog/kurumsal-mi-patron-sirketi-mi/): Şirket tiplerini ayıran şey çalışan sayısı değil; kararın nerede alındığı ve ne kadarının yazıya döküldüğü. Dört eksenli bir ayrım ve üç ayrı masadan bakış. - [Dual-write'tan outbox'a: idempotent tüketim ve alan-seviyesi şifreleme günlüğü](https://www.muhammetsafak.com.tr/blog/outbox-idempotent-tuketim-ve-alan-sifrelemesi/): Aynı projede dual-write yüzünden kaybolan event'ler beni transactional outbox'a, at-least-once teslim de idempotent tüketime götürdü. Bir de GDPR alanlarını x-gdpr-sensitive ile satır seviyesinde şifreledim. Gerçek bir projeden notlar. - [archlint: mimari sınırları CI'da deterministik olarak zorlamak](https://www.muhammetsafak.com.tr/blog/archlint-mimari-sinirlari-ci-da-zorlamak/): Mimari kararlar wiki'de doğru kalır, kodda çürür. archlint'i yazdım: architecture.json'daki katman+kural sınırlarını her commit'te go/parser ile, modelsiz, CI'da zorlayan bağımsız bir Go CLI. Niye böyle kurduğumu anlatıyorum. - [Tek mimari kuralı, üç dil: archlint artık Go + TypeScript + Python](https://www.muhammetsafak.com.tr/blog/archlint-tek-kural-uc-dil/): Polyglot bir repoda 'domain altyapıyı import etmesin' kuralı her dilde aynı; değişen, import'un nasıl çözüldüğü. archlint'e TypeScript ve Python ekledim — tek architecture.json üç dilin sınırlarını CI'da zorluyor. - [CommitBrief'e flaky-test dedektörü: AI'ın yazdığı kararsız testleri commit'te durdurmak](https://www.muhammetsafak.com.tr/blog/commitbrief-flaky-test-dedektoru/): CommitBrief'e deterministik bir flaky-test süzgeci ekledim. LLM'e sormak yerine, değişen test dosyalarındaki sabit sleep'leri ve seed'siz rastgeleliği commit aşamasında — modelsiz — yakalıyor. Niye LLM prompt'u değil de statik analiz seçtiğimi anlatıyorum. - [CommitBrief'e summary ve remote: değişikliğin brifini almak, PR'ı terminalden incelemek](https://www.muhammetsafak.com.tr/blog/commitbrief-summary-ve-remote/): CommitBrief'e iki yeni komut geldi: summary değişikliğin ve geçmişinin brifini çıkarıyor, remote pr ise PR'ı terminalden inceleyip yorumu insandan önce bırakıyor. İnsan reviewer'ın yerini değil, önünü açmak için. - [Vibe coding mi, AI destekli geliştirme mi — ve neden hâlâ bir senior'a ihtiyaç var](https://www.muhammetsafak.com.tr/blog/vibe-coding-mi-ai-destekli-gelistirme-mi/): Vibe coding ürün çıkarmayı gerçekten kolaylaştırdı. Ama yazılım ve sistem mimarisi bilmeyen birinin production'a çıkardığıyla, AI'ı yöneten bir senior'ın çıkardığı aynı şey değil. Üç seviye, üç farklı kalite. - [Bir e-fatura entegrasyonunda numara çakışmasını çözmek](https://www.muhammetsafak.com.tr/blog/e-fatura-entegrasyonunda-numara-cakismasi/): Üretimde iki worker aynı fatura numarasını üretti. Race condition ile yasal 'gap' arasındaki ikilemi gerçek bir projede nasıl çözdüğümün günlüğü. - [AI ile self-review — neyi hızlandırıyor, nerede yetmiyor](https://www.muhammetsafak.com.tr/blog/ai-ile-self-review-neyi-hizlandiriyor-nerede-yetmiyor/): Üç ay önce kendi diff'imi denetleyecek bir tool yazdım. Bu yazı 'niye' değil 'ne kadar' yazısı: workflow'a hangi katmanlarda giriyor, hangi rakamlarla hızlandırıyor, hangi bug pattern'lerini tekrar tekrar yakalıyor — ve nerede sınırına dayanıyor. - [Hangi Projede Hangi Metodoloji? — 18 Yıllık Bir Geliştiricinin Notları](https://www.muhammetsafak.com.tr/blog/hangi-projede-hangi-metodoloji-karar-matrisi/): Waterfall mı, Agile mı, Hybrid mi? Soru yanlış. 18 yıllık production tecrübesinden bir karar matrisi, üç gerçek vaka ve metodoloji dininden çıkış. - [Kendi diff'imi bir tool'a soruyorum — CommitBrief'i niye yazdım](https://www.muhammetsafak.com.tr/blog/kendi-diffimi-bir-tool-a-soruyorum-commitbrief/): Self-review körlüğüyle yüzleştiğim bir öğleden sonra, terminalden çıkmadan kendi diff'imi denetleyen bir tool yazdım: CommitBrief. Niye yazdığım, nasıl çalıştığı ve hangi soruyu çözdüğü üzerine bir not. - [Bu günlüğün on iki yılı: geriye dönüp bakmak](https://www.muhammetsafak.com.tr/blog/bu-gunlugun-on-iki-yili-geriye-donup-bakmak/): 2014'ten 2026'ya bu günlükte yazılan her şey bir araya geldiğinde anlattığı gelişim hikâyesi ve kapanış. - [Görünür olmak: yazmak neden bir kariyer yatırımıdır](https://www.muhammetsafak.com.tr/blog/gorunur-olmak-yazmak-neden-bir-kariyer-yatirimidir/): Yazmak, düşünceyi netleştirir ve zamanla birikim sağlar. Kişisel marka değil, dürüst bir iz olarak görünür olmanın kariyer değeri üzerine. - [Polyglot olmak bir hedef değil bir sonuçmuş](https://www.muhammetsafak.com.tr/blog/polyglot-olmak-bir-hedef-degil-bir-sonucmus/): Çok dilli geliştirici olmak nasıl bir hedefe dönüştü, neden aslında hiç öyle olmadığını ve buna nasıl ulaştığımı düşünüyorum. - [On bir yılın ardından: bir geliştiricinin değişen önceliği](https://www.muhammetsafak.com.tr/blog/on-bir-yilin-ardindan-bir-gelistiricinin-degisen-onceligi/): Bu günlüğün on bir yılında bir geliştiricinin önceliklerinin hızdan dayanıklılığa, koddan karara nasıl kaydığının değerlendirmesi. - [Yapay zeka çağında kod yazmanın değişen el becerisi](https://www.muhammetsafak.com.tr/blog/yapay-zeka-caginda-kod-yazmanin-degisen-el-becerisi/): Yapay zeka araçları kod yazmanın ne kadarını devraldı, geliştiriciye ne kaldı? Değişen el becerisi üzerine bir değerlendirme. - [Mentorluk ve bilgi paylaşımı: başkasını büyütürken büyümek](https://www.muhammetsafak.com.tr/blog/mentorluk-ve-bilgi-paylasimi-baskasini-buyuturken-buyumek/): Mentorluğun bir fedakârlık değil, kıdemli bir geliştirici için kendi gelişiminin de aracı olduğu üzerine bir kariyer yazısı. - [Bir özelliği fikirden üç platforma: uçtan uca akışım](https://www.muhammetsafak.com.tr/blog/bir-ozelligi-fikirden-uc-platforma-uctan-uca-akisim/): Bir özelliği API, web ve mobilde aynı anda teslim ettiğimde izlediğim olgunlaşmış, tekrarlanabilir süreci anlatıyorum. - [Uzman mı, genelci mi: T-tipi bir kariyer](https://www.muhammetsafak.com.tr/blog/uzman-mi-genelci-mi-t-tipi-bir-kariyer/): Derin uzmanlaşma ile geniş genelcilik arasındaki gerilimi ve T-tipi kariyer modelinin bu denklemi nasıl çözdüğünü aktarıyorum. - [Expo'da güncellemeleri OTA ile yönetmek](https://www.muhammetsafak.com.tr/blog/expoda-guncellemeleri-ota-ile-yonetmek/): Expo Updates ile mağaza döngüsünü beklemeden hızlı düzeltme yayınlamanın pratiklerini ve sınırlarını aktarıyorum. - [Polyglot bir kod tabanını sürdürmek: bağlam değiştirme maliyeti](https://www.muhammetsafak.com.tr/blog/polyglot-bir-kod-tabanini-surdurumek-baglan-degistirme-maliyeti/): Birden çok dilde aynı anda çalışmanın görünmeyen bilişsel bedeli ve bunu nasıl yönettiğimi aktarıyorum. - [Kendi ürününü tek başına kurmak: Looplio deneyimi](https://www.muhammetsafak.com.tr/blog/kendi-urununu-tek-basina-kurmak-looplio-deneyimi/): API, web ve mobili tek başına yürüten bir geliştiricinin dürüst günlüğü; tek kişilik ürün geliştirmenin getirdiği ve götürdükleri. - [Bir özelliği üç katmanda (API, web, mobil) birden teslim etmek](https://www.muhammetsafak.com.tr/blog/bir-ozelligi-uc-katmanda-api-web-mobil-birden-teslim-etmek/): Tek bir özelliği API, web ve mobil katmanlarında birlikte teslim etmenin uçtan uca akışı; Looplio üzerinde edindiğim pratik. - [Home (Cloud) Server Pi5 Upgrade](https://www.muhammetsafak.com.tr/blog/home-cloud-server-pi5-upgrade/): Raspberry Pi 5 ile ev bulut sunucusu kurulumu: CasaOS, NextCloud, RAID depolama ve Cloudflare Tunnel. - [Expo ile mobil uygulamayı mağazaya göndermek](https://www.muhammetsafak.com.tr/blog/expo-ile-mobil-uygulamayi-magazaya-gondermek/): Expo ve EAS Build ile bir React Native uygulamasını App Store ve Google Play'e gönderme sürecinin gerçek deneyimi ve hazırlık adımları. - [React Native'de performans: liste render'ı](https://www.muhammetsafak.com.tr/blog/react-native-de-performans-liste-renderi/): React Native'de büyük listeleri akıcı tutmanın somut teknikleri; FlatList, memo ve keyExtractor kullanımı ile gerçek deneyimler. - [Yan projeler ve açık kaynak: kariyere kattıkları ve gerçek maliyeti](https://www.muhammetsafak.com.tr/blog/yan-projeler-ve-acik-kaynak-kariyere-kattiklari-ve-gercek-maliyeti/): Yan projelerin ve açık kaynağın kariyere etkisini dürüstçe değerlendirmek: getiri, maliyet ve bir projeyi ne zaman arşivlemenin doğru olduğu. - [Mobil ve web'i aynı takvim mantığıyla beslemek (Looplio günlüğü)](https://www.muhammetsafak.com.tr/blog/mobil-ve-webi-ayni-takvim-mantigiyla-beslemek-looplio-gunlugu/): Looplio'da tek bir iş mantığını hem React Native hem web istemcisine tutarlı biçimde sunmanın pratik kararları ve öğretileri. - [React Native'de gezinme (navigation) ve ekran mimarisi](https://www.muhammetsafak.com.tr/blog/react-native-de-gezinme-navigation-ve-ekran-mimarisi/): React Native Navigation Stack, Tab ve Drawer yapılarını Looplio bağlamında kurmanın pratik kararları ve ekran mimarisi yaklaşımı. - [İş değiştirme kararı: kalmak mı, gitmek mi](https://www.muhammetsafak.com.tr/blog/is-degistirme-karari-kalmak-mi-gitmek-mi/): Ayrılma ya da kalma kararını duygusal tepkiden ölçülebilir bir değerlendirmeye çevirmek; meşru sinyalleri geçici hayal kırıklığından ayırt etmek. - [Bir yılda dört dil: polyglot pratiğin getirdiği zihin esnekliği](https://www.muhammetsafak.com.tr/blog/bir-yilda-dort-dil-polyglot-pratigin-getirdigi-zihin-esnekligi/): Bir yıl içinde PHP, Go, Python ve TypeScript arasında gidip gelmenin düşünme biçimine etkisi üzerine bir değerlendirme. - [Hype'ı filtrelemek: her yeni teknolojiyi öğrenmek zorunda değilsin](https://www.muhammetsafak.com.tr/blog/hypei-filtrelemek-her-yeni-teknolojiyi-ogrenmek-zorunda-degilsin/): Sürekli yeni araç ve framework baskısı karşısında öğrenme bütçesini yönetmek: hangi teknolojiyi ne zaman öğreneceğinize karar vermek için pratik bir yaklaşım. - [React Native ve Expo ile mobil uygulamaya ilk adım](https://www.muhammetsafak.com.tr/blog/react-native-ve-expo-ile-mobil-uygulamaya-ilk-adim/): Web geliştiricisinin mobil dünyaya geçiş deneyimi: Looplio'yu React Native ve Expo ile kurarken öğrendiklerim ve beklentilerimin nasıl değiştiği. - [2014'teki kendime: ilk yıllara dair tavsiyeler](https://www.muhammetsafak.com.tr/blog/2014-teki-kendime-ilk-yillara-dair-tavsiyeler/): Bu günlüğün başladığı yıla, 2014'e dönüp bakmak: erken kariyer yıllarında neye fazla, neye az önem verdiğim ve değiştirmek istediğim şeyler. - [Yapay zekanın kod yazmaya etkisini ilk kez ciddiye almak](https://www.muhammetsafak.com.tr/blog/yapay-zekanin-kod-yazmaya-etkisini-ilk-kez-ciddiye-almak/): ChatGPT'yi aylardır kullanıyorum; ama bu ay bir şey değişti. Bir merakı, çalışma biçimimi sorgulatan gerçek bir gözleme dönüştüren an. - [ChatGPT'yi bir geliştirici olarak ilk kez kullanmak](https://www.muhammetsafak.com.tr/blog/chatgpti-bir-gelistirici-olarak-ilk-kez-kullanmak/): OpenAI'nin yeni çıkan ChatGPT aracını birkaç gün denedikten sonra bir geliştiricinin dürüst ilk izlenimleri: nerede etkileyici, nerede güvenilmez. - [Kıdem: ünvanla gelmeyen sorumluluk](https://www.muhammetsafak.com.tr/blog/kidem-unvanla-gelmeyen-sorumluluk/): Ünvan çoğu zaman gerçek kıdemden önce gelir. Kıdemin teknik bilgi değil belirsizlik altında karar verme kapasitesi olduğu üzerine. - [Polyglot bir geliştirici olmak: dili probleme göre seçmek](https://www.muhammetsafak.com.tr/blog/polyglot-bir-gelistirici-olmak-dili-probleme-gore-secmek/): Birden çok programlama diline hâkim olmanın bir kimlik meselesi değil, araç seçimi meselesi olduğu üzerine kişisel notlar. - [Bir yazılımcı olarak araç setimi sadeleştirmek](https://www.muhammetsafak.com.tr/blog/bir-yazilimci-olarak-arac-setimi-sadestirmek/): Senior'dan staff seviyesine geçerken araç yığınımı gözden geçirdim. Daha az araç, daha net karar aldığımı fark ettim. - [Python'a giriş: bir betik dili daha neden](https://www.muhammetsafak.com.tr/blog/python-a-giris-bir-betik-dili-daha-neden/): Polyglot pratiğimde Python'un doldurduğu boşluğu, öğrenme sürecimi ve PHP geliştiricisinin Python'a bakışını anlatıyorum. - [Polyglot'a ilk adım: neden Go öğrenmeye başladım](https://www.muhammetsafak.com.tr/blog/polyglota-ilk-adim-neden-go-ogrenmeye-basladim/): On yılı aşkın PHP deneyiminin ardından neden ikinci bir dil öğrenmeye karar verdim? Go'yu seçmemin gerekçesi ve bu süreçten beklentilerim. - [2018'in muhasebesi: bir PHP geliştiricisi nereye geldi](https://www.muhammetsafak.com.tr/blog/2018in-muhasebesi-bir-php-gelistiricisi-nereye-geldi/): 2018 boyunca öğrendiklerimi, değişen alışkanlıklarımı ve önümüzdeki dönem için belirlediğim hedefleri dürüstçe değerlendiriyorum. - [Laravel ile takvim/etkinlik özelliği kurmak](https://www.muhammetsafak.com.tr/blog/laravel-ile-takvim-etkinlik-ozelligi-kurmak/): Tarih, tekrar kuralı ve zaman dilimi içeren bir takvim özelliğini Laravel'de uçtan uca kurma deneyimimi paylaşıyorum. - [Laravel ile ödeme entegrasyonu (iyzico) deneyimi](https://www.muhammetsafak.com.tr/blog/laravel-ile-odeme-entegrasyonu-iyzico-deneyimi/): Laravel projelerinde iyzico ödeme entegrasyonu yaparken karşılaşılan gerçek sorunlar ve çözümleri; deneyim anlatısı.