djangoperformancenginxgunicorntime-to-first-byte

Django + Nginx + Gunicorn - Why is my TTFB so high?


This is my first time setting up a web server using nginx/gunicorn so if there is anything obvious on why my TTFB is so high I apoligize.

According to gtmetrix.com my TTFB is 1.4s: enter image description here

In my own testing, my TTFB was around ~1.3s.

I am confused on why it's so high, even though I enabled Brotli, Caching (Static and Media files), Http2, I enabled html minifier, and so I don't know why. My server is a 2GB CPU on Digital Ocean in NYC (close to where I am), so the location is not the problem. I have checked this stack overflow question, but removing the django-htmlmin package still had a high ttfb. My django view on this page is just:

@minified_response
def home(request):
    context = {
        'posts': Post.objects.all()
    }
    return render(request, 'blog/home.html', context)

I think this is a simple query, and I don't expect the TTFB to be so high just for this get query. Is it a problem with my database (right now I am using sqlite)? If you need my any other file or thing to help me debug, just tell me.

Also, according to this article by Cloudflare, my TTFB is high because

At CloudFlare we make extensive use of nginx and while investigating TTFB came across a significant difference in TTFB from nginx when compression is or is not used. Gzip compression of web pages greatly reduces the time it takes a web page to download, but the compression itself has a cost. That cost causes TTFB to be greater even though the complete download is quicker.

So I tried to remove Brotli, but the TTFB was still fairly high, and disabling gzip in the Nginx conf file did not help the TTFB.

Description: Nginx-Gunicorn Server using Digitalocean NYC 2GB CPU On Django (sqlite database)

Edit: I stopped using Cloudflare because there were some issues I was having with it.


Solution

  • Checked this out: https://www.digitalocean.com/community/questions/how-can-i-improve-the-ttfb

    Turns out using fastcgi cache speeds it up so much. My ttfb before was around 1300ms, and now (if there is no updates from the server) the ttfb is around 10~40ms, but if the page is updated from data from the server the ttfb is around 1300~2000ms, but I'm fine with that. Please tell me if there are any problems with using fastcgi_cache, but so far there isn't any problems. My Nginx File:

    # Other Stuff
    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=djangocache:100m inactive=60m;
    fastcgi_cache_key # Your Cache Key (Ex: https://example.com/);
    fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
    # ...
    server {
        # more stuff
        location / {
              fastcgi_cache_valid 301 30d;
              fastcgi_cache djangocache;
              fastcgi_cache_valid 200 30m;
              fastcgi_cache_methods GET HEAD;
              fastcgi_cache_use_stale updating;
              fastcgi_cache_background_update on;
              fastcgi_pass # Your server name;
              fastcgi_param PATH_INFO $fastcgi_script_name;
              fastcgi_param REQUEST_METHOD $request_method;
              fastcgi_param CONTENT_TYPE $content_type;
              fastcgi_param CONTENT_LENGTH $content_length;
              add_header X-Fastcgi-Cache $upstream_cache_status;
              # ...
        }
        # ...
    }
    

    If you find any problems with my code above please tell me, I'm still experimenting with using fastcgi cache.

    EDIT 2: Be careful of the modules you {% load %} in your template because some of them can slow your ttfb so much. I was using profanity check, and I removed it from my templates which reduced the ttfb by about 750ms. The biggest fix for ttfb (in my case at least) was to check third part packages and what you load in your templates.

    EDIT 3: Another big thing that helped my TTFB was removing the package django-htmlmin. Removing it made my TTFB go down by 300ms, so now my ttfb was 10~40ms (no server update) or 200~500ms (server update) which I am happy with.