Server Ulimits In hosting, you specifically control how many files and processes your services are allowed to keep open at the same time, and thus decide on latency, error messages and availability. I will show you step by step how to measure, adjust and monitor file and process limits so that web servers run smoothly even under load. reliable work.
Key points
- Soft/Hard Understanding limits and setting them appropriately
- nofile (files) and nproc (processes) targeted increase
- PHP-FPM and configure queues correctly
- Monitoring and recognize bottlenecks
- Security with sensible upper limits
Ulimits briefly explained: Soft vs. hard
I use Ulimits in order to obtain reliable data per user or process. Boundaries for resources. Soft limits are the current, changeable limits, which I can raise up to the hard limit if the application needs more leeway in the short term. The hard limits represent the absolute upper limit and prevent uncontrolled growth of individual services, which would affect the entire host. By default, the ulimit command refers to the hard limit without a switch, which makes adjustments easier for administrators with rights. This prevents a single script from overloading the server with too many files or processes. overloaded.
I always differentiate between the most important parameters such as nofile (open files), nproc (processes/threads), fsize (file size), stack (stack size) and cpu (CPU time). Web stacks with PHP, database and cache components in particular often require significantly more open descriptors than the minimum default values. Without the correct limits, messages such as „too many open files“, long response times or timeouts for requests accumulate. I measure actual usage first, increase limits gradually and then check latency, error counters and throughput. This is how I ensure consistent performance under high access Response times.
Why limits are crucial in hosting
Hosting environments share hardware resources, so I use appropriate limits to prevent unfair resource access by individual accounts or services and keep the Performance stable. In entry-level plans, for example, simultaneous CGI/PHP processes and the CPU time per user are limited so that a faulty cron job does not slow down the entire host. In higher plans, more processes can run and more RAM can be used, which benefits demanding applications such as stores. I always evaluate the number of processes, RAM per process and CPU time together so that no artificial bottlenecks remain. I provide a detailed practical framework for fair resources in the article on Shared hosting limits, which explains the connections compactly organizes.
The file descriptor limit is critical because every open file, every socket and every pipe binds a descriptor. Default values of 1024 are often too small for modern web applications, especially when there are many simultaneous connections. I therefore first read real peaks from logs and tools before increasing values so that I know the effects on kernel tables and memory pressure. In this way, I increase throughput without risking the security and responsiveness of the host. If you understand the principle, you avoid random failures due to too tight Barriers.
The most important parameters in everyday life: nofile, nproc and co.
For web-related workloads nofile at the top because HTTP connections, upstream sockets and database connections consume massive amounts of descriptors. I plan buffers for peak loads, for example two to four times the typical peak, so that short traffic waves do not immediately lead to errors. For worker-based services, I scale nofile in parallel with the number of workers and their maximum connections. If a CDN, reverse proxy or messaging layer is added, the demand increases again, which I take into account in the calculation. Only with a clean buffer do sporadic „open file“ errors disappear and the Error rate decreases.
At nproc-limit, I consider processes and threads together because some runtimes use thread pools that count against the upper limit. I check spawn strategies of web servers, app servers and the database so that the upper limit does not take effect unnoticed and block new workers. If the nproc values are too low, this often manifests itself as sluggish service launches or queues that do not process. I increase the limit to match the CPU core count, the IO load and the architecture of the application. This keeps the spawn process predictable and prevents rigid Blockages.
Check Ulimits: how I read the reality
I start every optimization with visibility, because without numbers, measures remain blind. The command ulimit -a shows me the current limits of the shell session and thus provides the basis for comparisons with service configurations. I check nofile and nproc separately, because these values are the first to reach their limits in hosting. I also use lsof, ss or netstat to count open files and sockets per process. Only when I know the peak under production load do I plan buffers and include them in the Limit values in.
# All limits of a session
ulimit -a
# File descriptors (soft/hard)
ulimit -n
ulimit -Hn
# Processes/threads per user
ulimit -u
ulimit -Hu
For services that systemd starts, I don't just look at my interactive shell, because systemd sets its own Limits. I therefore compare the effective values of a running process via /proc//limits in order to expose inconsistencies between the shell and the service. Deviations indicate missing settings in unit files, which I then add directly. This comparison saves me a lot of puzzling over why an app is not allowed to open additional files despite higher shell limits. In this way, I can quickly find configuration gaps and ensure consistent Frame.
Temporarily customize: quick tests in running sessions
Before I set limits permanently, I specifically test higher limits in a shell. Values. This allows me to see without restarting whether the application is accepting more connections as expected or whether the latency is decreasing. Increased values apply in this session until I close it or restart the service. I document the effect on syslog, error logs and metrics so that later permanent adjustments are well-founded. Short tests save me large rollbacks and provide reliable results. Receipts.
# Temporary in the current shell
ulimit -n 65536 # Raise file descriptors
ulimit -u 4096 # Increase process/thread limit
# Explicitly check/adjust hard limits (root)
ulimit -Hn 131072
ulimit -Hu 8192
I carry out such tests at times of planned load peaks in order to determine real effects. See. If the „too many open files“ errors stop and the number of requests per second increases, I record the measured values. If the impact remains low, I look for parallel brakes such as socket backlogs that are too narrow, worker limits in the web server or database connection pools. Only when the entire chain scales does a higher ulimit server pay off cleanly. In this way, I prevent partial optimizations that ultimately have no noticeable effect. Improvement bring
Permanently configure: limits.conf and systemd
For permanent values, I edit /etc/security/limits.conf and add user- or service-specific Lines. I differentiate between soft and hard limits so that applications remain highly elastic in the short term but still have a clear upper edge. For systemd services, I also set LimitNOFILE and LimitNPROC, because otherwise unit files override shell changes. After customizing, I reload systemd and restart the affected services so that the new limits take effect. The restart is important, otherwise processes remain in old Frame values.
# /etc/security/limits.conf (example)
* soft nofile 65536
* hard nofile 131072
www-data soft nproc 4096
www-data hard nproc 8192
# systemd unit (e.g. /etc/systemd/system/nginx.service.d/limits.conf)
[Service]
LimitNOFILE=65536
LimitNPROC=4096
# Activate changes
systemctl daemon-reload
systemctl restart nginx
| Context | Place | Validity | Typical |
|---|---|---|---|
| Interactive session | ulimit in Shell | Only current shell/childs | Quick tests |
| System-wide user | /etc/security/limits.conf | Login/PAM-based processes | Durable base |
| Services (systemd) | Unit file: LimitNOFILE/LimitNPROC | Only affected service | Clear service boundaries |
Correctly classify system-wide kernel limits
In addition to process and user-related ulimits, there are system-wide caps that I always check. Even a high nofile is useless if the kernel keeps the global file descriptor table short. I therefore check fs.file-max (total possible open FDs) and fs.nr_open (maximum FDs allowed per process at kernel level). If these values do not match, I reach the limits early on despite raising the ulimits.
# Check system-wide limits
cat /proc/sys/fs/file-max
cat /proc/sys/fs/nr_open
cat /proc/sys/fs/file-nr # In-Use, Free, Max
# Temporarily raise (until reboot)
sysctl fs.file-max=2097152
# Permanent (in /etc/sysctl.d/99-ulimits.conf)
fs.file-max = 2097152
I note the cascade: Process limit (RLIMIT_NOFILE) ≤ fs.nr_open ≤ fs.file-max (global). If nofile is set via fs.nr_open, the kernel silently ignores the request. I scale globally accordingly, then per service. For accept backlogs, I additionally scale net.core.somaxconn and the backlog parameters of the respective services, otherwise incoming connections continue to starve in the queue.
systemd units: TasksMax, PIDsMax and DefaultLimits
On modern distributions, systemd limits not only descriptors, but also the number of tasks (processes/threads) per service via TasksMax. I set appropriate values for high concurrency setups or use „infinity“ when transferring control to nproc. For user services [email protected] respectively system.conf with DefaultLimit* switches to raise baseline values consistently.
# Service drop-in for more tasks and FD
mkdir -p /etc/systemd/system/php-fpm.service.d
cat < /etc/systemd/system/php-fpm.service.d/limits.conf
[Service]
LimitNOFILE=131072
LimitNPROC=8192
TasksMax=16384
EOF
systemctl daemon-reload
systemctl restart php-fpm
# System-wide defaults (use carefully)
# /etc/systemd/system.conf
DefaultLimitNOFILE=65536
DefaultLimitNPROC=4096
DefaultTasksMax=8192
Important: sudo, su and SSH logins inherit limits differently. For PAM-based logins, /etc/security/limits.conf takes effect, but often not for non-login shells or cronjobs. I therefore always test the complete path via which my service starts so that no silent deviations remain.
Scaling web servers together with Ulimits
With NGINX, I link worker_processes, worker_connections and worker_rlimit_nofile with the system-wide limits. Rule of thumb: Maximum simultaneous connections ≈ worker_processes × worker_connections, plus reserve for upstreams, logs and internal pipes. Without an increased worker_rlimit_nofile, NGINX runs early in EMFILE despite high ulimits.
# NGINX example (excerpt)
worker_processes auto;
events {
worker_connections 40960;
multi_accept on;
use epoll;
}
worker_rlimit_nofile 131072;
With Apache (MPM event) I pay attention to ServerLimit, ThreadsPerChild and MaxRequestWorkers. If the total number of possible connections increases, nofile must grow in parallel. Otherwise, queues fill up even though the CPU and RAM still have room to spare. In addition, I adjust the listen backlogs (e.g. for NGINX: listen ... backlog=...) and Kernel-somaxconn so that new acceptances are not dropped.
Databases and caches: budget open files correctly
Databases and caches have their own adjusting screws: Use MySQL/MariaDB open_files_limit and connection parameters, PostgreSQL benefits from connection pooling beforehand, while Redis translates the number of clients directly into open FDs. I make sure that the respective services hit a nofile that is above their internal maximum values. Otherwise, startup or load peaks will fail even though the application layer has been scaled.
A typical pattern: PHP-FPM increases parallelism, but the DB server remains on old FD limits and connection caps. I measure open handles per component and design the buffers additively. This prevents a downstream service from neutering the overall performance.
Containers and orchestration: Ulimits in the Docker/Kubernetes context
Ulimits work in containers regardless of the host login context. I set them explicitly at startup or in the orchestration and also observe cgroups limits (PIDs, memory). In the Docker environment, I define nofile/nproc and optionally a PIDs limit. Kubernetes encapsulates this via SecurityContext and RuntimeClass-specific options; depending on the environment, Ulimits must be set via Container Runtime.
# Docker local
docker run --ulimit nofile=131072:131072 \
--ulimit nproc=8192:8192 \
--pids-limit 20000 \
--name webapp -p 80:80 myimage:latest
# Docker Compose (excerpt)
services:
app:
image: myimage:latest
ulimits:
nofile:
soft: 65536
hard: 131072
nproc: 8192
pids_limit: 20000
I always verify limits in the container via /proc/self/limits and make sure that host adjustments such as limits.conf do not automatically diffuse into container processes. I create transparency with clear, version-controlled deploy parameters for each service.
Troubleshooting in practice: EMFILE, EAGAIN and slow spawns
For reproducible analyses, I use strace and search for EMFILE („Too many open files“) or EAGAIN („Resource temporarily unavailable“) for accept(), open(), pipe() or clone(). I regularly count FDs per process and compare them with the set limits. Leaks in file handles (e.g. forgotten close() calls) are detected more quickly this way.
# Determine open FDs per process
ls -l /proc//fd | wc -l
# System-wide usage at a glance
cat /proc/sys/fs/file-nr
# trim strace for FD errors
strace -fp -e trace=desc,process,network 2>&1 | grep -E 'EMFILE|EAGAIN'
Startup problems caused by nproc limits that are too tight reveal themselves through slow startup, „can't fork“ messages or incomplete worker pools. I correlate these events with spawn strategies (pre-fork, dynamic, on-demand) so that adjustments not only alleviate symptoms but also support the architecture.
Automation, tests and rollback
I keep limit changes reproducible: I maintain drop-ins for systemd, sysctl.d files and service templates declaratively. Every change receives a ticket, measured values before/after and a clear rollback. In staging, I simulate utilization with tools such as wrk, vegeta or k6 and pay attention to P95/P99 latencies, error rates and queue times. Only reliable results justify an expansion into production.
# Create drop-in scaffolding for multiple services
for s in nginx php-fpm redis; do
mkdir -p /etc/systemd/system/$s.service.d
cat < /etc/systemd/system/$s.service.d/limits.conf
[Service]
LimitNOFILE=65536
LimitNPROC=4096
TasksMax=8192
EOF
done
systemctl daemon-reload
systemctl restart nginx php-fpm redis
For campaigns, I switch limits up in a controlled manner, note start/end times and compare them with traffic curves. After the peak, I reintroduce the more conservative values to minimize the attack surface and free up unused kernel resources.
Risk of confusion: Ulimits vs. watcher/kernel parameters
Not every „too many files“ error is caused by nofile. File system watchers (inotify) have their own limits (e.g. max_user_watches), which are quickly reached with many small files or development stacks. Also vm.max_map_count (e.g. for search engines) or net.ip_local_port_range (ephemeral ports) can act as limiting factors. I check such parameters separately so that I don't turn the wrong knob.
Dimension PHP-FPM correctly: Processes, queues, limits
In PHP-FPM, I coordinate pm.max_children, pm.max_requests and the ulimit limits so that process start, memory and Connections remain balanced. When FPM reaches its upper limit, requests end up in a queue; this is intentional, but only makes sense if the web server handles timeouts and backoff properly. I measure the average execution time and use this to derive a viable process number that does not overload the CPU and RAM. I also adjust the file descriptor limit so that parallel upstream connections and log writers have enough leeway. If you want to delve deeper, you will find practical adjustment screws for PHP-FPM processes and determines the best Balance.
I also check how many database connections per FPM worker remain open at the same time, so that connection pools do not become the bottleneck become. Too large a number of workers increases RAM pressure and context switches, too small stagnates the throughput. That's why I scale in stages, observe latency P50/P95 and failures, and adjust in small steps. Only when queue times, CPU load and error rates are in balance do I fix the values permanently. This way, the stack runs more predictably and remains stable under load responsive.
Monitoring and capacity planning
I back up every step with measurement data, otherwise changes to limits only have a felt. Metrics such as open files per process, running and waiting requests, CPU seconds per worker and RSS memory help me to categorize them. Logs show me when the hard limits take effect and whether services are refusing connections as a result. Dashboards with P95/P99 latencies reveal bottlenecks that conceal average values. From all this, I derive a practicable process limit hosting that smoothes the workload and reduces queues. shortened.
I always keep reserved headroom free so that short peaks don't cause any interference. produce. Anyone heading for monthly or campaign peaks raises limits one to two weeks in advance and checks real traffic tests. I then reactivate tighter limits to keep resources and attack surfaces small. This rhythm protects the platform economically and reduces the risk of disruption at the same time. Planning pays off several times over here, because proactive steps can reduce service windows and Uptime secure
Inodes and number of files: quiet limits with a big effect
In addition to nofile, the file system limits the number of Inodes and therefore the possible number of files, regardless of the memory used. Web projects with lots of small cache files or session files quickly hit a snag here. I check df -i, clean up old artifacts, rotational remnants and temp directories and adjust the structure of the file system if necessary. Consolidating CMS caches or placing them in-memory relieves the load on inodes and IO printing at the same time. I include details, background information and strategies in my guide to Understanding inodes who has developed the topic for hosting practices unlocks.
If inodes are scarce, a higher file descriptor limit alone is useful nothing. I therefore ensure clear log rotation, limit debug verbosity and move rarely used artifacts to archive storage. Build pipelines should also clean up artifacts so that deployments do not gradually eat up the inode reserves. Such hygiene keeps limits stable in the long term and saves a lot of time when troubleshooting. A clean view of inodes prevents unexpected Downtimes.
Targeted rectification of typical error messages
The message „too many open files“ almost always indicates that there are not enough files. nofile. I increase the limit temporarily in the shell, confirm the effect and then adjust the values in limits.conf and systemd. If „resource temporarily unavailable“ appears when spawning, it is often due to the nproc limit, which I increase to match the worker architecture. If PHP scripts seem to hang, I also check memory_limit, max_execution_time and the CPU seconds granted by the hosting setup for CGI/FPM. I eliminate bottlenecks along the chain and prevent a switch in one place from only generating new Brakes generated at another position.
If these errors occur sporadically, I work with metric correlations to determine the time and load situation. catch. Peaks in simultaneous connections, increased backend errors or long DNS lookups provide good indications. I then check the limits of the affected services separately to identify effective values. If the configuration is correct but the errors remain, I look for leaks in file handles, defective watchers or unnecessary open sockets. Step-by-step containment saves time and reduces the Risk renewed failures.
A smart balance between performance and safety
I never increase limits without limits, because openings that are too wide are open to attack. enlarge. Brute force or DoS scenarios benefit from limits that are too high if no other controls are in place. That's why I combine limits with rate limiting, backoff strategies and clear timeouts in the web server and upstream. I set hard upper limits so that legitimate peaks can happen but abuse cannot escalate. This is how I ensure availability without Control to lose.
In everyday life, a graduated concept pays off: some headroom for peaks, measurable effect, and regular Reviews. If you know deployments, traffic campaigns and seasonal loads, you can plan limits proactively. I document every change with the date, reason and measured values so that later analyses are not left in the dark. This catalog speeds up future decisions and prevents duplication of work. Performance and security benefit because decisions are based on Data based.
Evaluating hosting packages: what do I look out for?
I check hosting offers not only for CPU and RAM, but explicitly for Ulimits for processes, descriptors and CPU seconds. Specific details on nproc, nofile and, if applicable, inode quotas help me to correctly estimate capacity. For stores and APIs, I require transparent commitments for PHP FPM processes, CPU budgets and limit increases on request. VPS or dedicated environments give me sovereignty, but sensible default values for operation also count here. Clear figures prevent disappointments and keep migrations on track straightforward.
| Plan | Process limit (nproc) | Files (nofile) | RAM/Process | CPU time | Suitability |
|---|---|---|---|---|---|
| Beginner | 32-64 | 4096-8192 | 256–512 MB | 5-600 s | Small sites |
| Business | 64-128 | 16384-65536 | 512–1024 MB | 600-3600 s | Stores, APIs |
| VPS/Dedicated | Configurable | Configurable | As required | As required | High load |
Briefly summarized
I measure real usage first, then I lift Boundaries in stages and check the effect on latency, error rate and throughput. The core switches are nofile for files/sockets and nproc for processes/threads, supplemented by fsize, stack and cpu. I set permanent values consistently in limits.conf and in systemd units so that services have identical framework conditions. For PHP-FPM, I coordinate process numbers, memory and queues closely with the file descriptor limit. Monitoring, inode hygiene and sensible upper limits keep hosting setups under load Reliable and responsive.


