...

HTTP-cache-headers: Sådan saboterer de din caching-strategi

HTTP-cache-headers bestemmer, hvordan browsere og proxyserver gemmer indhold i cachen – hvis de er indstillet forkert, bremser de indlæsningstiden og øger serverbelastningen mærkbart. I dette indlæg viser jeg, hvordan små fejl i headers kan påvirke din Caching-strategi sabotere, og hvordan du med få rettelser kan blive mærkbart hurtigere.

Centrale punkter

Følgende nøglebudskaber hjælper mig med hurtigt at kontrollere HTTP-headere og holde dem rene på lang sigt.

  • TTL Vælg rigtigt: Cache statiske aktiver meget længe, HTML kort og kontrolleret.
  • Validering Brug: ETag og Last-Modified reducerer unødvendige anmodninger.
  • Konflikter Undgå: Origin- og CDN-headere skal passe sammen.
  • Versionering Brug: Filhash'er muliggør aggressive cache-strategier.
  • Overvågning Etablere: Måle HIT-raten og øge den systematisk.

Hvad HTTP-cache-headers virkelig styrer

Cache-Control, Expires, ETag og Last-Modified bestemmer, om indholdet er nyt, hvor længe det er gyldigt, og hvornår browseren skal forespørge. Med max-alder definerer jeg levetiden, med public/private placeringen i browseren eller delte caches. Direktiver som ingen opbevaring forhindrer lagring fuldstændigt, no-cache tvinger en revalidering før brug. For statiske filer er et års gyldighed værd, HTML får korte tider med intelligent revalidering. Jeg bygger desuden på uforanderlig, hvis filer garanteret forbliver uændrede via hash-version.

Denne styring har direkte indflydelse på latenstid, båndbredde og serverbelastning. En øget HIT-rate forkorter ventetider og reducerer backend-arbejdet. Derudover optimerer jeg overførslen med HTTP-komprimering, så der skal transporteres færre bytes. Hvis man adskiller disse ting tydeligt, aflastes CDN'er, proxyservere og browser-caches i lige høj grad. Sådan sikrer jeg en problemfri Indlæsningstider igennem.

TTL-planlægning i praksis

Den passende TTL afhænger af ændringsfrekvens, risiko og tilbagefaldsstrategi. For aktiver med filhash sætter jeg 12 måneder, fordi jeg kontrollerer ændringer via nye filnavne. For HTML orienterer jeg mig efter indholdets dynamik: Start- eller kategorisider forbliver ofte aktuelle i 1–5 minutter, mens detaljesider med kommentarer er kortere. Det er vigtigt at have en Rollback-sti: Hvis der alligevel opstår en fejl live, har jeg brug for en hurtig purge (Edge) og en tvungen revalidering (must-revalidate) for browsere. API-responser får korte TTL'er, men med stale-Direktiver, så brugerne kan se svarene i tilfælde af fejl. Jeg dokumenterer disse profiler pr. rute eller filtype og forankrer dem i build-/deploy-pipeline, så ingen „stille“ ændringer utilsigtet underminerer friskhedspolitikken.

Hvordan fejlkonfigurationer saboterer strategien

For kort TTL'er som max-age=60 sekunder ved CSS, JS eller billeder tvinger konstante forespørgsler og ødelægger fordelene ved cachen. En global no-cache i CMS-opsætninger bremser selv, når store dele af en side faktisk er stabile. Mangler ETag eller Last-Modified, indlæser browseren filer helt forfra i stedet for at kontrollere dem på en smart måde. Overflødige query-strings skaber fragmentering Cache-nøgler og sænker HIT-raten betydeligt. Hvis Origin sender no-cache, ignorerer CDN kantcaches – hvilket resulterer i længere veje og højere serverbelastning.

Jeg kan se resultatet i målingerne: Flere anmodninger, højere CPU-tid og stigende svartider. Ved trafikspidser stiger risikoen for timeouts. Samtidig stiger båndbreddeforbruget, uden at brugerne mærker nogen fordel. Med et kig i DevTools kan jeg hurtigt genkende sådanne mønstre. Jeg begynder så med at justere Cache-kontrol, før jeg øger serverressourcerne.

Anbefalinger pr. indholdstype: de passende direktiver

Afhængigt af indholdstypen bruger jeg forskellige Overskrift, så caches fungerer optimalt, og brugerne kan se aktuelle data. Nedenstående tabel viser gennemprøvede profiler, som jeg bruger i projekter.

