Technical

Time to First Byte (TTFB)

A web performance metric that measures the time from when a browser requests a page until it receives the first byte of data from the web server.

Quick Answer

  • What it is: A web performance metric that measures the time from when a browser requests a page until it receives the first byte of data from the web server.
  • Why it matters: TTFB directly impacts all other performance metrics and user experience, as nothing can load until the server responds.
  • How to check or improve: Optimize server processing, implement caching, use CDNs, and reduce database query times to achieve TTFB under 600ms.

When you'd use this

TTFB directly impacts all other performance metrics and user experience, as nothing can load until the server responds.

Example scenario

Hypothetical scenario (not a real company)

A team might use Time to First Byte (TTFB) when Optimize server processing, implement caching, use CDNs, and reduce database query times to achieve TTFB under 600ms.

Common mistakes

  • Confusing Time to First Byte (TTFB) with Largest Contentful Paint (LCP): A Core Web Vitals metric that measures the render time of the largest image or text block visible within the viewport, relative to when the page first started loading.
  • Confusing Time to First Byte (TTFB) with Core Web Vitals: A set of three specific metrics that Google uses to measure user experience on websites: loading performance (LCP), interactivity (INP), and visual stability (CLS). Learn how to measure and improve your Core Web Vitals scores.

How to measure or implement

  • Optimize server processing, implement caching, use CDNs, and reduce database query times to achieve TTFB under 600ms

Test your server response times

Start here
Updated Jan 20, 2026·5 min read

Time to First Byte (TTFB) is the foundational web performance metric that measures how quickly your server responds to requests. It spans from the moment a user's browser initiates a request until it receives the first byte of response data. While not a Core Web Vital itself, TTFB directly impacts LCP and overall page load performance—you can't paint content that hasn't arrived yet.

What is Time to First Byte?

TTFB encompasses the entire journey of a web request's initial phase:

  1. DNS lookup: Resolving the domain name
  2. Connection establishment: TCP handshake and SSL/TLS negotiation
  3. Server processing: Backend processing time
  4. Network transit: Time for the first byte to travel back

The metric effectively measures your infrastructure's responsiveness—combining network latency, server processing power, application efficiency, and database performance into a single number.

Google's recommended TTFB thresholds:

  • Good: Under 600ms (ideally under 200ms)
  • Needs Improvement: 600ms to 1500ms
  • Poor: Over 1500ms

These thresholds apply to the 75th percentile of page loads, meaning 75% of your users should experience "good" TTFB.

Why TTFB Matters for Performance and SEO

The Cascade Effect

TTFB is the first domino in the performance cascade. A slow TTFB delays everything:

  • LCP impact: Can't render content that hasn't loaded
  • FID impact: JavaScript can't execute until it arrives
  • User perception: Users see blank screens during high TTFB

Research shows that every 100ms improvement in TTFB correlates with:

  • 0.6% increase in conversion rates
  • 1% improvement in page views per session
  • 0.4% reduction in bounce rate

SEO Implications

While TTFB isn't a direct Core Web Vital, it affects SEO through:

Crawl Budget Optimization: Googlebot allocates crawl time based on server responsiveness. Slow TTFB means:

  • Fewer pages crawled per visit
  • Slower index updates
  • Potential ranking delays

Indirect Ranking Factors:

  • Poor TTFB worsens Core Web Vitals
  • Increases bounce rates (negative user signal)
  • Reduces pages per session
  • Limits crawl efficiency

Competitive Advantage: In competitive niches, TTFB can be the differentiator. Amazon found that every 100ms of latency cost them 1% in sales.

Global User Impact

TTFB varies dramatically by geography:

  • Same-region requests: 10-50ms
  • Cross-country requests: 50-150ms
  • International requests: 150-500ms+
  • Emerging markets: Often 500ms+ due to infrastructure

This geographical variance makes CDNs and edge computing critical for global audiences.

How TTFB Works: Technical Components

Breaking Down TTFB

TTFB consists of several sequential components:

1. DNS Resolution (0-200ms)

User enters URL → Browser checks DNS cache →
→ OS DNS cache → Router cache → ISP DNS →
→ Root servers → TLD servers → Authoritative servers

