Indeks dnevnikaDockup / bilješka s terena
Note / unexpected-egress-charges

Neočekivani troškovi egresa: Odakle dolaze računi za bandwidth

Neočekivani troškovi egresa obično proizlaze iz četiri navike: posluživanje medija iz aplikacije, izostanak cache headera, previše komunikativni API-ji i promet između regija. Pronađite izvor i smanjite račun bez promjene providera.

Račun stiže i četiri je puta veći nego što ste očekivali. Stavka za compute približno odgovara onome što ste predvidjeli. Stavka koja ne odgovara jest egress — bajtovi koji napuštaju vašu infrastrukturu — a postoji velika šansa da o tome dosad niste ni jednom razmišljali.

Neočekivani troškovi egresa najčešće su iznenađenje na računu kod hostanja aplikacija, a razlog je strukturalan: ništa u vašem development loopu ne mjeri bajtove. Laptop vam ih ne naplaćuje. Staging nema korisnike. Bandwidth prvi put postaje vidljiv na računu, a do tada ste već isporučili naviku koja ga je uzrokovala.

Evo odakle on zapravo dolazi, redoslijedom kojim se najčešće pokaže da je upravo to uzrok.

1. Posluživanje medija iz aplikacije

Ovaj je uzrok daleko najveći od ostalih i gotovo je uvijek slučajan.

Dodate video u /public kako biste nešto demonstrirali. Radi, pa ostane tamo. Svaki pregled stranice sada šalje tu datoteku iz vašeg containera. Jedan video od 40 MB na stranici koju mjesečno posjeti tisuću korisnika znači 40 GB — za datoteku koju ste smatrali privremenim placeholderom.

Isti se obrazac odnosi na slike proizvoda, PDF-ove, korisničke uploade i fontove. Kad ih dodajete, nijedan od njih ne djeluje kao infrastrukturna odluka.

Rješenje nije posebno domišljato: statički mediji pripadaju na object storage iza CDN-a, a ne u filesystem vaše aplikacije. Aplikacija bi trebala posluživati HTML i JSON. U trenutku kad svakom posjetitelju poslužuje hero sliku od 4 MB, radi posao CDN-a, ali bez ijedne njegove ekonomske prednosti.

2. Nema cache headera

Ako vaši responseovi nemaju cache headere, svaki posjetitelj preuzima svaki asset pri svakom učitavanju stranice. Posjetitelji koji se vraćaju ponovno preuzimaju sve. Crawler ga preuzme desecima puta dnevno.

# 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

To je promjena od jednog retka po klasi responsea koja redovito uklanja većinu računa za bandwidth jer je promet koji se time eliminira čisto ponavljanje.

3. API-ji koji vraćaju više nego što klijent koristi

Endpoint za listu koji vraća cijele objekte, iako UI prikazuje tri polja, šalje razliku pri svakom requestu, zauvijek. To se nikad ne vidi u profilingu jer je brzo — samo je veliko.

Na najopterećenijim endpointima provjerite dvije stvari:

  • Je li compression uključen? Content-Encoding: gzip ili br za JSON obično smanjuje veličinu za 70–80 %. To je jedan redak u middlewareu i često nedostaje.
  • Šaljete li polja koja nitko ne čita? Serijaliziranje cijelog retka zato što je ORM to učinio jednostavnim zadano je ponašanje većine codebaseova.

Polling client pogoršava oba problema za onoliko puta koliko u minuti radi polling.

4. Promet između regija i servisa

Ako je vaša aplikacija u jednoj regiji, a baza podataka u drugoj, svaki rezultat queryja prelazi granicu koja se naplaćuje. To se lako dogodi slučajno — prvo kreirate bazu podataka, odaberete regiju bez puno razmišljanja, a aplikaciju nekoliko tjedana kasnije smjestite negdje drugdje.

Promet između vlastitih servisa također može biti egress ako napusti privatnu mrežu i vrati se kroz javni hostname. Dva servisa u istom workspaceu koja međusobno komuniciraju preko svojih javnih URL-ova plaćaju dvaput za razgovor koji nikad nije trebao napustiti mrežu.

