Time to First Byte (TTFB): Los het knelpunt op dat alles vertraagt
Je server heeft 2,3 seconden nodig om te reageren. In die tijd zien gebruikers een leeg scherm. Niets laadt. Geen afbeeldingen, geen tekst, helemaal niets. Ze zijn weg voordat je pagina zelfs maar begint te renderen. TTFB is de verborgen rem op alle andere metrics.

Wat is TTFB (en waarom het belangrijk is)?
TTFB meet hoe lang het duurt voordat de browser de eerste byte ontvangt van je server. Het is de tijd van het moment dat een gebruiker een pagina opvraagt tot het moment dat de server begint met het verzenden van data. Gedurende deze tijd zien gebruikers een leeg scherm.
Belangrijk: TTFB is geen officieel Core Web Vital, maar heeft direct invloed op LCP en FCP. Google beschouwt het als een fundamentele metric voor algehele paginaprestaties. Als je TTFB traag is, laadt alles te laat.
Let op: TTFB heeft meerdere definities
Verschillende meettools hanteren verschillende beginpunten voor TTFB-berekeningen. Begrijpen welke variant je meet is essentieel voor nauwkeurige prestatieanalyse en eerlijke vergelijkingen.
TTFB-normen (Navigation TTFB)
In deze gids gebruiken we Navigation TTFB (de CrUX-definitie) tenzij anders aangegeven.
Wat is er inbegrepen in Navigation TTFB?
Navigation TTFB components (startTime → responseStart):
1. Redirects (0ms if no redirects)
2. Service worker (0ms if not used)
3. Browser cache (checking local cache)
4. DNS lookup (0-100ms, or 0ms if cached)
5. TCP connection (1 RTT, or 0ms if reused)
6. TLS handshake (1-2 RTT, or 0ms if reused)
7. HTTP request (minimal)
8. Server processing (varies widely)
9. Response start (first byte arrives)
Note: Many subparts can be 0ms depending on caching,
connection reuse, and other factors.TTFB-variabiliteit begrijpen
TTFB combineert meerdere onderdelen die zich anders gedragen afhankelijk van caching en verbindingsstatus. Aanvragen op bestaande verbindingen slaan DNS en TLS over (0 ms), terwijl nieuwe verbindingen de volledige overhead hebben. Resources in de cache omzeilen het netwerk volledig. Dit leidt tot duidelijk verschillende prestatieclusters in je data — sommige laadtijden zijn snel, andere traag — waardoor gemiddelde of percentielwaarden belangrijke patronen in de gebruikerservaring kunnen verhullen.
Waarom TTFB belangrijk is voor prestaties
TTFB is het startschot voor het laden van de pagina. Elke milliseconde TTFB-vertraging telt op bij LCP, FCP en de totale laadtijd. Een snelle TTFB versterkt alle andere optimalisaties.
Impact op LCP
Als TTFB 2 seconden is, kan je LCP niet beter zijn dan 2 seconden. Een snelle TTFB geeft je ruimte om andere aspecten van het laden te optimaliseren.
Impact op FCP
Er wordt niets gerenderd totdat de HTML binnenkomt. Een trage TTFB betekent dat gebruikers langer naar een leeg scherm staren, zelfs als je CSS en JavaScript perfect zijn geoptimaliseerd.
Waargenomen prestaties
Gebruikers op trage verbindingen zijn bijzonder gevoelig voor TTFB. Een vermindering van 500 ms in TTFB voelt dramatisch sneller dan het micro-optimaliseren van JavaScript.
TTFB terugbrengen van 1,5 s naar 500 ms kan de conversie met 7–10% verhogen. Serversnelheid is onzichtbaar — maar gebruikers voelen het direct.
TTFB meten
Velddata (echte gebruikers)
Echte TTFB varieert per locatie, netwerkkwaliteit en serverbelasting. Velddata toont wat je gebruikers daadwerkelijk ervaren:
- Iron/Out gratis benchmark — haal je TTFB op uit het Chrome UX Report
- PageSpeed Insights — toont veld-TTFB-data uit het Chrome UX Report waar beschikbaar
- Real User Monitoring — volg TTFB voor elke bezoeker met onze observability-implementatie
Labdata (testen)
Test TTFB vanuit verschillende locaties en configuraties:
- WebPageTest — test vanuit meerdere wereldwijde locaties, toont TTFB-uitsplitsing
- Lighthouse — rapporteert TTFB in de diagnosticssectie
- Chrome DevTools — het Network-tabblad toont timing voor elke aanvraag
TTFB meten in Chrome DevTools
// Chrome DevTools Network tab:
// 1. Open DevTools (F12)
// 2. Go to Network tab
// 3. Reload the page
// 4. Click on the main document request
// 5. Go to Timing tab
// 6. "Waiting for server response" = TTFB
// TTFB includes:
// - Queueing
// - Stalled
// - DNS Lookup
// - Initial connection
// - SSL
// - Request sent
// - Waiting (TTFB)TTFB programmatisch meten
Installeer de web-vitals library:
npm install web-vitalsTrack vervolgens TTFB:
import {onTTFB} from 'web-vitals';
onTTFB((metric) => {
console.log('TTFB:', metric.value);
// Send to analytics
analytics.track('ttfb', {
value: metric.value,
rating: metric.rating, // 'good', 'needs-improvement', 'poor'
navigationType: metric.navigationType
});
});
// Or use Navigation Timing API directly
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach((entry) => {
if (entry.entryType === 'navigation') {
const ttfb = entry.responseStart - entry.requestStart;
console.log('TTFB:', ttfb);
}
});
});
observer.observe({ type: 'navigation', buffered: true });Veelvoorkomende oorzaken van trage TTFB
1. Trage serververwerking
Server-side rendering, databasequeries en API-aanroepen tellen allemaal op bij TTFB. Complexe paginalogica kan honderden milliseconden in beslag nemen voordat de eerste byte wordt verzonden.
Fix: Cache gerenderde pagina's, optimaliseer databasequeries, gebruik edge rendering.
2. Geen CDN of slechte CDN-configuratie
Gebruikers ver van je oorspronkelijke server hebben een hoge latentie. Een gebruiker in Australië die een aanvraag doet bij een Amerikaanse server voegt 200–300 ms toe alleen al voor de retourreis.
Fix: Gebruik een wereldwijd CDN om content te serveren vanuit edge-locaties dicht bij gebruikers.
3. Onvoldoende serverresources
Onderbemande servers worstelen onder belasting. CPU-knelpunten, geheugenbeperkingen en trage schijf-I/O verhogen allemaal TTFB tijdens verkeerspieken.
Fix: Schaal serverresources op, implementeer caching, optimaliseer de backend-code.
4. Databasequeryprestaties
Trage queries, ontbrekende indexen en N+1-queryproblemen kunnen seconden toevoegen aan TTFB. Elke niet-gecachede databaseaanvraag voegt latentie toe.
Fix: Voeg database-indexen toe, implementeer querycaching, gebruik leesreplica's.
5. Netwerklatentie
DNS-opzoektijd, TCP-handshake en TLS-onderhandeling dragen allemaal bij aan TTFB. Slechte netwerkrouting kan aanzienlijke overhead toevoegen.
Fix: Gebruik DNS-prefetching, schakel HTTP/3 in, implementeer connection prewarming.
TTFB-optimalisatietechnieken
1. Gebruik een CDN voor edge caching
Stel juiste cache-headers in
// Express.js: Set cache-control headers
app.get('/api/data', (req, res) => {
res.set('Cache-Control', 'public, max-age=3600, s-maxage=86400');
res.json(data);
});
// Nginx: Cache static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}Impact: CDN-caching kan TTFB verlagen van 500–1000 ms naar 20–50 ms voor gecachede responses.
2. Serververwerking optimaliseren
Databasequeryoptimalisatie
// Bad: N+1 query problem
const users = await db.query('SELECT * FROM users');
for (const user of users) {
user.posts = await db.query(
'SELECT * FROM posts WHERE user_id = ?',
[user.id]
);
}
// TTFB: 500-2000ms (100 queries)
// Good: Single query with JOIN
const users = await db.query(`
SELECT
users.*,
posts.id as post_id,
posts.title as post_title
FROM users
LEFT JOIN posts ON posts.user_id = users.id
`);
// TTFB: 50-150ms (1 query)
// Better: Add indexes
CREATE INDEX idx_posts_user_id ON posts(user_id);
CREATE INDEX idx_users_email ON users(email);
// Query time: 100ms -> 5msIncrementele statische regeneratie implementeren
// Next.js: ISR for fast TTFB with fresh content
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
// Serve cached page, rebuild in background
revalidate: 60 // Check for updates every 60 seconds
};
}
// First request after revalidate:
// - User gets cached version (TTFB: 50ms)
// - New version builds in background
// - Next user gets updated version
// Without ISR:
// - Every request hits database (TTFB: 500ms+)3. HTTP/3 en moderne protocollen inschakelen
// Cloudflare: HTTP/3 enabled by default
// Reduces TTFB by 20-30% on mobile networks
// Nginx: Enable HTTP/3
server {
listen 443 quic reuseport;
listen 443 ssl http2;
ssl_protocols TLSv1.3;
ssl_early_data on; # 0-RTT
add_header Alt-Svc 'h3=":443"; ma=86400';
}
// Benefits:
// - Faster connection establishment
// - Better mobile performance
// - Head-of-line blocking eliminated
// - 0-RTT resumption (saves 1 RTT on repeat visits)4. DNS-opzoektijd verminderen
<!-- DNS prefetching for external domains -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//analytics.example.com">
<!-- Preconnect for critical origins -->
<link rel="preconnect" href="//api.example.com" crossorigin>
<!-- Use a fast DNS provider -->
Cloudflare DNS: ~10ms lookup time
Google DNS: ~20ms
Default ISP: ~50-200ms
<!-- Benefits: -->
DNS Prefetch: Saves 20-100ms on first request
Preconnect: Saves 20-100ms + TCP/TLS timeGeavanceerde TTFB-optimalisatiestrategieën
Edge rendering met Cloudflare Workers / Vercel Edge
// Render React at the edge, closest to users
import { renderToString } from 'react-dom/server';
import App from './App';
export default async function handler(request) {
const html = renderToString(<App />);
return new Response(html, {
headers: {
'Content-Type': 'text/html',
'Cache-Control': 'public, s-maxage=60'
}
});
}
// Benefits:
// - 10-30ms TTFB globally
// - No origin server load
// - Scales infinitelyGeavanceerd: 103 Early Hints
Met 103 Early Hints kunnen servers resource-preload-instructies sturen voordat de volledige HTML-response gegenereerd is. Terwijl de server de aanvraag verwerkt, kan de browser alvast beginnen met het downloaden van kritieke CSS en lettertypen. Dit kan de gemeten TTFB met 200–500 ms verlagen.
Gebruik dit alleen als je trage server-side verwerking hebt en weet welke resources kritiek zijn. Cloudflare en Fastly ondersteunen dit van nature. Lege 103-responses zonder zinvolle resource hints manipuleren slechts de metric zonder de echte prestaties te verbeteren.
Cold starts optimaliseren voor serverless
// Vercel/Netlify: Reduce cold start times
// Bad: Large dependencies
import _ from 'lodash'; // 100KB
import moment from 'moment'; // 200KB
// Cold start: 500-1000ms
// Good: Import only what you need
import debounce from 'lodash/debounce'; // 5KB
import { format } from 'date-fns'; // 10KB
// Cold start: 100-200ms
// Keep functions warm
// - Use Vercel Edge Functions (no cold starts)
// - Or ping functions every 5 minutes
// - Or use reserved concurrency (AWS Lambda)Database connection pooling
// Reuse database connections
import { Pool } from 'pg';
const pool = new Pool({
max: 20, // Max connections
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000
});
// Bad: New connection each request (100-200ms overhead)
app.get('/data', async (req, res) => {
const client = new Client();
await client.connect();
const result = await client.query('SELECT * FROM data');
await client.end();
res.json(result.rows);
});
// Good: Reuse pooled connections (5-10ms overhead)
app.get('/data', async (req, res) => {
const result = await pool.query('SELECT * FROM data');
res.json(result.rows);
});TTFB monitoren over tijd
TTFB kan langzaam verslechteren naarmate het verkeer groeit of de code complexer wordt. Monitor het proactief.
TTFB tracken per route en locatie
import {onTTFB} from 'web-vitals';
onTTFB((metric) => {
analytics.track('ttfb', {
value: metric.value,
rating: metric.rating,
page_path: location.pathname,
navigation_type: metric.navigationType,
connection_type: navigator.connection?.effectiveType,
// Server timing breakdown (if available)
server_timing: getServerTimingMetrics()
});
});
function getServerTimingMetrics() {
const navigation = performance.getEntriesByType('navigation')[0];
const serverTiming = navigation.serverTiming || [];
return serverTiming.map(entry => ({
name: entry.name,
duration: entry.duration
}));
}Server-Timing header voor debugging
// Express middleware: Track backend timing
app.use((req, res, next) => {
const start = Date.now();
const timings = {};
res.on('finish', () => {
const total = Date.now() - start;
res.set('Server-Timing', [
`total;dur=${total}`,
`db;dur=${timings.db || 0}`,
`cache;dur=${timings.cache || 0}`,
`render;dur=${timings.render || 0}`
].join(', '));
});
req.timing = timings;
next();
});
// In route handler
app.get('/product/:id', async (req, res) => {
const cacheStart = Date.now();
const cached = await cache.get(req.params.id);
req.timing.cache = Date.now() - cacheStart;
if (cached) return res.json(cached);
const dbStart = Date.now();
const product = await db.getProduct(req.params.id);
req.timing.db = Date.now() - dbStart;
res.json(product);
});
// Visible in Chrome DevTools Network -> Timing tabAlerts instellen
- P75 TTFB-norm: Alert als het 75e percentiel boven 800 ms uitkomt
- Regionale monitoring: Volg TTFB per geografische regio
- Regressiedetectie: Alert bij een TTFB-stijging van meer dan 100 ms na een deployment
- CDN cache hit rate: Alert als de CDN cache hit rate onder een doelnorm zakt
Performance budgets
- TTFB P75: Onder 800 ms wereldwijd
- CDN cache hit rate: Boven 90%
- Databasequerytijd: Onder 50 ms voor de meeste queries
- Oorspronkelijke serverrespons: Onder 200 ms voor gecachede content
TTFB-optimalisatiechecklist
Hulp nodig bij het verlagen van je TTFB?
Serveroptimalisatie vereist diepgaande infrastructuurkennis. Wij kunnen je backend auditeren, knelpunten identificeren en bewezen oplossingen implementeren. Neem contact op of voer een gratis benchmark uit om je huidige TTFB te zien.
Hulp nodig bij het verbeteren van je TTFB?
Wij auditen je serverinfrastructuur en implementeren optimalisaties die de responstijden drastisch verlagen.