2. TCP Connection (10-150ms per round trip)

SYN → (network latency) → Server
SYN-ACK ← (network latency) ← Server
ACK → (network latency) → Server

3. TLS Handshake (20-200ms)

ClientHello → Server
ServerHello, Certificate ← Server
ClientKeyExchange, Finished → Server
Finished ← Server

4. HTTP Request (5-50ms)

GET /page HTTP/1.1 → Server
Host: example.com
[Headers...]

5. Server Processing (Variable, 50-5000ms)

Request received → Route matching → Authentication →
→ Database queries → Business logic → Template rendering →
→ Response generation

6. First Byte Transit (5-150ms)

Server → Network infrastructure → User's browser

Server Processing Deep Dive

The server processing phase often dominates TTFB:

Request Lifecycle:

  1. Web server receives request (nginx, Apache)
  2. Passes to application server (Node.js, Python, PHP)
  3. Router determines handler
  4. Middleware executes (auth, logging, etc.)
  5. Controller/handler processes request
  6. Database queries execute
  7. Template renders or JSON serializes
  8. Response buffers and sends

Common Bottlenecks:

  • Unoptimized database queries
  • Synchronous external API calls
  • Heavy computation on request thread
  • Session storage retrieval
  • Template compilation

Network Factors

Physical Distance: Speed of light limitations mean:

  • Same city: ~1ms round trip
  • Cross-country (US): ~40ms round trip
  • Transoceanic: ~100-150ms round trip

Network Congestion:

  • Peak hours increase latency
  • ISP routing inefficiencies
  • Peering agreements affect routes
  • Mobile networks add 20-100ms

Best Practices for Optimizing TTFB

1. Implement Smart Caching Strategies

Server-Side Caching

// Redis caching example
const redis = require("redis")
const client = redis.createClient()

async function getCachedData(key, fetchFunction, ttl = 3600) {
  // Check cache first
  const cached = await client.get(key)
  if (cached) return JSON.parse(cached)

  // Fetch and cache if miss
  const data = await fetchFunction()
  await client.setex(key, ttl, JSON.stringify(data))
  return data
}

// Usage
app.get("/api/products", async (req, res) => {
  const products = await getCachedData(
    "products:all",
    () => db.products.findAll(),
    300 // 5-minute cache
  )
  res.json(products)
})

Edge Caching with CDN

# Nginx caching configuration
location /api/ {
  proxy_cache api_cache;
  proxy_cache_valid 200 302 5m;
  proxy_cache_valid 404 1m;
  proxy_cache_use_stale error timeout updating;
  proxy_cache_lock on;
  add_header X-Cache-Status $upstream_cache_status;
}

Database Query Caching

-- MySQL query cache
SET SESSION query_cache_type = ON;

-- PostgreSQL with materialized views
CREATE MATERIALIZED VIEW product_summary AS
SELECT category, COUNT(*), AVG(price)
FROM products
GROUP BY category;

-- Refresh periodically
REFRESH MATERIALIZED VIEW CONCURRENTLY product_summary;

2. Optimize Database Performance

Query Optimization

-- Bad: N+1 query problem
SELECT * FROM posts;
-- Then for each post:
SELECT * FROM comments WHERE post_id = ?;

-- Good: Single query with JOIN
SELECT p.*, c.*
FROM posts p
LEFT JOIN comments c ON c.post_id = p.id
ORDER BY p.created_at DESC;

-- Better: With selective columns
SELECT
  p.id, p.title, p.excerpt,
  COUNT(c.id) as comment_count
FROM posts p
LEFT JOIN comments c ON c.post_id = p.id
GROUP BY p.id
LIMIT 20;

Indexing Strategy

-- Analyze slow queries
EXPLAIN ANALYZE SELECT * FROM users
WHERE email = 'user@example.com' AND status = 'active';

-- Add composite index
CREATE INDEX idx_users_email_status
ON users(email, status);

-- Monitor index usage
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes
ORDER BY idx_scan;

Connection Pooling

// Node.js with connection pooling
const { Pool } = require("pg")

