Beklenmedik Egress Ücretleri: Bandwidth Faturaları Nereden Gelir?
Beklenmedik egress ücretlerinin temelinde genellikle dört alışkanlık yatar: medyayı uygulamadan sunmak, cache header kullanmamak, gereğinden fazla konuşkan API'ler ve region'lar arası trafik. Kaynağı bulun ve provider değiştirmeden faturayı düşürün.
Fatura gelir ve beklediğiniz tutarın dört katıdır. Compute kalemi bütçenize aşağı yukarı uygundur. Uymayan kalem egress'tir — altyapınızdan çıkan byte'lar — ve daha önce bunu hiç düşünmemiş olma ihtimaliniz oldukça yüksektir.
Beklenmedik egress ücretleri, uygulama hosting'inde en yaygın faturalandırma sürprizidir. Bunun nedeni yapısaldır: geliştirme döngünüzde hiçbir şey byte'ları ölçmez. Laptop'unuz bunlar için sizden ücret almaz. Staging ortamında kullanıcı yoktur. Bandwidth'ün görünür hâle geldiği ilk an faturadır; o noktaya gelindiğinde de buna neden olan alışkanlığı çoktan production'a taşımış olursunuz.
İşte kaynağı, cevabın en sık karşılaşılan nedenlerinden başlayarak sıralı biçimde.
1. Medyayı uygulamadan sunmak
Bu neden diğerlerini açık ara geride bırakır ve neredeyse her zaman yanlışlıkla ortaya çıkar.
Bir şeyi demo etmek için /public içine video koyarsınız. Çalışır ve orada kalır. Artık her sayfa görüntülemesi bu dosyayı container'ınızdan dışarıya stream eder. Ayda bin ziyaretçisi olan bir sayfadaki 40 MB'lık tek bir video, placeholder olarak gördüğünüz bir dosya yüzünden 40 GB trafik demektir.
Aynı durum product image'ları, PDF'ler, user upload'ları ve font dosyaları için de geçerlidir. Bunları eklerken hiçbiri bir infrastructure kararı gibi görünmez.
Çözüm karmaşık değildir: static media, uygulamanızın filesystem'ında değil, CDN arkasındaki object storage üzerinde bulunmalıdır. Uygulamanız HTML ve JSON sunmalıdır. Her ziyaretçiye 4 MB'lık hero image sunmaya başladığı anda, CDN'in işini CDN'in ekonomik avantajlarından hiçbiri olmadan yapıyor demektir.
2. Cache header kullanmamak
Response'larınızda cache header yoksa her ziyaretçi, her sayfa yüklemesinde her asset'i indirir. Tekrar gelen ziyaretçiler bunların tamamını yeniden indirir. Bir crawler ise bunları günde onlarca kez indirir.
# Fingerprinted build assets never change — cache them for a year
Cache-Control: public, max-age=31536000, immutable
# HTML changes — revalidate but allow a short window
Cache-Control: public, max-age=0, must-revalidate
# Anything user-specific
Cache-Control: private, no-store
Bu, her response class için tek satırlık bir değişikliktir ve ortadan kaldırdığı trafik tamamen tekrardan ibaret olduğu için bandwidth faturasının büyük bölümünü düzenli olarak yok eder.
3. Client'ın kullandığından fazlasını döndüren API'ler
UI üç alanı render ederken full object döndüren bir list endpoint'i, her request'te aradaki farkı sonsuza kadar gönderir. Profiling'de hiç görünmez, çünkü hızlıdır — yalnızca büyüktür.
En yoğun kullandığınız endpoint'lerde şu iki noktayı kontrol edin:
- Compression açık mı? JSON üzerinde
Content-Encoding: gzipveyabrkullanmak genellikle boyutu %70–80 oranında düşürür. Bu bir middleware satırıdır ve sıklıkla eksiktir. - Kimsenin okumadığı field'ları gönderiyor musunuz? ORM bunu kolaylaştırdığı için tüm row'u serialize etmek, çoğu codebase'in varsayılan davranışıdır.
Polling yapan bir client, polling'i dakikada kaç kez gerçekleştiriyorsa her iki sorunu da o katsayı kadar büyütür.
4. Region'lar ve service'ler arası trafik
Uygulamanız bir region'da, database'iniz başka bir region'daysa her query sonucu ücretli bir sınırdan geçer. Bunu yanlışlıkla yapmak kolaydır: önce database'i oluşturur, fazla düşünmeden bir region seçer, haftalar sonra uygulamayı başka bir yere yerleştirirsiniz.
Kendi service'leriniz arasındaki trafik de private network'ten çıkıp public hostname üzerinden geri dönüyorsa egress sayılabilir. Aynı workspace içindeki iki service'in public URL'leri üzerinden iletişim kurması, hiç dışarı çıkması gerekmeyen bir konuşma için iki kez ödeme yaptığınız anlamına gelir.
Dockup'ta bu özel hatayı yapmak zordur, çünkü service'ler birbirlerine internal name üzerinden ulaşır. Bir service main-db.internal:5432 adresine, başka bir service ise <slug>.internal alias'ına erişir; workspace network'ü içinde kalan trafik hiçbir zaman public listener'a ulaşmaz. Database'in varsayılan olarak public hostname'a sahip olmamasının nedeni de budur: trafiği yanlışlıkla oradan yönlendirebileceğiniz bir yol yoktur.
Tahmin etmek yerine kaynağı bulmak
Dört nedenden hangisi olduğunu tahmin etmek bir faturalandırma döngüsünü boşa harcar. Bunun yerine ölçüm yapın:
Access log'u request sayısına göre değil, byte sayısına göre okuyun. En çok response döndüren endpoint'leri request sayısına göre değil, sunulan toplam byte'a göre sıralayın. En fazla veri gönderen endpoint, en sık çağrılan endpoint olma eğiliminde değildir.
En büyük static asset'lerinizi kontrol edin. Bir megabyte'tan büyük herhangi bir şey uygulamanızdan sunuluyorsa, taşınması gereken ilk şey odur.
# What is the service actually doing right now
dockup metrics my-project/my-api --json
# And what is it logging
dockup logs my-project/my-api -n 1000
Crawler'lara dikkat edin. Büyük dosyaları tekrar tekrar çeken sorunlu bir bot, insan trafiği sınırlı bir sitede aylık egress'in çoğundan sorumlu olabilir. robots.txt ve preview environment'larında noindex kullanmak düşük maliyetli çözümlerdir.
Kimsenin hesaba katmadığı environment'lar
İki alışkanlık, kimsenin zihinsel modelinde yer almayan egress üretir:
Preview environment'ları. Her pull request için bir preview oluşturmak gerçekten faydalıdır ve footprint'inizi sessizce katlar. Beş açık PR, her biri kendi trafiğine sahip stack'inizin beş kopyası demektir. Üstelik preview URL'lerini engellemediğiniz sürece çoğu zaman aynı crawler'lar tarafından taranırlar.
Uzun süre çalışan staging. Sekiz aydır çalışan, kimsenin ziyaret etmediği bir staging hâlâ image'ları çeker, hâlâ taranır ve hâlâ cron job'larını çalıştırır.
Bunların hiçbiri bu environment'ları kullanmayı bırakmanız için bir neden değildir. İkisini de sınırlandırmanız için birer nedendir: PR kapandığında preview'ları expire edin ve search engine'lerin sizin adınıza bunları indirmeyi bırakması için noindex olarak işaretleyin.
dockup noindex my-project/my-api --on
İyi bir faturalandırma nasıl görünür?
Fatura gelmeden önce şu üç soruyu yanıtlayabilmelisiniz:
- Şu anda neler çalışıyor? Unuttuğunuz şeyler de dahil.
- Her biri ne tüketti? Tek bir sayı yerine compute ve transfer olarak ayrıştırılmış biçimde.
- Tüketim artarsa ne olur? Service'leri durduran bir limit can sıkıcıdır. Hiç limit olmaması ise daha kötüdür.
Dockup, infrastructure kullanımını plan'den ayrı olarak ölçer. Böylece plan ücreti kullanımı gizlemez; ayrıca Pro plan'ın $20 kredisi de ücrette indirim olarak değil, bu kullanımın karşılığında uygulanır. Önemli olan, hangi kısmın ne olduğunu görebilmenizdir.
Kısa özet
Medyayı object storage'a taşıyın. Cache header'ları ayarlayın. Compression'ı açın. Service'leri ve database'lerini aynı region'da tutun; public internet yerine private network üzerinden iletişim kurmalarını sağlayın. Preview environment'larını expire edin ve search result'larında görünmelerini engelleyin.
Bu beş alışkanlık, neredeyse tüm beklenmedik bandwidth faturalarını önler ve hosting yaptığınız yeri değiştirmenizi gerektirmez.
Sık sorulan sorular
Egress nedir? Altyapınızdan internet'e doğru çıkan veridir. Kullanıcılara gönderilen response'lar, indirilen dosyalar ve API payload'ları buna dahildir. Inbound trafik genellikle ücretsizdir; outbound trafik ise genellikle ücretsiz değildir.
Egress faturam neden compute faturamdan yüksek? Neredeyse her zaman nedeni, uygulamanın CDN üzerinde bulunması gereken dosyaları sunmasıdır. Popüler bir sayfadaki tek bir büyük asset, haftalarca süren request işlemlerinden daha fazla maliyet oluşturabilir.
CDN gerçekten maliyeti azaltır mı? Cache kullandığında evet. Origin dosyayı her ziyaretçi için bir kez sunmak yerine her edge için bir kez sunar ve CDN'in gigabyte başına fiyatı genellikle bir application platform'unun fiyatının küçük bir bölümüdür.
Preview environment'ları production kadar maliyetli midir? Tükettikleri kadar maliyet oluştururlar. Bu tutar genellikle beklenenden yüksektir, çünkü her biri stack'in tam bir kopyasıdır ve engellemediğiniz sürece preview URL'leri crawler'lar tarafından taranır.
