worker_connections is not the number of visitors nginx can serve

worker_processes × worker_connections gets quoted as nginx’s capacity, and for a static file server it is roughly right. For anything proxying to PHP-FPM it is out by a factor of two, because a request in flight holds one connection to the client and a second one to the upstream.

worker_processes      auto;    # one per core
worker_rlimit_nofile  8192;    # or the connections cannot be opened at all

events {
    worker_connections 2048;   # per worker, not in total
    multi_accept on;
}

# 4 workers × 2048          = 8192 connections
#   ÷ 2 for the upstream leg = 4096 concurrent proxied requests
#   minus every keepalive connection sitting idle between requests

Keepalive is the second correction: a browser holds its connection open for keepalive_timeout after the response, so connections are occupied by clients who are not asking for anything, and 75 seconds of that is a great many of them on a page with any think time. The limit that bites first is usually not this one at all — every connection is a file descriptor and the default ulimit -n of 1024 sits below any value worth setting here, which is what worker_rlimit_nofile exists to raise. And none of it matters if PHP-FPM has 25 children, because nginx will cheerfully accept 8,000 connections and queue 7,975 of them, converting a refused connection into a slow one. Size the pool first; use this to make sure nginx is not the thing turning people away.