TTFB-optimering i 2026: Sådan reducerer du Time to First Byte

Lær hvordan du reducerer Time to First Byte (TTFB) med CDN, edge computing, HTTP 103 Early Hints, caching-strategier og backend-optimering. Med praktiske kodeeksempler.

Hvorfor TTFB er fundamentet for al web-performance

Time to First Byte — eller bare TTFB — er den tid, der går fra browseren sender en HTTP-anmodning, til den modtager den allerførste byte af serverens svar. Det lyder måske som en nørdet backend-metrik, men her er pointen: TTFB er det absolutte fundament for alt andet på din side. Mens browseren venter på det første byte, kan den bogstaveligt talt ikke gøre noget. Ingen parsing, ingen rendering, intet. Bare en blank skærm.

Og det er her, det virkelig bider.

Har du allerede læst vores guides til LCP, INP og CLS-optimering, ved du, at alle tre Core Web Vitals afhænger af, at browseren hurtigt kan komme i gang med sit arbejde. Det starter alt sammen med TTFB. En langsom TTFB skubber FCP, LCP og alle efterfølgende metrikker længere ud i tid — uanset hvor optimeret din frontend ellers er. Du kan have den mest perfekte lazy-loading-strategi i verden, men hvis serveren bruger 2 sekunder på at svare, hjælper det ikke det store.

TTFB-tærskelværdier

Google anbefaler en TTFB på under 800 millisekunder målt på 75. percentilen af alle sidevisninger. Værdier over 1800ms betragtes som decideret dårlige. Men TTFB er faktisk ikke en officiel Core Web Vital — den er en diagnostisk metrik. Det betyder dog ikke, at du bare kan ignorere den. En høj TTFB gør det praktisk talt umuligt at opnå gode LCP-scores, fordi LCP inkluderer TTFB som en del af sin samlede tid.

I praksis bør du sigte efter:

  • Under 200ms for statisk eller cached indhold
  • Under 500ms for server-renderede dynamiske sider
  • Under 800ms som absolut øvre grænse

Hvad udgør TTFB? De fire komponenter

For at optimere TTFB skal du forstå, hvad den egentlig består af. TTFB kan nedbrydes i fire faser:

  • DNS-opslag: Oversættelse af domænenavnet til en IP-adresse. Typisk 20–120ms for et ukashet opslag.
  • TCP-forbindelse: Etablering af en TCP-forbindelse (inkl. TLS-handshake for HTTPS). Latensen afhænger direkte af den fysiske afstand til serveren — og det er en faktor, mange undervurderer.
  • Anmodning sendt: Tiden det tager at sende selve HTTP-anmodningen. Normalt ubetydelig for typiske GET-requests.
  • Serverbehandlingstid: Den tid serveren bruger på at generere svaret. Det er her, langt størstedelen af optimeringsmulighederne ligger — databaseforespørgsler, applikationslogik, template-rendering og den slags.

De tre første faser er primært netværksrelaterede, og den mest effektive måde at reducere dem på er via en CDN. Den fjerde fase — serverbehandlingstiden — kræver backend-optimering, caching og nogle arkitekturmæssige beslutninger. Lad os kigge nærmere på begge dele.

Måling og diagnosticering af TTFB

Chrome DevTools

Åbn Network-panelet i Chrome DevTools, klik på dokumentanmodningen (typisk den første HTML-request) og åbn Timing-fanen. Her finder du "Waiting for server response" — det er din TTFB. Du kan se de individuelle faser for DNS, TCP, TLS og ventetid. Det er ærligt talt det hurtigste sted at starte, når du fejlsøger.

Server-Timing headeren: Din bedste ven

Server-Timing er en alt for ofte overset HTTP-header, der lader dig eksponere server-side målinger direkte i browserens DevTools. Den er uvurderlig, når du skal identificere præcis hvor serverbehandlingstiden bruges. Jeg har personligt brugt den til at finde flaskehalse, som ellers ville have taget timer at diagnosticere med traditionel logging.