const pool = new Pool({
  max: 20, // Maximum connections
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000
})

// Reuse connections
app.get("/api/data", async (req, res) => {
  const client = await pool.connect()
  try {
    const result = await client.query("SELECT * FROM data")
    res.json(result.rows)
  } finally {
    client.release() // Return to pool
  }
})

3. Use Content Delivery Networks (CDNs)

CDN Configuration

// Cloudflare Workers for edge compute
addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
  // Check edge cache
  const cache = caches.default
  const cached = await cache.match(request)
  if (cached) return cached

  // Fetch from origin
  const response = await fetch(request)

  // Cache at edge
  if (response.status === 200) {
    const headers = new Headers(response.headers)
    headers.set("Cache-Control", "public, max-age=300")
    const cachedResponse = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: headers
    })
    event.waitUntil(cache.put(request, cachedResponse.clone()))
    return cachedResponse
  }

  return response
}

Multi-Region Deployment

# AWS CloudFront configuration
Distributions:
  MyDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      Origins:
        - DomainName: origin.example.com
          S3OriginConfig:
            OriginAccessIdentity: !Sub origin-access-identity
      Enabled: true
      PriceClass: PriceClass_All # Use all edge locations
      ViewerCertificate:
        AcmCertificateArn: !Ref Certificate
      CacheBehaviors:
        - PathPattern: /api/*
          TargetOriginId: APIOrigin
          ViewerProtocolPolicy: https-only
          CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad

4. Optimize Server Configuration

Enable HTTP/2 and HTTP/3

# Nginx HTTP/2 and HTTP/3 configuration
server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  listen 443 http3 reuseport;
  listen [::]:443 http3 reuseport;

  ssl_certificate /path/to/cert.pem;
  ssl_certificate_key /path/to/key.pem;

  # Enable OCSP stapling
  ssl_stapling on;
  ssl_stapling_verify on;

  # HTTP/3 advertisement
  add_header Alt-Svc 'h3=":443"; ma=86400';
}

Optimize Application Server

// Node.js cluster for multi-core utilization
const cluster = require("cluster")
const os = require("os")

if (cluster.isMaster) {
  const cpuCount = os.cpus().length

  for (let i = 0; i < cpuCount; i++) {
    cluster.fork()
  }

  cluster.on("exit", worker => {
    console.log(`Worker ${worker.process.pid} died, restarting...`)
    cluster.fork()
  })
} else {
  require("./app.js") // Your application
}

5. Implement Server Push and Preloading

HTTP/2 Server Push

// Express with HTTP/2 push
app.get("/", (req, res) => {
  // Push critical resources
  if (res.push) {
    res
      .push("/css/main.css", {
        request: { accept: "text/css" },
        response: { "content-type": "text/css" }
      })
      .end(cssContent)

    res
      .push("/js/app.js", {
        request: { accept: "application/javascript" },
        response: { "content-type": "application/javascript" }
      })
      .end(jsContent)
  }

  res.send(htmlContent)
})

Early Hints (103 Status)

// Send early hints while processing
app.get("/page", async (req, res) => {
  // Send 103 Early Hints immediately
  res.writeHead(103, {
    Link: [
      "</css/main.css>; rel=preload; as=style",
      "</js/app.js>; rel=preload; as=script",
      "</api/data>; rel=preload; as=fetch"
    ].join(", ")
  })

  // Process request (database queries, etc.)
  const data = await processRequest(req)

  // Send final response
  res.render("page", data)
})

Common TTFB Mistakes to Avoid

1. Synchronous External API Calls

// Bad: Blocking API call
app.get("/product/:id", async (req, res) => {
  const product = await db.getProduct(req.params.id)
  const reviews = await externalAPI.getReviews(product.id) // Blocks response
  res.json({ product, reviews })
})

// Good: Parallel fetching or async loading
app.get("/product/:id", async (req, res) => {
  const product = await db.getProduct(req.params.id)

  // Send product immediately
  res.json({
    product,
    reviewsUrl: `/api/reviews/${product.id}` // Load async
  })
})

2. Missing Database Indexes

-- Identify missing indexes
SELECT
  schemaname,
  tablename,
  attname,
  n_distinct,
  correlation
FROM pg_stats
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
  AND n_distinct > 100
  AND correlation < 0.1
ORDER BY n_distinct DESC;

3. Not Using Keep-Alive Connections

# Enable keep-alive
upstream backend {
  server backend1.example.com:8080;
  server backend2.example.com:8080;

  keepalive 32;  # Connection pool size
}

location / {
  proxy_pass http://backend;
  proxy_http_version 1.1;
  proxy_set_header Connection "";  # Required for keep-alive
}

4. Inefficient Session Storage

// Bad: Database sessions
app.use(session({
  store: new MySQLStore({...}), // Database hit on every request
}));

// Good: Redis sessions
app.use(session({
  store: new RedisStore({
    client: redisClient,
    ttl: 3600
  }),
}));

// Better: Stateless JWT tokens
app.use(jwt({
  secret: process.env.JWT_SECRET,
  algorithms: ['HS256']
}));

5. No Warmup Strategy

// Implement cache warming
async function warmCache() {
  const criticalRoutes = ["/", "/products", "/api/featured"]

  for (const route of criticalRoutes) {
    await fetch(`http://localhost:3000${route}`)
  }
}

// Run on deploy or periodically
setInterval(warmCache, 3600000) // Every hour

Tools for Measuring TTFB

Command Line Tools

# cURL with timing information
curl -o /dev/null -s -w "TTFB: %{time_starttransfer}\n" https://example.com

# Detailed timing breakdown
curl -o /dev/null -s -w "\
  DNS Lookup: %{time_namelookup}s\n\
  Connect: %{time_connect}s\n\
  TLS Handshake: %{time_appconnect}s\n\
  TTFB: %{time_starttransfer}s\n\
  Total: %{time_total}s\n" \
  https://example.com

Browser DevTools

Chrome DevTools Network Panel shows:

  • DNS lookup time
  • Initial connection
  • SSL negotiation
  • TTFB (Waiting/TTFB)
  • Content download

Online Tools

  • WebPageTest: Detailed waterfall with TTFB breakdown
  • GTmetrix: TTFB by location
  • Pingdom: Global TTFB monitoring
  • Rankwise Speed Test: Competitive TTFB analysis

Monitoring Scripts

// Browser-based TTFB measurement
const measureTTFB = () => {
  const [navigation] = performance.getEntriesByType("navigation")
  if (navigation) {
    const ttfb = navigation.responseStart - navigation.requestStart
    console.log(`TTFB: ${ttfb}ms`)

    // Send to analytics
    if (window.gtag) {
      gtag("event", "timing_complete", {
        name: "TTFB",
        value: Math.round(ttfb)
      })
    }
  }
}

window.addEventListener("load", measureTTFB)

Frequently Asked Questions

What's the difference between TTFB and server response time?

TTFB includes network latency (DNS, connection, SSL) plus server response time. Server response time is just the backend processing duration. TTFB is what users experience; server response time is what you can directly control.

How does HTTPS affect TTFB?

HTTPS adds a TLS handshake, typically 20-200ms depending on distance and cipher suites. Use TLS 1.3 for faster handshakes, enable OCSP stapling, and consider session resumption to minimize this overhead.

Should I prioritize TTFB over other metrics?

Balance is key. A fast TTFB with slow render is still a poor experience. Aim for:

  • TTFB < 600ms
  • FCP < 1.8s
  • LCP < 2.5s Focus on your worst metric first.

How much does hosting location matter?

Immensely for global audiences. A US-hosted site serving Asian users might have 200ms+ network latency alone. Use CDNs or multi-region deployments for global sites. Every 100ms of distance-based latency directly adds to TTFB.

Can service workers improve TTFB?

Yes, dramatically for repeat visits. Service workers can serve cached responses with 0ms TTFB. However, they don't help first visits and add complexity. Use them for frequently accessed resources and offline functionality.

Put GEO into practice

Generate AI-optimized content that gets cited.

Try Rankwise Free
Newsletter

Stay ahead of AI search

Weekly insights on GEO and content optimization.