ulimits and Resource Limits
Why Resource Limits Matter in Production
Linux allows you to limit how much a process can consume:
- Open files
- Number of processes
- Memory
- CPU time
If these limits are too low, services fail silently. If they are too high without control, runaway processes can crash the system. Production stability depends on sane limits.
Check Current Limits
ulimit -a
Common critical values:
- open files (-n)
- max user processes (-u)
- core file size (-c)
The Classic Production Failure: Too Many Open Files
Symptoms:
- New connections fail
- Error: EMFILE
- Service appears alive but not accepting traffic
Check file descriptor usage:
ulimit -n cat /proc/<pid>/limits ls /proc/<pid>/fd | wc -l
Increase File Descriptor Limit (Temporary)
ulimit -n 65535
This only affects the current shell. It does NOT persist across restarts.
Persistent Limits via systemd
For production services, define limits in the unit file:
[Service] LimitNOFILE=65535 LimitNPROC=4096
Then reload:
sudo systemctl daemon-reload sudo systemctl restart myapp
Always prefer systemd limits over shell ulimit hacks.
Global Limits Configuration
System-wide limits can be defined in:
/etc/security/limits.conf /etc/security/limits.d/*.conf
Example:
myapp soft nofile 65535 myapp hard nofile 65535
Process Count Limits
If a service forks too many processes, you may hit:
- fork: Resource temporarily unavailable
- Cannot allocate memory
Check:
ulimit -u cat /proc/<pid>/limits
Core Dumps and Debugging
If core dump size is 0, crashes produce no dump. Enable for debugging:
ulimit -c unlimited
For production, be careful: core dumps can be large and contain secrets.
Hard vs Soft Limits
- Soft limit: current usable limit
- Hard limit: maximum value soft can be raised to
Only privileged users can raise hard limits.
Investigating Limit-Related Incidents
If you suspect limit exhaustion:
cat /proc/<pid>/limits lsof | wc -l journalctl -u myapp -n 100 --no-pager
Look for:
- EMFILE
- Cannot fork
- Too many open files
Common Production Mistakes
- Raising limits blindly without understanding workload
- Setting huge global limits instead of per-service limits
- Ignoring file descriptor leaks
- Using shell ulimit instead of systemd Limit directives
Mental Model
Resource limits are safety rails. Too low = service failure. Too high = runaway damage. Production engineering means setting limits aligned with expected workload.
Production Checklist
- Review LimitNOFILE for high-connection services
- Configure limits in systemd units
- Monitor file descriptor usage
- Check limits during unexplained connection failures
- Align limits with capacity planning