// Express.js middleware til Server-Timing
app.use(async (req, res, next) => {
  const timings = {};

  // Mål databasetid
  const dbStart = performance.now();
  res.locals.dbResult = await db.query(req.queryParams);
  timings.db = performance.now() - dbStart;

  // Mål template-rendering
  const renderStart = performance.now();
  res.locals.html = renderTemplate(res.locals.dbResult);
  timings.render = performance.now() - renderStart;

  // Mål cache-opslag
  timings.cache = res.locals.cacheHit ? 0 : timings.db;

  // Sæt Server-Timing header
  res.setHeader('Server-Timing',
    `db;dur=${timings.db.toFixed(1)};desc="Database",` +
    `render;dur=${timings.render.toFixed(1)};desc="Template rendering",` +
    `cache;dur=${timings.cache.toFixed(1)};desc="Cache lookup"`
  );

  next();
});

I Chrome DevTools dukker disse målinger op under en "Server Timing"-sektion i Timing-fanen. Har du f.eks. en TTFB på 400ms og kan se, at db bruger 280ms, ved du præcis, hvor du skal sætte ind. Ingen gætteri nødvendigt.

Feltdata med web-vitals-biblioteket

Lab-data er fint til fejlsøgning, men du skal også vide, hvad rigtige brugere oplever. Her er et eksempel med web-vitals-biblioteket, der sender TTFB-data til din analytics:

import { onTTFB } from 'web-vitals';

onTTFB((metric) => {
  console.log('TTFB:', metric.value, 'ms');
  console.log('Rating:', metric.rating); // "good", "needs-improvement", "poor"

  // Nedbryd i faser via NavigationTiming
  const nav = performance.getEntriesByType('navigation')[0];
  const breakdown = {
    dns: nav.domainLookupEnd - nav.domainLookupStart,
    tcp: nav.connectEnd - nav.connectStart,
    tls: nav.secureConnectionStart > 0
      ? nav.connectEnd - nav.secureConnectionStart : 0,
    serverTime: nav.responseStart - nav.requestStart
  };

  navigator.sendBeacon('/analytics/ttfb', JSON.stringify({
    ttfb: metric.value,
    ...breakdown,
    url: location.href
  }));
});

CDN og edge computing: Reducer netværkslatensen

En Content Delivery Network (CDN) distribuerer dit indhold til servere placeret tæt på dine brugere. I 2026 er der ærligt talt ingen undskyldning for ikke at bruge en CDN — selv gratis planer fra Cloudflare giver dramatiske forbedringer. Vi taler typisk om en reduktion på 60–80% i TTFB for internationale brugere. Det er ikke småpenge.

Edge computing: Mere end bare caching

Moderne edge-platforme som Cloudflare Workers, Vercel Edge Functions og AWS CloudFront Functions lader dig køre dynamisk applikationslogik direkte på edge-serveren. Det betyder, at selv personaliserede, dynamiske sider kan serveres med ekstremt lav TTFB — uden at anmodningen skal hele vejen tilbage til din origin-server.

Her er et konkret eksempel:

// Cloudflare Worker: Edge-side rendering med caching
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const cacheKey = new Request(url.toString(), request);
    const cache = caches.default;

    // Tjek edge-cache først
    let response = await cache.match(cacheKey);
    if (response) {
      return new Response(response.body, {
        ...response,
        headers: {
          ...Object.fromEntries(response.headers),
          'X-Cache': 'HIT',
          'Server-Timing': 'edge;dur=1;desc="Cache HIT"'
        }
      });
    }

    // Cache miss — hent fra origin
    const originStart = Date.now();
    response = await fetch(request);
    const originTime = Date.now() - originStart;

    // Gem i edge-cache med stale-while-revalidate
    const cachedResponse = new Response(response.body, {
      ...response,
      headers: {
        ...Object.fromEntries(response.headers),
        'Cache-Control': 's-maxage=3600, stale-while-revalidate=86400',
        'X-Cache': 'MISS',
        'Server-Timing': `origin;dur=${originTime};desc="Origin fetch"`
      }
    });

    // Gem asynkront — bloker ikke svaret
    await cache.put(cacheKey, cachedResponse.clone());
    return cachedResponse;
  }
};

Caching-strategier der faktisk virker

Cache-Control med stale-while-revalidate

