Her iki senede bir aynı Twitter kavgası patlıyor: “JWT kullanmayın” vs “session stateful, scale etmez”. İkisi de eksik. Gerçek durum: kullanım senaryonuz ne diyor?
Onlarca backend projesinde her iki modeli de kurguladım. Bu yazı tartışmayı bitirmek için değil, sizin özel durumunuzda doğru kararı vermenizi sağlamak için.
Session nedir, ne değildir?
Sunucuda bir session store (Redis, memcached, DB) tutuyorsun. Kullanıcı login olduğunda random bir session ID üretiyorsun, client’ın cookie’sine koyuyorsun. Her request’te client bu cookie’yi gönderiyor, backend session ID’yi store’da arıyor, user’ı buluyor.
Avantajları:
- Revoke etmek trivial: session store’dan silersin, kullanıcı anında dışarı
- Payload küçük: cookie sadece bir ID
- User bilgilerini değiştirmek kolay: session store’da günceller, sonraki request’te yeni bilgi
Dezavantajları:
- Session store her request’te lookup, latency ve load
- Dağıtık sistemlerde session sticky routing ya da shared store gerekli
- Cross-domain zor (cookie limitations)
JWT nedir, ne değildir?
Client login olduğunda backend bir token üretiyor. Token içinde user bilgileri var (id, role, expiry). Token cryptographic olarak imzalı, backend değiştirilip değiştirilmediğini anlayabiliyor. Client her request’te bu token’ı gönderiyor (genelde Authorization: Bearer header’ı).
Avantajları:
- Stateless: backend hiçbir şey tutmuyor, sadece signature doğruluyor
- Dağıtık sisteme doğal uyum: hangi server’a gitsen doğrular
- Cross-domain, cross-service kolay
- Token içinde bilgi olduğu için DB lookup’a gerek yok
Dezavantajları:
- Revoke etmek zor: token zaten “geçerli”
- Token büyük (500 byte – 2KB), her request’te bandwidth
- Kullanıcı bilgileri değiştiğinde token güncellenmiyor (expire olana kadar eski bilgi)
- Token leak olursa expire olana kadar yapacak bir şey yok
Karar ağacı
Sorum sizin özel durumunuzla ilgili:
Soru 1: Anında revoke gerekiyor mu?
Banking, medical, payroll, hassas sistemler. Kullanıcı hesabından çıkıldığında, kompromize olduğu tespit edildiğinde ilgili session HEMEN geçersiz olmalı.
- Evet gerekiyorsa → Session kullan. JWT ile bunu yapmak için blacklist store’u tutman gerekiyor, ki o zaman stateless avantajı yok oluyor.
- “15 dakika gecikme tolere edilebilir” → JWT olabilir (kısa expiry + refresh token).
Soru 2: Çoklu servisin var mı?
3+ backend servisin varsa ve hepsi aynı user’ı authentication ediyor:
- Monolit → Session muhtemelen yeter
- Microservices → JWT ile her servis bağımsız doğrular
- Hybrid (API gateway önde) → Gateway JWT doğrular, içeride session-like bir state, ama JWT dışa hala kullanışlı
Soru 3: Mobile uygulama/native client var mı?
Cookie-based session native mobile’da awkward. HTTP client’lar cookie yönetimini hep iyi yapmıyor. Token-based auth native’de daha rahat.
- Sadece web → Session daha basit
- Mobile + web → JWT daha universal
Soru 4: Kullanıcı bilgileri ne sıklıkta değişiyor?
Kullanıcı kendine premium almış olsun:
- Session ile: bir sonraki request’te premium feature açılıyor (session’da update)
- JWT ile: yeni JWT almadan eski JWT geçerli, kullanıcı deneyimi “niye premium açılmadı” sorusu
“Çok sık değişmiyor” → JWT tolere edilebilir
“Permission değişiklikleri instant görünmeli” → Session
Hybrid approach: her ikisinin de iyisi
Gerçekçi production deployment’larda benim en sık kullandığım pattern:
- Access token (JWT): kısa ömür (15 dakika), stateless, her API request’te bu
- Refresh token (opaque, DB’de): uzun ömür (30 gün), sadece yeni access token almak için
Flow:
- Login → Access token + Refresh token dönüyor
- Her API request’te access token
- Access token expire olduğunda client refresh token’la yeni access token alıyor
- Refresh token revoke edilebilir (DB’den silinir)
- Hassas operasyon (şifre değiştir, ödeme) için re-authentication isteniyor
Bu pattern JWT’nin statelessness avantajını alıyor, session’ın revoke edebilmesini de koruyor. Stripe, GitHub, Google, hepsi benzer yaklaşım.
JWT hakkında yaygın yanlışlar
1. JWT encryption değil, sadece imza
JWT içeriği (payload) base64 encoded, encrypt edilmiyor. Token içeriğini herhangi biri okuyabilir. Hassas veri (kredi kartı, şifre) ASLA JWT içine koymayın. Sadece user_id, role, expiry gibi bilgiler.
Eğer gerçekten encrypt lazımsa JWE (JSON Web Encryption) kullanın, ama neredeyse hiçbir zaman gerekli değil.
2. “JWT scalable” efsanesi
JWT kullandın diye scalable değilsin. Session store’unuz Redis ise zaten scalable. “Stateless daha scalable” argümanı ölçek 100+ server’a kadar teorik bir fark.
3. localStorage’da JWT tutmak
XSS vulnerable. Browser’daki JavaScript JWT’yi çalabilir. HTTP-only cookie’de tutun (XSS koruma). Bu durumda session ile JWT arasındaki fark daha da azalıyor, cookie-based JWT esasen session-like davranıyor.
Sonuç
Doğru cevap “duruma göre”. Ama duruma göre demek yetmiyor, hangi soruları sormak gerektiğini bilmek gerekiyor:
- Revoke hızı ne kadar kritik?
- Sistemin dağıtık yapısı ne?
- Client tipleri (web, mobile, 3rd party) neler?
- User bilgileri ne sıklıkta değişiyor?
Bu 4 soruya cevap verdikten sonra hangi modelin sizin için doğru olduğu net hale geliyor.
Benim tercihim? Çoğu web SaaS için session cookie. Mobile + web + 3rd party entegrasyon varsa JWT + refresh token pattern. Microservices için JWT zorunlu. Hybrid her yerde çalışır.
Önemli olan karar verirken prensipten değil, pratiğinden bakmak.