Indhold Anbefalet cache-kontrol Gyldighed Hint
JS/CSS/billeder (versioneret) offentlig, max-age=31536000, uforanderlig 12 måneder Brug filnavn med hash (f.eks. app.abc123.js)
Skriftfiler (woff2) offentlig, max-age=31536000, uforanderlig 12 måneder Vær opmærksom på CORS, hvis indlæst fra CDN
HTML (offentlig) public, max-age=300, stale-while-revalidate=86400 5 minutter Kort Friskhed, blød genindlæsning i baggrunden
HTML (personliggjort) privat, max-age=0, no-cache Revalidering Ingen videregivelse i delte cacher
API'er public, max-age=60–300, stale-if-error=86400 1–5 minutter Fejltilfælde med stale afbøde

Disse profiler dækker typiske websteder og hjælper med hurtigt at skabe konsistens. Regler Det er vigtigt at have en klar versionering for aktiver, så lange max-age-værdier ikke leverer forældede filer. HTML forbliver kortvarigt og opdateres via revalidering. API'er får korte tider og et sikkerhedsnet via stale-if-error. På den måde forbliver siderne også ved forstyrrelser. brugbar.

Cache fejlkoder og omdirigeringer korrekt

Videresendelser og fejlside fortjener deres egne regler. 301/308 (permanent) kan caches i CDN'er og browsere i meget lang tid; jeg angiver her ofte dage til uger for at undgå omdirigeringskæder. 302/307 (midlertidige) får korte TTL'er, ellers bliver midlertidige tilstande „frosset“. For 404/410 er det en god idé at have en moderat friskhed (f.eks. minutter til timer), så bots og brugere ikke konstant forespørger; ved hyppigt skiftende indhold holder jeg 404 ret kort. 5xx-Jeg cacher generelt ikke fejl, men bruger i stedet stale-if-error til midlertidigt at levere fungerende kopier. På den måde forbliver platformen stabil, og jeg reducerer rerendering-belastningen ved hyppigt anmodede, men manglende stier.

Korrekt brug af validering: ETag og Last-Modified

Med ETag og Last-Modified kontrollerer browseren, om en ressource virkelig skal indlæses igen. Klienten sender If-None-Match eller If-Modified-Since, og serveren svarer ideelt set med 304 i stedet for 200. På den måde sparer jeg overførsel og reducerer Trafik tydeligt. For statiske filer er Last-Modified ofte tilstrækkeligt, mens jeg bruger ETags til dynamisk genereret indhold. Vigtigt: Konsistent ETag-generering, så caches kan genkende hits.

Jeg kombinerer gerne validering med stale-Direktiver. stale-while-revalidate holder siderne hurtige, mens de opdateres i baggrunden. stale-if-error sikrer pålidelighed i tilfælde af backend-problemer. Således forbliver brugeroplevelsen stabil, og serverne skånes. Følgende uddrag viser typiske indstillinger, som jeg bruger.

Header set Cache-Control "public, max-age=31536000, immutable"
 /etc/nginx/conf.d/caching.conf location ~* .(css|js|png|jpg|svg|woff2)$ { add_header Cache-Control "public, max-age=31536000, immutable"; }

Avancerede direktiver og detaljer

Ud over max-age bruger jeg målrettet s-maxage, for at fylde Edge-caches længere end browsere. Således kan CDN f.eks. holde i 1 time, mens klienter genvaliderer efter 5 minutter. skal-revalidere tvinger browsere til at kontrollere udløbne kopier før brug – vigtigt i sikkerhedsrelevante områder. proxy-revalidate retter pligten mod delte cacher. Med ingen transformation forhindrer jeg proxyservere i at ændre billeder eller komprimering uden forespørgsel. For at sikre bred kompatibilitet sender jeg ud over Cache-Control valgfrit en Udløber-Dato i fremtiden (Assets) eller fortiden (HTML), selvom moderne cacher primært overholder Cache-Control. Ved CDN-strategier adskiller jeg browser- og edge-regler: public + max-age for klienter, plus s-maxage/Surrogate-Control for kanten. Denne opdeling maksimerer HIT-rater uden risiko for forældelse på slutapparater.

Samspil med CDN og edge-caches