stale-while-revalidate er nok en af de mest undervurderede teknikker til at reducere TTFB uden at ofre indholdets friskhed. Strategien er simpel: server det cachede indhold øjeblikkeligt til brugeren, og opdater cachen i baggrunden til den næste besøgende.

# Nginx: Aggressiv caching med stale-while-revalidate
location / {
    proxy_pass http://app_server;
    proxy_cache_valid 200 1h;
    proxy_cache_use_stale updating error timeout http_500 http_502;
    proxy_cache_background_update on;

    add_header Cache-Control "s-maxage=3600, stale-while-revalidate=86400";
    add_header X-Cache-Status $upstream_cache_status;
}

# Statiske assets: Langtids-caching med versionering
location /assets/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

Med denne konfiguration caches dine sider i én time, men stale-indhold kan serveres i op til 24 timer, mens Nginx henter en frisk version i baggrunden. I praksis giver det en cache hit rate på over 90% og næsten øjeblikkelig TTFB for de fleste besøgende. Det er svært at argumentere imod den slags resultater.

Origin shielding

Her er et scenarie, som mange overser: Uden origin shielding sender hver CDN-edge-server sin egen anmodning til din origin ved et cache miss. Har du 100 edge-lokationer og et cache miss, kan din origin pludselig modtage 100 samtidige anmodninger for det samme indhold. Det er mildt sagt ikke optimalt.

Med origin shielding routes alle anmodninger gennem et enkelt shield-POP, og din origin modtager kun én anmodning. De fleste store CDN-udbydere — Cloudflare, Fastly, Akamai — tilbyder origin shielding som en simpel konfigurationsindstilling. Slå det til.

HTTP 103 Early Hints: Udnyt serverens tænketid

HTTP 103 Early Hints er en relativt ny HTTP-statuskode, der i 2026 er understøttet af alle store browsere (Chrome, Firefox, Safari og Edge). Idéen er smart i al sin enkelhed: Mens serveren arbejder på at generere det endelige svar, sender den et foreløbigt 103-svar med Link-headers, der fortæller browseren, hvilke ressourcer den allerede kan begynde at hente.

# Nginx: Konfigurer Early Hints
location / {
    # Send 103 Early Hints med kritiske ressourcer
    add_header Link "; rel=preload; as=style" early;
    add_header Link "; rel=preload; as=font; crossorigin" early;
    add_header Link "; rel=preconnect" early;

    proxy_pass http://app_server;
}

Effekten er målbar: op til 30% hurtigere sideindlæsning, fordi browseren downloader stylesheets, fonts og andre kritiske ressourcer parallelt med, at serveren genererer HTML-dokumentet. Cloudflare tilbyder endda automatisk Early Hints ved at parse dine Link-headers fra origin-svaret og cache dem til efterfølgende anmodninger. Ret elegant, faktisk.

Backend-optimering: Reducer serverbehandlingstiden

Databaseoptimering

Så, lad os tale om den del, som de fleste egentlig bør starte med. Databaseforespørgsler er den hyppigste årsag til langsom serverbehandlingstid — og det er her, Server-Timing headeren virkelig betaler sig selv hjem. Når du har identificeret de langsomme queries, kan du anvende følgende:

  • Indexering: Sørg for, at alle kolonner brugt i WHERE- og JOIN-klausuler er indekseret. En manglende indeks på en tabel med millioner af rækker kan betyde forskellen mellem 2ms og 2000ms. Det er ikke en overdrivelse.
  • Query-caching: Implementer application-level caching med Redis eller Memcached for resultater, der ikke ændres ved hver request.
  • N+1-problemet: Brug eager loading i stedet for lazy loading i din ORM. En side, der udløser 50 individuelle databaseforespørgsler, er altid langsommere end én velskrevet JOIN. (Ja, det gælder også dig, Django-udviklere.)
  • Forbindelsespooling: Opret databaseforbindelser på forhånd og genbrug dem med connection pooling. At oprette en ny forbindelse per request er overraskende dyrt.

Komprimering og HTTP/2

Aktiver Brotli-komprimering på serveren — den giver 15–25% bedre komprimering end Gzip for HTML, CSS og JavaScript. Kombiner det med HTTP/2 (eller HTTP/3, hvis din CDN understøtter det) for at eliminere head-of-line blocking og tillade multiplexede anmodninger over én enkelt forbindelse.

