Tuning Open File Limits on Linux
Introduction¶
Too many open files (EMFILE) on a busy web server, database, or proxy is
almost always a limit that's set too low for the workload — not a leak. The
confusion is that there are four separate limits and raising the wrong one does
nothing.
The four limits¶
| Limit | Scope | Where set |
|---|---|---|
fs.file-max |
System-wide total | sysctl / /etc/sysctl.d/ |
fs.nr_open |
Per-process ceiling (upper bound for ulimit -n) |
sysctl |
RLIMIT_NOFILE soft |
Per-process, the actual enforced value | ulimit -n, PAM, systemd |
RLIMIT_NOFILE hard |
Per-process, max the soft can be raised to without root | same |
Also relevant: net.core.somaxconn (listen backlog) and per-user process
counts — different limits, similar symptoms.
Check what a running process actually has¶
# The limits the process is running under
cat /proc/<pid>/limits | grep "open files"
# How many it currently has open
ls /proc/<pid>/fd | wc -l
# System-wide
cat /proc/sys/fs/file-nr # allocated unused max
sysctl fs.file-max fs.nr_open
If /proc/<pid>/limits says 1024 and the process needs 50k, that's your
limit — regardless of fs.file-max.
Raising it — the right layer¶
For a systemd service (the common case)¶
sudo systemctl edit myapp.service
[Service]
LimitNOFILE=262144
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
cat /proc/$(pgrep -f myapp)/limits | grep "open files"
systemd services do NOT read /etc/security/limits.conf — that's PAM, and
systemd doesn't go through PAM for services. This trips people up constantly.
For interactive / login sessions¶
/etc/security/limits.d/90-nofile.conf:
* soft nofile 65536
* hard nofile 262144
root soft nofile 65536
root hard nofile 262144
Requires pam_limits.so in the PAM stack (default) and a fresh login. Verify
with ulimit -n (soft) and ulimit -Hn (hard).
System-wide ceiling¶
Only if fs.file-max is genuinely the bottleneck (millions of fds across all
processes):
# /etc/sysctl.d/99-files.conf
fs.file-max = 2097152
fs.nr_open = 1048576 # raise if you want a per-process ulimit above ~1M
sudo sysctl --system
Verification and troubleshooting¶
# Reproduce and watch fd count climb
watch -n1 'ls /proc/$(pgrep -f myapp)/fd | wc -l'
- Raised
limits.confbut the service still hits 1024 — it's a systemd service; useLimitNOFILE=in a drop-in, not PAM limits. - Set
LimitNOFILE=but/proc/<pid>/limitsunchanged — nodaemon-reload, or the service was reloaded (not restarted — limits apply at process start), or a wrapper/suinExecStartreset them. - fd count keeps climbing without bound — a genuine leak.
ls -l /proc/<pid>/fdand look for hundreds of the same socket or file.lsof -p <pid> | sort -k9 | uniq -c -f8 | sort -rn. ulimit -n unlimitedrefused — you can't; there's a hard cap atfs.nr_open. Raise that sysctl if you truly need >1M.- Container hits the limit — the container's limits come from the runtime
(
docker run --ulimit nofile=65536:65536, orLimitNOFILEon thecontainerd/dockerservice, or the Kubernetes node). The image's ownlimits.confis irrelevant for the main process. accept: too many open filesbut fd count is well under the limit — could befs.file-max(system total) reached by other processes, or you're out of ephemeral ports / conntrack entries, which present similarly.
Related tools and reading¶
- On-site: Linux commands reference, Port Checker.
- Related posts: Finding what is using a port, Understanding Linux load average.
Stuck on something this site can't fix?Reach out to Prabath directly on LinkedIn.More in Linux & Sysadmin
resolv.conf and systemd-resolved
On modern distros /etc/resolv.conf points at a stub resolver managed by systemd-resolved. Editing it directly usually does nothing — here's the real model.
October 24, 2026ss and conntrack for Connection Debugging
ss shows you every socket and its send/receive queues; conntrack shows what the firewall is tracking. Together they explain most 'connection refused' and 'no buffer space' problems.
October 24, 2026How systemd Unit Files Work
A practical walk through writing your first systemd service: the three sections, the dependency model, and how to debug one that won't start.
October 24, 2026