Question

How can I improve the TTFB?

  • Posted July 7, 2014

Heya!

I’m running Nginx on a 512MB Debian 7 Droplet in Amsterdam. The time-to-first-byte is between 400-500ms for static files/pages and funnily enough for a WordPress installation as well.

I’d like to get that down to 100ms, maybe 200ms. Is that a good goal, or are 500ms already good? How do I get that number down without using Varnish? Can I tweak Nginx some way, or would a hardware upgrade change it?

Cheers, Till

Subscribe
Share

Submit an answer
You can type!ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)

I was having a very large (500-1500ms) TTFB with nginx, wordpress, PHP 7 (php-fpm), and SSL. This was not the case on non-PHP sites, so it was safe to assume that PHP and SSL each could use some tuning.

2 things got me great improvement (<100ms TTFB):

  1. Enable http2 in all of my SSL server blocks (needs nginx 1.9.5+)

    server {
      listen 443 ssl http2;
      #rest of your config here
    }
    
  2. Set up fastcgi_cache

    In /etc/nginx/nginx.conf:

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    

    In your server’s .conf file likely in /etc/nginx/conf.d/ modify the php handling block

    location ~ [^/]\.php(/|$) {
    fastcgi_cache phpcache; # The name of the cache key-zone to use
    fastcgi_cache_valid 200 30m; # What to cache: 'Code 200' responses, for half an hour
    fastcgi_cache_methods GET HEAD; # What to cache: only GET and HEAD requests (not POST)
    add_header X-Fastcgi-Cache $upstream_cache_status; # Add header so we can see if the cache hits or misses
    
    # the rest of your existing stuff to handle PHP files here
    }
    
  3. restart nginx sudo nginx -s reload

This reduced my TTFB to under 100ms consistently, and everything seems to be pretty happy :)