JournalindexDockup / fältanteckning
Note / unexpected-egress-charges

Oväntade egresskostnader: Var bandbreddsräkningen kommer ifrån

Oväntade egresskostnader beror oftast på fyra vanor: att servera media från appen, saknade cache headers, pratiga API:er och trafik mellan regioner. Hitta källan och sänk kostnaden utan att byta leverantör.

Räkningen kommer och är fyra gånger högre än du hade väntat dig. Compute-raden ligger ungefär där du budgeterade. Det som inte gör det är egress – byten som lämnar din infrastruktur – och det finns en god chans att du aldrig har tänkt på det en enda gång.

Oväntade egresskostnader är den vanligaste fakturaöverraskningen när man hostar applikationer, och orsaken är strukturell: inget i ditt utvecklingsflöde mäter bytes. Din laptop tar inte betalt för dem. Staging har inga användare. Första gången bandbredd blir synlig är på en faktura, och då har du redan lanserat vanan som orsakade den.

Här är var kostnaderna faktiskt kommer ifrån, i ordning efter hur ofta det är svaret.

1. Att servera media från applikationen

Det här överträffar de andra orsakerna med råge och är nästan alltid oavsiktligt.

Du lägger en video i /public för att demonstrera något. Det fungerar, så den blir kvar. Nu strömmas filen ut från din container vid varje sidvisning. En video på 40 MB på en sida med tusen besökare i månaden blir 40 GB – från en fil du såg som en platshållare.

Samma mönster gäller produktbilder, PDF-filer, användaruppladdningar och fontfiler. Inget av detta känns som infrastrukturval när du lägger till det.

Lösningen är inte särskilt avancerad: statisk media hör hemma i object storage bakom en CDN, inte i applikationens filsystem. Din app bör servera HTML och JSON. Så fort den serverar en hero-bild på 4 MB till varje besökare gör den en CDN:s jobb, utan någon av de ekonomiska fördelarna.

2. Inga cache headers

Om dina svar saknar cache headers laddar varje besökare ner varje asset vid varje sidladdning. Återkommande besökare laddar ner allt igen. En crawler laddar ner det dussintals gånger om dagen.

# 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

Det här är en ändring på en rad per svarsklass som regelbundet tar bort merparten av en bandbreddsräkning, eftersom trafiken som försvinner bara är ren upprepning.

3. API:er som returnerar mer än klienten använder

Ett list-endpoint som returnerar kompletta objekt när gränssnittet visar tre fält skickar mellanskillnaden vid varje anrop, för alltid. Det syns aldrig i profileringen eftersom det går snabbt – det är bara stort.

Kontrollera två saker i dina mest använda endpoints:

  • Är komprimering aktiverad? Content-Encoding: gzip eller br för JSON minskar vanligtvis storleken med 70–80 %. Det är en rad middleware och saknas ofta.
  • Skickar du fält som ingen läser? Att serialisera hela raden eftersom ORM:et gör det enkelt är standardbeteendet i de flesta kodbaser.

En klient som pollar gör båda problemen värre, med en faktor som motsvarar hur många gånger per minut den pollar.

4. Trafik mellan regioner och tjänster

Om din app finns i en region och databasen i en annan passerar varje frågeresultat en avgiftsbelagd gräns. Det är lätt att göra av misstag – du skapar databasen först, väljer region utan att tänka på det och placerar appen någon annanstans flera veckor senare.

Trafik mellan dina egna tjänster kan också räknas som egress om den lämnar det privata nätverket och kommer tillbaka via ett publikt hostname. Två tjänster i samma workspace som kommunicerar via sina publika URL:er betalar alltså två gånger för ett samtal som aldrig behövde lämna nätverket.

På Dockup är just det här misstaget svårt att göra, eftersom tjänster adresserar varandra med interna namn. En tjänst når main-db.internal:5432 och en annan tjänst via dess <slug>.internal-alias – trafik som stannar i workspace-nätverket når aldrig en publik listener. Det är också därför databasen inte har något publikt hostname som standard: det finns inget som av misstag kan routas genom det.

Hitta källan i stället för att gissa

Att gissa vilken av de fyra orsakerna det är slösar bort en faktureringsperiod. Mät i stället:

Läs accessloggen efter bytes, inte antal anrop. Sortera dina vanligaste svar efter totalt antal serverade bytes i stället för antal anrop. Endpointen som skickar mest data är sällan den som anropas oftast.

Kontrollera dina största statiska assets. Om något större än en megabyte serveras från din app är det det första du bör flytta.

# 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

Håll utkik efter crawlers. En felkonfigurerad bot som hämtar stora filer upprepade gånger kan stå för merparten av en månads egress på en webbplats med måttlig mänsklig trafik. robots.txt och en noindex på preview-miljöer är billiga åtgärder.

Miljöerna som ingen räknar med

Två vanor genererar egress som aldrig finns med i någons mentala modell:

Preview-miljöer. En preview per pull request är verkligen användbar och multiplicerar samtidigt obemärkt ditt footprint. Fem öppna PR:er innebär fem kopior av din stack, var och en med sin egen trafik – ofta från samma crawlers, eftersom preview-URL:er indexeras om du inte stoppar dem.

Långlivad staging. Staging som har körts i åtta månader och som ingen besöker hämtar fortfarande images, crawlas fortfarande och kör fortfarande sina cron-jobb.

Inget av detta är ett skäl att sluta använda miljöerna. Båda är däremot skäl att begränsa dem: ta bort previews när PR:en stängs och markera dem med noindex så att sökmotorer slutar ladda ner dem åt dig.

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

Så ser bra fakturering ut

Du bör kunna svara på tre frågor innan fakturan kommer:

  1. Vad körs just nu? Även sådant du har glömt bort.
  2. Vad förbrukade varje del? Uppdelat i compute och dataöverföring, inte som en enda siffra.
  3. Vad händer om förbrukningen ökar kraftigt? En gräns som stoppar tjänster är obehaglig. En gräns som inte finns är värre.

Dockup mäter infrastruktur separat från abonnemanget, så abonnemangsavgiften döljer inte användningen – och Pro-planens kredit på 20 dollar dras från användningen i stället för att vara en rabatt på avgiften. Poängen är att du kan se vad som hör till vilken del.

Kortversionen

Flytta media till object storage. Ange cache headers. Aktivera komprimering. Håll tjänster och deras databaser i samma region och låt dem kommunicera via det privata nätverket i stället för det publika internet. Ta bort preview-miljöer när de inte längre behövs och håll dem borta från sökresultaten.

De här fem vanorna hanterar nästan alla oväntade bandbreddsräkningar, och ingen av dem kräver att du ändrar var du hostar.

Vanliga frågor

Vad är egress? Data som lämnar din infrastruktur på väg mot internet. Svar till användare, filer som laddas ner och API-payloads. Inkommande trafik är vanligtvis gratis; utgående trafik är det oftast inte.

Varför är min egressräkning högre än min compute-räkning? Nästan alltid för att applikationen serverar filer som hör hemma på en CDN. En enda stor asset på en populär sida kostar mer än veckor av request-hantering.

Minskar en CDN verkligen kostnaden? Ja, när den cachar. Origin serverar filen en gång per edge i stället för en gång per besökare, och CDN:ens pris per gigabyte är vanligtvis en bråkdel av priset hos en applikationsplattform.

Kostar preview-miljöer lika mycket som produktion? De kostar utifrån vad de förbrukar, vilket ofta är mer än väntat eftersom varje miljö är en fullständig kopia och preview-URL:er crawlas om du inte förhindrar det.