☕ Kev's Tech Notes

Page 2 — Nginx, Reverse Proxy & The Stuff That Breaks At 2am

Page 2 — Full Article
NginxNov 8, 2026• 7 min read

I Thought My Nginx Config Was Fine. Then Black Friday Hit.

Alright, real story. No BS.

We had a client — small e-commerce shop, nothing crazy, like 2k visitors a day normally. I set up their Nginx, Cloudflare in front, everything looked good. I even tested with Apache Bench. 500 concurrent users? No problem. I was feeling good about myself.

Then Black Friday. 8am. Traffic went from 2k to like 18k in 20 minutes. And the site just... died. 502s everywhere. CPU was only at 40%. Memory was fine. I was like, what the hell?

What was actually wrong

It wasn't the backend. It wasn't Cloudflare. It was this:

# nginx.conf - the default I left in
events {
  worker_connections 512;
}

512. That's the default. With 4 workers, that's only ~2k concurrent connections. And with keep-alive + websockets + images, you burn through that super fast.

I bumped it to 4096, reloaded, and boom — site came back in like 10 seconds. I felt like an idiot, but also relieved.

My current production template

This is what I actually use now on every new server. Copy it if you want:

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
  worker_connections 4096;
  use epoll;
  multi_accept on;
}

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  client_max_body_size 20M;

  # Gzip - don't skip this
  gzip on;
  gzip_vary on;
  gzip_min_length 1024;
  gzip_types text/plain text/css application/json application/javascript text/xml;

  # Rate limit - saves you from bots
  limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

  include /etc/nginx/sites-enabled/*;
}

3 things I check first now

1. worker_connections — If it's still 512, fix it.
2. client_max_body_size — Default is 1M. Your users will try to upload a 5MB image and get a 413. Set it to 20M.
3. proxy_read_timeout — If your backend is slow, default 60s will kill long requests. I use 120s for API servers.

Anyway, lesson learned. Don't trust defaults. Test with real traffic, not just ab -n 1000.

— Kev

← Back to Home | Next: BBR Test →