Na Dockupu je ovu konkretnu pogrešku teško napraviti, jer se servisi međusobno adresiraju internim imenom. Servis pristupa main-db.internal:5432, a drugom servisu preko njegova <slug>.internal aliasa — promet koji ostaje unutar mreže workspacea nikad ne dolazi do javnog listenera. Zato baza podataka prema zadanim postavkama nema javni hostname: nema ničega što bi se slučajno usmjerilo kroz javnu mrežu.

Pronađite izvor umjesto da nagađate

Nagađanje o tome koji je od ova četiri uzroka kriv potrošit će vam cijeli obračunski ciklus. Umjesto toga mjerite:

Čitajte access log prema broju bajtova, a ne prema broju requestova. Poredajte najčešće responseove prema ukupno posluženim bajtovima, a ne prema broju requestova. Endpoint koji šalje najviše podataka rijetko je onaj koji se najčešće poziva.

Provjerite najveće statičke assete. Ako se iz aplikacije poslužuje bilo što veće od megabajta, to je prvo što trebate premjestiti.

# 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

Pazite na crawlere. Bot koji se loše ponaša i opetovano preuzima velike datoteke može činiti većinu mjesečnog egresa na stranici s umjerenim prometom stvarnih korisnika. robots.txt i noindex na preview okruženjima jeftine su mjere.

Okruženja koja nitko ne uračunava

Dvije navike stvaraju egress koji se nikad ne pojavljuje u ničijem mentalnom modelu:

Preview okruženja. Preview za svaki pull request doista je koristan, ali neprimjetno umnožava vaš footprint. Pet otvorenih PR-ova znači pet kopija vašeg stacka, svaka s vlastitim prometom — često od istih crawlera jer se preview URL-ovi indeksiraju ako ih ne zaustavite.

Dugotrajni staging. Staging koji radi osam mjeseci, a nitko ga ne posjećuje, i dalje povlači imageove, i dalje ga crawlaju botovi i i dalje izvršava svoje cron jobove.

Nijedno od toga nije razlog da ih prestanete koristiti. Oboje je razlog da im postavite ograničenja: expajrajte preview okruženja kad se PR zatvori i označite ih s noindex kako ih tražilice ne bi preuzimale u vaše ime.

dockup noindex my-project/my-api --on

Kako izgleda dobra naplata

Prije nego što račun stigne, trebali biste moći odgovoriti na tri pitanja:

  1. Što je trenutno pokrenuto? Uključujući i ono što ste zaboravili.
  2. Koliko je svaka stavka potrošila? Razdvojeno na compute i transfer, a ne prikazano kao jedan broj.
  3. Što se događa ako potrošnja naglo poraste? Limit koji zaustavlja servise nije ugodan. Limit koji ne postoji još je gori.

Dockup infrastrukturu mjeri odvojeno od plana, pa naknada za plan ne skriva potrošnju — a kredit od 20 USD na Pro planu primjenjuje se na tu potrošnju, umjesto da bude popust na naknadu. Poanta je u tome da možete vidjeti koji se dio na što odnosi.

Ukratko

Premjestite medije na object storage. Postavite cache headere. Uključite compression. Servise i njihove baze podataka držite u istoj regiji i omogućite im komunikaciju preko privatne mreže umjesto javnog interneta. Expajrajte preview okruženja i uklonite ih iz rezultata pretraživanja.

Tih pet navika rješava gotovo svaki iznenađujući račun za bandwidth, a nijedna od njih ne zahtijeva promjenu mjesta hostanja.

Često postavljana pitanja

Što je egress? Podaci koji napuštaju vašu infrastrukturu prema internetu. Responseovi korisnicima, preuzete datoteke, API payloadi. Dolazni promet obično je besplatan, a odlazni se obično naplaćuje.

Zašto je moj račun za egress veći od računa za compute? Gotovo uvijek zato što aplikacija poslužuje datoteke koje pripadaju CDN-u. Jedan veliki asset na popularnoj stranici može premašiti tjedne obrade requestova.

Smanjuje li CDN doista troškove? Da, kada radi caching. Origin poslužuje datoteku jednom po edge lokaciji umjesto jednom po posjetitelju, a cijena CDN-a po gigabajtu obično je tek dio cijene application platforme.

Koštaju li preview okruženja jednako kao produkcija? Koštaju onoliko koliko potroše, što je često više nego što očekujete jer je svako od njih puna kopija, a preview URL-ove crawleri indeksiraju ako to spriječite.