
August 25, 2026
10 min read
Table of Contents
By Kokil Thapa | Last reviewed: August 2026
You need to speed up Ubuntu performance because your production application is responding slowly under load, or you want to maximize the value of your current VPS before upgrading. Default Ubuntu 24.04 LTS installations are tuned for general compatibility, not for serving high-traffic Laravel or WordPress applications. The path to genuine improvement lies in systematic tuning of the kernel, PHP-FPM process manager, web server, and database layer based on actual workload metrics. For teams managing infrastructure alongside development, understanding these layers is as critical as writing clean code; if you are evaluating whether to handle this internally or bring in specialized help, my overview of full-stack developer services in Nepal outlines where infrastructure expertise fits into project delivery.
How Do You Tune Sysctl Kernel Parameters to Speed Up Ubuntu Performance?
The Linux kernel ships with conservative defaults designed to prevent resource exhaustion on minimal hardware. On a production web server running Ubuntu 24.04 LTS with at least 4GB RAM, these defaults often become bottlenecks. Adjusting sysctl parameters allows the kernel to handle more concurrent connections, reduce TCP handshake latency, and manage memory more aggressively for application workloads.
Critical Network Stack Adjustments
Create or edit /etc/sysctl.d/99-web-performance.conf with the following parameters. These values assume a server dedicated to web applications with 8GB+ RAM:
# Increase listen backlog for bursty traffic
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# Enable TCP Fast Open (reduces handshake RTT)
net.ipv4.tcp_fastopen = 3
# Allow TIME_WAIT socket reuse (safe behind Nginx reverse proxy)
net.ipv4.tcp_tw_reuse = 1
# Increase local port range for outbound connections
net.ipv4.ip_local_port_range = 1024 65535
# Optimize TCP buffer sizes for modern networks
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
# Reduce swappiness for application-heavy workloads
vm.swappiness = 10 Apply changes immediately with sudo sysctl --system. The tcp_tw_reuse parameter is safe when your server acts as both client and server behind a reverse proxy, but avoid it on public-facing edge servers without proper SYN cookie protection. On legal-tech portals I've maintained, enabling TCP Fast Open reduced average API response latency by 8–12ms for repeat clients, which compounds significantly across thousands of daily requests.
Memory Management for Application Servers
Setting vm.swappiness=10 tells the kernel to strongly prefer keeping application memory resident rather than swapping to disk. For Laravel applications using Redis or Memcached alongside PHP-FPM, this prevents cache eviction storms during traffic spikes. Monitor actual swap usage with vmstat 1 after applying; if swap activity persists, investigate memory leaks in your application before increasing swappiness back toward the default of 60.
What Are the Best PHP-FPM and OPcache Settings for Ubuntu Web Servers?
PHP-FPM configuration has more direct impact on application throughput than almost any other single setting. Misconfigured process managers either waste RAM on idle workers or drop requests during peaks. Combined with OPcache JIT in PHP 8.4, correct tuning can double effective request capacity on the same hardware.
Calculating pm.max_children Correctly
The most common mistake is copying pm.max_children values from tutorials without accounting for actual per-process memory usage. Measure your application's real footprint first:
- Restart PHP-FPM:
sudo systemctl restart php8.4-fpm - Generate realistic load for 2 minutes using
wrk -t4 -c50 -d120s http://localhost/health - Measure average RSS:
ps --no-headers -o rss -C php-fpm | awk '{sum+=$1} END {print sum/NR/1024 " MB"}'
If average worker RSS is 85MB and you have 8GB RAM allocated to PHP (reserving rest for MySQL/Nginx/OS), calculate: (8192 - 512 reserve) / 85 ≈ 90 workers. Set pm.max_children = 90 in /etc/php/8.4/fpm/pool.d/www.conf.
| Parameter | Dynamic Mode Value | Static Mode Value | Purpose |
|---|---|---|---|
| pm | dynamic | static | Process management strategy |
| pm.max_children | 90 | 90 | Maximum concurrent workers |
| pm.start_servers | 20 | N/A | Workers spawned at startup |
| pm.min_spare_servers | 10 | N/A | Minimum idle workers kept alive |
| pm.max_spare_servers | 40 | N/A | Maximum idle workers before cleanup |
| pm.max_requests | 1000 | 1000 | Recycle worker after N requests (leak prevention) |
Use static mode only if your traffic pattern is consistently high and predictable; dynamic handles variable loads better while avoiding cold-start penalties through min_spare_servers. On e-commerce projects like Nepal Gift Card, switching from poorly estimated dynamic settings to measured static allocation eliminated intermittent 502 errors during flash sales.
OPcache and JIT Configuration for PHP 8.4
Edit /etc/php/8.4/fpm/conf.d/10-opcache.ini with production-optimized values:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=32
opcache.max_accelerated_files=20000
opcache.validate_timestamps=0
opcache.jit=1255
opcache.jit_buffer_size=128M Setting validate_timestamps=0 is mandatory for production performance but requires you to invalidate OPcache after deployments. When using Deployer 7 with zero-downtime releases, add php8.4-fpm reload to your deploy script's post-symlink task to clear stale bytecode. The JIT buffer of 128MB provides substantial gains for CPU-bound Laravel operations like PDF generation or complex Eloquent hydration without consuming excessive shared memory.
How Should You Configure Nginx to Complement Ubuntu Performance Tuning?
Nginx serves as the front-line request handler and static asset server. Its configuration determines how efficiently requests reach PHP-FPM and how quickly static content returns to clients. Proper tuning reduces PHP-FPM load by 30–50% on typical Laravel applications through aggressive caching and compression.
File Descriptor and Connection Limits
Increase system limits before tuning Nginx itself. Add to /etc/security/limits.conf:
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535
root hard nofile 65535 Then in /etc/nginx/nginx.conf, set matching worker limits:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
multi_accept on;
use epoll;
} The epoll event method is default on Linux but explicitly declaring it prevents fallback to less efficient methods during edge-case configurations. Setting worker_connections to 4096 per worker allows handling ~32K concurrent connections on an 8-core server, far exceeding typical PHP-FPM backend capacity.
Static Asset Caching and Compression
Add to your server block for Laravel or WordPress sites:
# Gzip compression for text assets
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
# Browser caching for versioned assets (Laravel Mix/Vite)
location /build/assets/ {
expires max;
add_header Cache-Control "public, immutable";
access_log off;
}
# Open file cache for frequently accessed files
open_file_cache max=10000 inactive=60s;
open_file_cache_valid 120s;
open_file_cache_min_uses 2;
open_file_cache_errors on; The open_file_cache directive caches file descriptors, directory existence checks, and modification times in kernel space. For WordPress sites with thousands of media files or Laravel applications with extensive Blade templates, this eliminates redundant syscalls. On a legal document portal serving many PDF downloads, enabling this reduced p99 latency for static assets from 45ms to 8ms.
Which Database Optimizations Matter Most When Trying to Speed Up Ubuntu Performance?
Database performance often determines overall application responsiveness more than web server tuning. Ubuntu's default MySQL/MariaDB packages ship with minimal buffer allocations suitable for development, not production workloads. PostgreSQL similarly needs explicit tuning for connection pooling and memory utilization.
MySQL/MariaDB Buffer Pool Sizing
For a dedicated database server with 16GB RAM, set innodb_buffer_pool_size = 10G in /etc/mysql/mysql.conf.d/mysqld.cnf. This leaves adequate memory for OS page cache, connection threads, and temporary sort buffers. On shared application/database servers, allocate 50–60% of total RAM to the buffer pool. Monitor hit rate with:
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%'; A healthy production system maintains >99% hit ratio (Innodb_buffer_pool_read_requests / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads)). Values below 95% indicate undersized buffer pools or unindexed queries forcing full table scans. For Laravel applications using Eloquent, also enable the query log temporarily during staging load tests to identify N+1 patterns that no amount of server tuning can fix.
Connection Pooling with ProxySQL or PgBouncer
PHP-FPM opens and closes database connections per request by default. At 90 concurrent workers, this means 90 simultaneous TCP handshakes and authentication rounds. Deploy ProxySQL (MySQL) or PgBouncer (PostgreSQL) as a local connection pooler. Configure Laravel's DB_HOST=127.0.0.1 and DB_PORT=6033 (ProxySQL default) to route through the pooler. This reduces connection establishment overhead by 90% and provides query-level insights for ongoing optimization.
How Do You Measure Real Performance Gains After Tuning Ubuntu?
Benchmarking validates whether tuning efforts actually improve user-perceived performance. Synthetic benchmarks guide initial configuration, but production monitoring confirms sustained gains under real workloads.
Synthetic Benchmarking Protocol
Use wrk for HTTP-level throughput testing against a staging environment identical to production:
# Baseline before changes
wrk -t8 -c100 -d60s --latency https://staging.example.com/api/products > baseline.txt
# After each tuning change, re-run and compare
wrk -t8 -c100 -d60s --latency https://staging.example.com/api/products > optimized.txt Test multiple endpoints representing different workload profiles: static pages, authenticated API calls, database-heavy listings, and file downloads. A single endpoint benchmark misrepresents overall system behavior. Document every change and its measured impact in a runbook; future debugging sessions will thank you.
Production Observability Stack
Install node_exporter and mysqld_exporter for Prometheus metrics. Key dashboards should track: PHP-FPM active/idle workers, OPcache hit rate and memory usage, Nginx request rate and upstream response times, MySQL buffer pool efficiency and slow queries, and system-level CPU steal time (critical on shared VPS). Alert on leading indicators like rising PHP-FPM queue length or declining buffer pool hit ratio before users experience degradation. For teams managing multiple client sites across Nepal and international markets, centralized monitoring prevents tuning regressions during routine maintenance or package upgrades.
Speed Up Ubuntu Performance as Part of Holistic Infrastructure Strategy
Tuning Ubuntu for web application performance yields measurable returns when approached systematically: kernel parameters reduce network latency, PHP-FPM sizing matches compute to workload, OPcache JIT accelerates execution, Nginx offloads static serving, and database buffer pools minimize disk I/O. Each layer reinforces the others; neglecting one undermines gains elsewhere. Start with measurement, apply changes incrementally, and validate continuously. If your team lacks bandwidth to maintain this discipline alongside feature development, consider engaging experienced practitioners who treat infrastructure as integral to application delivery. Reach out via my contact page to discuss your specific performance challenges, or explore related guidance on securing Ubuntu servers in production and application-level caching strategies that complement OS-level tuning.