Et CDN respekterer Origin-header – Forkerte direktiver ved oprindelsen deaktiverer globale caches. For delte caches indstiller jeg public og om nødvendigt s-maxage, så kanter holder længere end browsere. Surrogate-Control kan desuden levere regler for Edge-caches. Hvis no-cache rammer oprindelsen, afviser CDN den ønskede Opbevaring. Derfor koordinerer jeg bevidst browser- og CDN-strategien.

Ved nye projekter undersøger jeg desuden forudindlæsningsstrategier. Med HTTP/3 Push & Preload Jeg indlæser kritiske aktiver tidligt og reducerer renderingsblokeringer. Denne teknik erstatter ikke caching, men supplerer den. Sammen med lange TTL'er for aktiver forbedres startydelsen mærkbart. Sådan arbejder jeg på netværksrangeringen, før Server overhovedet kommer til at svede.

Vary-strategien i detaljer

Varierer bestemmer, hvilke forespørgselsheadere der genererer nye varianter. Jeg holder Vary minimalt: For HTML er det oftest Accept-Encoding (komprimering) og eventuelt sprog; for aktiver helst slet ikke. Et for bredt Vary (f.eks. User-Agent) ødelægger HIT-raten. Samtidig skal ETags som repræsentationsspecifik Reflektere variant: Hvis jeg leverer gzip eller br, gælder ETags pr. kodningsvariant, og jeg indstiller Vary: Accept-Encoding. Hvis jeg bruger svage ETags (W/), sørger jeg for at generere dem konsekvent, ellers opstår der unødvendige 200'ere. Fonts eller billeder skal som regel klare sig uden Vary, så nøglerne forbliver stabile. Mit princip: Først definere, hvilke varianter der er fagligt nødvendige – først derefter udvide Vary, aldrig omvendt.

Overvågning og diagnose i DevTools

Jeg starter altid i Netværksfane browser-værktøjerne. Der kan jeg se, om svarene kommer fra cachen, hvor gamle de er, og hvilke direktiver der gælder. Kolonnerne Age, Cache-Control og Status hjælper med hurtige kontroller. En HIT-rate under 50% viser, at der er behov for handling, og målværdier på 80% og mere er realistiske. Ved afvigelser tjekker jeg først de tilhørende headers.

Værktøjer som PageSpeed eller GTmetrix bekræftede mine lokale Målinger. Jeg sammenligner derefter før/efter ændringer for at kvantificere fordelene. Hvis der tilføjes store overførselsmængder, aktiverer jeg konsekvent moderne komprimering. På den måde sparer jeg yderligere millisekunder. Således dokumenterer jeg hver eneste tuning med hårde Tal.

Automatiserede kontroller og CI

For at reglerne ikke bliver udvandet, integrerer jeg header-kontroller i CI. Jeg definerer målprofiler for hver sti og lader hver build kontrollere tilfældigt mod staging. Enkle shell-kontroller er ofte tilstrækkelige:

# Eksempel: Forventede direktiver for versionerede aktiver curl -sI https://example.org/static/app.abc123.js | grep -i "cache-control" # Forventet kortvarighed og revalidering for HTML
curl -sI https://example.org/ | egrep -i "cache-control|etag|last-modified" # Inspicere Age-header og cache-status (hvis tilgængelig) curl -sI https://example.org/styles.css | egrep -i "age|cache-status|x-cache"

I kombination med syntetiske tests planlægger jeg regelmæssige „header-audits“. Resultaterne føres tilbage til infrastrukturkoden. Således forbliver Politikker stabil – uanset hvem der sidst har ændret CMS, CDN eller serverkonfigurationen.

Hostingoptimering: Caching af sider, objekter og opkoder

Ud over browser- og CDN-caches satser jeg på Server-caches. Page Caching leverer færdige HTML-sider, Object Caching bufferer database-resultater, og OPcache beskæftiger sig med PHP-bytecode. Disse lag aflaster backend betydeligt, når headere er korrekt indstillet. Kun kombinationen af hurtige kanter, sunde TTL'er og server-caches giver reelle topværdier. På den måde holder jeg svartiderne stabile, selv når Trafik øges.

Følgende markedsoversigt viser, hvad jeg lægger vægt på, når det gælder hosting. En høj HIT-rate, Redis-tilgængelighed og en god pris er afgørende for valget.

Hosting-udbyder PageSpeed-score Redis-understøttelse Pris (starter)
webhoster.de 98/100 Ja 4,99 €
Andet1 92/100 Valgfrit 6,99 €
Andet2 89/100 Nej 5,99 €

