Fix Slow Server Response (TTFB) for Better LCP
If the document response arrives late, inspect connection setup, redirects, and server work before optimizing the LCP resource. Time to First Byte (TTFB) measures navigation start to the first response byte.
Measure the full LCP timing after a server change. The improvement can differ from the TTFB reduction.
What's the problem?
TTFB includes DNS, connection setup, redirects, applicable service worker startup, and server work. Google's field guidance uses 800ms or less as good and above 1800ms as poor, at the 75th percentile. Values between those thresholds need improvement.
TTFB is a diagnostic metric, not a Core Web Vital. It does not directly contribute to the Lighthouse Performance score.
Lighthouse's Document request latency insight checks server responses above 600ms, redirects, and compression. Its server response measurement excludes DNS and redirects, so it covers only part of navigation TTFB. Older reports call this audit "Reduce initial server response time".
A slow document response can delay LCP. With 103 Early Hints or streamed HTML, the first response byte can precede the full document. Inspect the LCP breakdown to see where loading and rendering still wait.
The problem compounds across geographic distances. A user in Singapore requesting a page from a Virginia server experiences 250ms+ of network latency each way. Add database queries, server-side rendering, and cold starts, and you're looking at TTFB measurements that dwarf everything else in your performance waterfall.
How to identify this issue
Chrome DevTools
- Open DevTools (F12) and navigate to the Network tab
- Hard reload the page (Ctrl+Shift+R / Cmd+Shift+R)
- Click on the first HTML document request
- Examine the Timing breakdown and look for "Waiting (TTFB)"
- Inspect DNS, connection setup, and redirects separately. One request does not establish a field percentile or Core Web Vitals assessment.
DevTools Waiting (TTFB) includes a network round trip and server processing. It does not include every phase of navigation TTFB.
Command line
curl -w "TTFB: %{time_starttransfer}s\n" -o /dev/null -s https://your-site.com
for i in {1..5}; do curl -w "%{time_starttransfer}\n" -o /dev/null -s https://your-site.com; done
curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTTFB: %{time_starttransfer}s\n" -o /dev/null -s https://your-site.comLighthouse indicators
Open Document request latency and inspect its server response, redirect, and compression findings. A server response above 600ms needs investigation. The insight helps diagnose loading delays; passing it does not establish good field TTFB or passing Core Web Vitals.
The fix
Primary: deploy a CDN with edge caching
A CDN eliminates geographic latency by serving cached content from servers close to your users. This single change typically reduces TTFB by 100-500ms for global audiences.
/*
Cache-Control: public, max-age=3600, s-maxage=3600// Vercel edge caching via headers
export const config = {
runtime: 'edge',
}
export default function handler(req) {
return new Response(html, {
headers: {
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
},
})
}For dynamic content, use stale-while-revalidate to serve cached content immediately while refreshing in the background:
Cache-Control: public, max-age=60, stale-while-revalidate=3600Secondary: optimize database queries
Slow database queries are the hidden TTFB killer. A single unindexed query can add 500ms+ to every page load.
-- Find slow queries in PostgreSQL
SELECT query, calls, mean_time, total_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;
-- Add indexes for common patterns
CREATE INDEX idx_posts_user_published
ON posts(user_id, published_at)
WHERE status = 'published';// Use connection pooling - critical for serverless
import { Pool } from 'pg'
const pool = new Pool({
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
})Tertiary: edge computing for dynamic content
When you can't cache HTML, move your compute closer to users with edge functions.
// Cloudflare Workers - global edge deployment
export default {
async fetch(request, env) {
const data = await env.KV.get('page-data', 'json')
return new Response(renderPage(data), {
headers: { 'Content-Type': 'text/html' },
})
}
}// Vercel Edge Functions
export const config = { runtime: 'edge' }
export default async function handler(req) {
const data = await fetch('https://api.example.com/data')
return new Response(renderTemplate(await data.json()))
}Why this works
An earlier document response can let the browser discover resources and render content sooner. A CDN can reduce connection latency, while caching can avoid repeated server work. The LCP result also depends on resource loading and render delay. Compare the full breakdown after a change instead of assuming matching TTFB and LCP gains.
Technical SEO bonus: crawl budget
Improving TTFB doesn't just help users; it helps Googlebot index your site.
- Crawl Budget: Google allocates a specific time/resource budget to crawl your site.
- The Connection: Faster server response = Googlebot crawls more pages in the same amount of time.
- The Result: Faster discovery of new content and updates.
"If the site is fast, we can crawl more. If the site is slow, we crawl less." - Google Search Central
Framework-specific solutions
Next.js: Use App Router with automatic streaming. Deploy to Vercel for built-in edge caching. Configure generateStaticParams for static generation. Add ISR with revalidate for dynamic content that changes infrequently.
export const revalidate = 3600 // ISR every hourNuxt: Configure routeRules for per-route caching strategies. Use prerenderRoutes for static paths. Deploy to Cloudflare or Vercel for edge rendering. Enable experimental.componentIslands for partial hydration.
export default defineNuxtConfig({
routeRules: {
'/blog/**': { swr: 3600 },
'/': { prerender: true },
},
})Verify the fix
After implementing changes:
- Clear all caches (CDN, server, browser)
- Run the curl command from multiple geographic locations
- Use WebPageTest with test locations matching your user base
- Run Lighthouse and inspect Document request latency and the LCP breakdown
- Compare field TTFB and LCP for the same URL or origin and device. CrUX uses a trailing 28-day period.
Repeat the same test conditions. A lower TTFB does not guarantee the same reduction in LCP or a passing Core Web Vitals assessment.
Common mistakes
Over-caching personalized content: Caching user-specific pages at the CDN edge causes users to see each other's data. Use Cache-Control: private for authenticated pages, or implement edge-side personalization with cookies.
Ignoring cold starts: Serverless functions can add 500ms+ on cold start. Monitor cold start frequency separately from average TTFB. Use provisioned concurrency or edge functions with faster cold starts.
Missing cache invalidation: Aggressive caching without proper invalidation serves stale content. Implement cache tags or surrogate keys for targeted purging when content updates.
Related issues
TTFB problems often compound with other LCP issues:
- Render-Blocking Resources - Both delay the critical rendering path
- Redirects - Each redirect adds another full TTFB cycle
- Client-Side Rendering - SSR with slow TTFB is still slow
Test your entire site
TTFB varies across pages - your homepage may be fast while product pages with database queries are slow. Run a complete scan to identify which routes have server response problems before they impact real users.
Scan Your Site with Unlighthouse