# Nginx: Aktiver Brotli
brotli on;
brotli_comp_level 6;
brotli_types text/html text/css application/javascript application/json image/svg+xml;

# Aktiver HTTP/2
listen 443 ssl http2;

# Aktiver HTTP/3 (QUIC) hvis understøttet
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';

Reducer redirects og DNS-opslag

Hvert redirect tilføjer en komplet round-trip til din TTFB. En klassisk synder er kæden http://example.comhttps://example.comhttps://www.example.com — det er to ekstra round-trips, der nemt kan koste 100–300ms. Reducer dine redirect-kæder til maksimalt ét hop, og implementer HSTS-headers for at undgå HTTP-til-HTTPS-redirects for tilbagevendende brugere.

For tredjepartsdomæner du er afhængig af (analytics, CDN, API'er osv.) kan du bruge dns-prefetch og preconnect hints i din HTML:

<!-- DNS-prefetch for tredjepartsdomæner -->
<link rel="dns-prefetch" href="https://analytics.example.com">

<!-- Preconnect for kritiske tredjepartsressourcer -->
<link rel="preconnect" href="https://cdn.example.com" crossorigin>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

Monitoring: Hold øje med TTFB over tid

TTFB er ikke noget, du optimerer én gang og så glemmer alt om. Nye features, flere database-rækker, tredjepartsintegrationer og stigende trafik kan langsomt forringe din TTFB uden at du opdager det. Det er lidt som at koge en frø — det sker så gradvist, at ingen lægger mærke til det, før det er for sent.

Opsæt automatisk overvågning med CrUX (Chrome User Experience Report), PageSpeed Insights API eller en RUM-løsning (Real User Monitoring), der sporer TTFB som en nøglemetrik over tid.

Sæt performance-budgetter: Konfigurer alarmer, hvis P75-TTFB overstiger dine tærskelværdier, så du kan reagere, før dine brugere begynder at forlade siden. Det er langt billigere at forebygge end at reparere.

FAQ: Ofte stillede spørgsmål om TTFB

Er TTFB en Core Web Vital?

Nej, TTFB er ikke en officiel Core Web Vital. Det er en diagnostisk metrik. Men den påvirker direkte LCP og FCP, som er Core Web Vitals. En dårlig TTFB gør det praktisk talt umuligt at opnå gode LCP-scores, så den bør behandles med lige så stor alvor.

Hvad er en god TTFB-værdi?

Google anbefaler under 800ms som "god". Under 200ms er fremragende for cached eller statisk indhold. For dynamiske server-renderede sider er under 500ms et realistisk mål. Sigt altid mod den lavest mulige værdi — enhver millisekund sparet i TTFB forbedrer alle efterfølgende metrikker.

Kan en CDN alene løse dårlig TTFB?

Kort svar: det kommer an på. En CDN løser primært den netværksrelaterede del af TTFB (DNS, TCP, TLS). Hvis din serverbehandlingstid er langsom — f.eks. pga. tunge databaseforespørgsler — hjælper en CDN kun, hvis indholdet kan caches. For dynamiske sider skal du kombinere CDN med backend-optimering, caching og eventuelt edge computing.

Hvordan påvirker TTFB min SEO?

TTFB påvirker indirekte SEO, fordi den forlænger LCP og FCP, som er vigtige rankingfaktorer. Derudover begrænser en høj TTFB, hvor mange sider Googlebot kan crawle inden for sit tidsbudget. En hurtig TTFB betyder, at flere af dine sider bliver indekseret hurtigere — og det er svært at sætte en pris på.

Hvad er forskellen mellem TTFB og serverresponstid?

Serverresponstid (Server Response Time) måler kun den tid, serveren bruger på at generere svaret. TTFB inkluderer også netværkstiden (DNS, TCP, TLS). Så TTFB = netværkstid + serverresponstid. Lighthouse rapporterer "Reduce initial server response time" som serverresponstiden, mens TTFB i CrUX-data inkluderer hele rejsen fra browser til server og tilbage.

Om Forfatteren Editorial Team

Our team of expert writers and editors.