Ugyldiggørelse og udrensningsstrategier

Cache-opbygning er kun halvdelen af arbejdet – den Invalidering afgør sikkerhed og smidighed. For aktiver udløser jeg ændringer via filhash, så der ikke er behov for rensninger. For HTML og API'er planlægger jeg målrettede rensninger: efter implementering (kritiske ruter), efter offentliggørelse (kun berørte sider) eller efter funktionsflag. Jeg understøtter gerne edge-caches via tags/nøgler for at Grupper at tømme i stedet for at finde stier enkeltvis. Hvor det er muligt, bruger jeg „Soft Purge“: Indhold markeres straks som „forældet“ og valideres først ved næste forespørgsel. På den måde undgår jeg belastningsspidser ved samtidige re-fetches. Det er vigtigt at have en organiseret kortlægning: Hvilke begivenheder udløser hvilken purge? Denne logik skal versioneres i platformen.

Sikkerhed og databeskyttelse: offentligt vs. privat

Personlige sider hører hjemme i Privat cache i browseren, ikke i delte caches. Derfor indstiller jeg private, max-age=0 eller no-cache for sådanne indhold. Offentlige HTML-sider kan få public med kort friskhed. Hvis jeg er opmærksom på cookies i anmodningen, forbliver indholdet rent adskilt. På den måde forhindrer jeg, at fremmede brugere uønsket Data andre ser.

Samtidig anvender jeg strenge regler for betalings- og kontoområder. no-store forhindrer enhver lagring af følsomme svar. For resten af webstedet er jeg generøs, så ydeevnen er i orden. Denne klare adskillelse holder platformen hurtig og sikker. Jeg dokumenterer Profiler, så alle involverede forbliver konsekvente.

Forstå heuristisk caching

Hvis Cache-Control og Expires mangler, bruger caches heuristik tilbage – cirka en procentdel af tiden siden sidste ændring. Dette fører til resultater, der er svære at gengive, og svingende aktualitet. Jeg undgår sådanne automatismer ved eksplicit at angive Cache-Control for hver relevant rute. Hvor Last-Modified er unøjagtig (f.eks. ved dynamiske skabeloner), foretrækker jeg ETags. På den måde styrer jeg aktivt aktualiteten og får stabile målinger på tværs af alle klienter.

Range-anmodninger og store filer

Afspil for medier og downloads Rækkevidde-forespørgsler (206 Partial Content) spiller en rolle. Jeg aktiverer Accept-Ranges og leverer konsistente ETags/Last-Modified, så browsere kan genbruge dele korrekt. For versionerede videosegmenter (HLS/DASH) indstiller jeg lange TTL'er; manifestene selv forbliver kortvarige. Vigtigt: Håndter If-Range korrekt, så delområder ikke fører til forældede blandede tilstande ved ændringer. For følsomt indhold gælder fortsat: ingen lagring med no-store, selvom Range er i spil.

Hurtig fejlfinding af almindelige fejl: mit playbook

Jeg begynder med en oversigt over overskrifter: Hvilke direktiver leverer Origin, og hvad ændrer CDN? Derefter definerer jeg TTL-profiler for hver indholdstype. Versionerede aktiver får et år, HTML fem minutter plus revalidering. Jeg aktiverer ETag/Last-Modified overalt, hvor det giver mening. Derefter kontrollerer jeg, om unødvendige Vary- eller Query-parametre HIT-rate tryk.

I næste trin tager jeg mig af netværksdetaljer uden for cachen. En forkert Charset-header eller manglende komprimering koster også tid. Derefter måler jeg igen: DevTools, syntetiske tests og om nødvendigt Real-User-Monitoring. Hvis værdierne er korrekte, fastfryser jeg reglerne i konfigurationen og holder dem versioneret. Sådan vokser kvalitet Trin for trin.

Kort opsummeret

Med korrekte HTTP-headere Jeg styrer, hvad der ligger hvor og hvor længe – og sparer tid og ressourcer. Lange TTL'er for versionerede aktiver, korte tider plus revalidering for HTML og meningsfulde stale-direktiver giver hastighed og robusthed. Rene cache-nøgler, konsekvent versionering og klare regler for public/private forhindrer typiske forhindringer. Overvågning leverer dokumentation og viser resterende huller. Hvis man gør det på denne måde, hæver man Ydelse mærkbar og stabil.

Aktuelle artikler