Black Friday 2026'da Next.js E-Ticaret Ölçeklendirme: 50K Eş Zamanlı Kullanıcı, Sıfır Kesinti
Next.js tabanlı bir e-ticaret sitesinin Black Friday trafiğini ayakta geçirmesi için uyguladığımız darboğaz tespiti ve düzeltme kalıpları.
Ekiplerin hazırlanmasına yardım ettiğimiz tipik senaryo: 40.000 ila 50.000 trafik bekleyen bir Next.js e-ticaret sitesi, yük testinde 8.000 eş zamanlı kullanıcıda çöker. Aşağıdaki playbook, gerçek yığınlarda önce ne kırıldığına dair profiling temelli, sırasıyla uyguladığımız düzeltme setidir.
Öncelikle profil çıkardık. Darboğazın sebebi kimsenin beklediği yerde değildi. Ürün listeleme sayfaları iyiydi, ISR ile statik oluşturulmuşlardı. Sorun sepet ve ödeme akışıydı. Her sepete ekleme işlemi, tüm sepeti (fiyatlar, indirimler, kargo tahminleri, vergi) senkron olarak yeniden hesaplayan tam bir sunucu gidiş-dönüşü tetikliyordu. 8K kullanıcıda Node.js sunucusu tüm zamanını sepet hesaplamalarına harcıyordu.
Düzeltme 1: Sepet durumunu iyimser güncellemelerle istemciye taşıdık. Kullanıcı bir ürün eklediğinde, UI yerel durumdan hemen güncelleniyor. Sunucu hesaplaması arka planda debounce edilmiş bir API çağrısı ile gerçekleşiyor. Sunucu aynı fikirde değilse (fiyat değişti, ürün stokta yok), uzlaştırma yapıyoruz. Bu algılanan gecikmeyi 800ms'den 40ms'ye düşürdü ve sunucu yükünü %60 azalttı.
Düzeltme 2: Ürün verileri için Redis önbellekleme. Ürün fiyatları, stok seviyeleri ve indirim kuralları her sepet hesaplamasında PostgreSQL'den çekiliyordu. 30 saniyelik TTL ile bir Redis katmanı ekledik. Yoğun trafik sırasında önbellek isabet oranı %94'tü. Bu tek başına p95 API yanıt süresini 320ms'den 45ms'ye düşürdü.
Düzeltme 3: Ürün sayfaları için edge önbellekleme. Zaten ISR kullanıyorduk, ama yeniden doğrulama süresi 60 saniyeydi. Black Friday sırasında envanter her birkaç saniyede değişiyor. Envanter webhook olayları tarafından tetiklenen talep üzerine yeniden doğrulamaya geçtik. Stok 10 birimin altına düştüğünde sayfa hemen yeniden doğrulanıyor. Aksi takdirde 60 saniyelik ISR devam ediyor.
Düzeltme 4: Veritabanı bağlantı havuzu. Orijinal kurulum sunucusuz fonksiyon çağrısı başına doğrudan PostgreSQL bağlantısı kullanıyordu. Ölçekte bu, dakikalar içinde 100 bağlantı limitini tüketti. İşlem modunda PgBouncer ekledik. Yüzlerce fonksiyon çağrısını 20 gerçek veritabanı bağlantısı üzerinden çokluyor. Bağlantı hataları sıfıra düştü.
Düzeltme 5: Stripe webhook yönetimi. Ödeme akışı Stripe'ı senkron olarak çağırıp, onay bekleyip, sonra veritabanını güncelleyip, sonra onay e-postası gönderiyordu. Asenkron yaptık: bir Stripe PaymentIntent oluştur, hemen başarı sayfasına yönlendir, webhook onayını asenkron ele al. Kullanıcı 'Sipariş Onaylandı'yı 4.5 saniye yerine 1.2 saniyede görüyor.
Bu beş düzeltme birlikte uygulandığında, daha önce 8K eş zamanlı kullanıcıda tıkanan bir Next.js + PostgreSQL yığını tipik olarak p95 sayfa yükleme süresi bir saniye civarında 40K-50K'yı geçer. Kesin rakamlar trafik şeklinize bağlı, ama darboğazlar ve sıraları projeler arasında dikkat çekici biçimde tutarlıdır.
Meta-ders: performans optimizasyonu neredeyse hiçbir zaman kodu daha hızlı bir dilde yeniden yazmakla ilgili değildir. Asıl darboğazın (varsayılan değil) bulunması ve onu kaldıran minimum değişikliğin yapılmasıyla ilgilidir. Beş düzeltmemizden dördü mimari değişikliklerdi, kod düzeyinde optimizasyonlar değil. Önce profil çıkarın, sonra optimize edin.
Önemli Çıkarımlar
- 01Sepet darboğazı: her sepete ekleme için tüm sepeti sunucuda yeniden hesaplamayı bırak. İyimser durumu istemciye taşı, arka planda uzlaştır. Algılanan gecikme 800ms'den on milisaniyelere düşüyor.
- 02Ürün verisi için Redis: PostgreSQL önünde 30 saniyelik TTL, p95 API yanıt süresini tipik olarak %90 üzeri isabet oranıyla yüzlerce ms'den on milisaniyelere çekiyor.
- 03Sabit 60 saniyelik aralık yerine on-demand ISR: envanter webhook'larından yeniden doğrulama tetikle, stok düşüşleri sayfaları anında yeniden yazsın, normal gezinti CDN'de kalsın.
- 04İşlem modunda PgBouncer, yüzlerce serverless çağrısını küçük bir sabit PostgreSQL bağlantı havuzu üzerinden çokluyor; zirvede bağlantı tükenme hatalarını kaldırıyor.
- 05Asenkron ödeme onayı: Stripe PaymentIntent oluştur, hemen yönlendir, webhook'u arka planda işle. Sipariş-onaylandı deneyimi dört-beş saniye yerine iki saniye altına iniyor.
Sıkça Sorulan Sorular
Black Friday ölçeğinde bir Next.js e-ticaret sitesini genelde hangi darboğaz kırıyor?
Neredeyse her zaman ürün sayfaları değil, sepet ve ödeme yolu. Ürün listeleri tipik olarak statik üretiliyor ve CDN'den sunuluyor. Sepet, gerçek zamanlı fiyat, indirim ve kargo hesapları yapıyor ve yük altında ilk o kapasiteyi tüketiyor.
PostgreSQL'im varsa gerçekten Redis'e ihtiyacım var mı?
Yüksek eşzamanlılıkta evet. Her sepet hesaplamasının fiyat ve stok bilgisini doğrudan PostgreSQL'den çekmesi, ucuza ölçeklenemeyen tek bir sıcak yol yaratıyor. Önünde 30 saniyelik Redis cache, kataloğu genelde belleğe sığdırıyor ve okumaların çoğunu milisaniye altı isabete çeviriyor.
Stok hızlı değişirken ISR sayfalarını nasıl doğru tutarım?
Kısa sabit aralık yerine envanter webhook'larıyla tetiklenen on-demand revalidation kullan. Stok bir eşiğin altına düştüğünde sadece o ürünü yeniden doğrulayan bir webhook tetikleniyor. Geri kalan her şey daha uzun ISR planında kalıyor, CDN cache isabet oranı yüksek kalıyor.
Zirvede PostgreSQL'de 'too many connections' hatasını genelde ne yaratır?
Her çağrıda doğrudan bağlantı açan serverless fonksiyonlar. 100 bağlantı limiti hızla doluyor. İşlem modunda PgBouncer, yüzlerce çağıranı küçük bir havuz üzerinden çokluyor ve hatayı kaldırıyor; maliyeti, e-ticaretin neredeyse hiç kullanmadığı prepared statement cache gibi birkaç Postgres özelliğini desteklememesi.
Projeniz için konuşalım
15 dakika, taahhut yok.