• Skip to secondary menu
  • Skip to main content
  • Skip to primary sidebar
  • Home
  • Projects
  • Products
  • Themes
  • Tools
  • Request for Quote

Vengala Vinay

Having 12+ Years of Experience in Software Development

  • Home
  • WordPress
  • PHP
    • Codeigniter
  • Django
  • Magento
  • Selenium
  • Server
Home » The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MySQL on OVH for Laravel

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MySQL on OVH for Laravel

Nginx Configuration for Laravel on OVH

Optimizing Nginx is crucial for serving Laravel applications efficiently, especially on OVH infrastructure where resource allocation and network latency can be factors. We’ll focus on key directives that impact performance and security.

Worker Processes and Connections

The `worker_processes` directive controls how many worker processes Nginx spawns. Setting this to `auto` is generally recommended, allowing Nginx to determine the optimal number based on available CPU cores. The `worker_connections` directive sets the maximum number of simultaneous connections that each worker process can handle. A common starting point is 1024, but this can be increased based on anticipated traffic load.

Edit your main Nginx configuration file (often `/etc/nginx/nginx.conf`):

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 4096; # Increased from 1024
}

Gzip Compression

Enabling Gzip compression significantly reduces the size of text-based assets (HTML, CSS, JS, JSON), leading to faster load times. Ensure it’s enabled and configured appropriately for common file types.

http {
    # ... other http directives ...

    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6; # Compression level (1-9)
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    # ... rest of http configuration ...
}

Caching and Keep-Alive

Leveraging browser caching and HTTP keep-alive can reduce server load and improve client-side performance. Set appropriate `Cache-Control` headers for static assets and configure `keepalive_timeout`.

server {
    # ... other server directives ...

    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    keepalive_timeout 65; # Default is 65, adjust if needed
    keepalive_requests 1000; # Default is 1000, adjust if needed

    # ... rest of server configuration ...
}

PHP-FPM Configuration for Laravel

When using PHP-FPM with Nginx for Laravel, tuning the PHP-FPM pool is critical. The `pm` (process manager) setting determines how PHP processes are managed. `dynamic` is a good balance for most applications, allowing the number of child processes to scale based on demand.

Process Manager Settings (pm)

Key directives for `pm` are `pm.max_children`, `pm.start_servers`, `pm.min_spare_servers`, and `pm.max_spare_servers`. These control the number of PHP worker processes. Setting these too high can exhaust server memory; too low can lead to request queuing.

Locate your PHP-FPM pool configuration file (e.g., `/etc/php/8.1/fpm/pool.d/www.conf` or similar, depending on your PHP version and OS distribution):

; For dynamic process management
pm = dynamic
pm.max_children = 100       ; Adjust based on available RAM. (e.g., 100 processes * 20MB/process = 2GB RAM)
pm.start_servers = 10       ; Initial number of children to start
pm.min_spare_servers = 5    ; Minimum number of idle processes
pm.max_spare_servers = 20   ; Maximum number of idle processes

; For static process management (if you have predictable load and ample RAM)
; pm = static
; pm.max_children = 150

; Other important settings
request_terminate_timeout = 60s ; Timeout for script execution
pm.process_idle_timeout = 10s   ; Timeout for idle processes to be killed

Tuning `pm.max_children`: A common rule of thumb is to calculate the maximum memory a single PHP-FPM process consumes (e.g., 20-30MB for a lean Laravel app, potentially more with heavy packages) and divide your total available RAM by this figure. Subtract a buffer for the OS and other services (like Nginx and MySQL). For example, on a 4GB RAM server, if each PHP process uses 30MB, `max_children` could be around `(4096MB – 1024MB buffer) / 30MB ≈ 102`. Start conservatively and monitor.

OPcache Configuration

OPcache is essential for PHP performance. It caches precompiled script bytecode in shared memory, eliminating the need to load and parse PHP scripts on every request. Ensure it’s enabled and tuned.

; In your php.ini file (e.g., /etc/php/8.1/fpm/php.ini)
opcache.enable=1
opcache.enable_cli=1 ; Important for Artisan commands
opcache.memory_consumption=128 ; MB, adjust based on your application's size and number of files
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000 ; Number of files to cache. Increase if you have many PHP files.
opcache.revalidate_freq=60 ; Check for file updates every 60 seconds (0 to disable, not recommended for production)
opcache.validate_timestamps=1 ; Set to 0 in production for maximum performance if you have a deployment process that clears opcache
opcache.save_comments=1
opcache.load_comments=1
opcache.enable_file_override=0
opcache.fast_shutdown=0

After making changes to PHP-FPM or OPcache, you must restart the respective services:

sudo systemctl restart php8.1-fpm # Adjust version as needed
sudo systemctl restart nginx

MySQL Tuning for Laravel Applications

Database performance is often a bottleneck. Tuning MySQL, particularly its buffer pool and connection handling, can yield significant improvements for Laravel applications.

InnoDB Buffer Pool

The `innodb_buffer_pool_size` is the most critical MySQL setting. It caches InnoDB data and indexes. A common recommendation is to set it to 50-70% of your available RAM on a dedicated database server. On a shared server, be more conservative.

; In your my.cnf or my.ini file (e.g., /etc/mysql/mysql.conf.d/mysqld.cnf)
[mysqld]
innodb_buffer_pool_size = 2G ; Example for a server with 4GB RAM, adjust accordingly
innodb_log_file_size = 256M  ; Recommended to be at least 25% of innodb_buffer_pool_size
innodb_flush_log_at_trx_commit = 1 ; For ACID compliance, set to 2 for better performance with slight risk on OS crash

Connection Handling

`max_connections` determines the maximum number of simultaneous client connections. Laravel applications can sometimes open more connections than expected due to ORM behavior or middleware. Monitor your actual usage and set this appropriately, but avoid setting it excessively high, as each connection consumes memory.

; In your my.cnf or my.ini file
[mysqld]
max_connections = 200 ; Adjust based on application needs and server resources
thread_cache_size = 16 ; Cache threads for reuse

Query Cache (Deprecated/Removed)

Note: The MySQL query cache has been deprecated and removed in MySQL 8.0. If you are using an older version, it might be beneficial, but it often causes more contention than it solves in high-write environments. For modern setups, focus on other optimizations.

Other MySQL Tuning Parameters

Consider these for further tuning:

  • `innodb_flush_method`: `O_DIRECT` can bypass OS caching and improve performance on some systems.
  • `innodb_io_capacity`: Tune based on your disk I/O capabilities.
  • `tmp_table_size` and `max_heap_table_size`: Control the size of in-memory temporary tables.
; In your my.cnf or my.ini file
[mysqld]
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000 ; Adjust based on your storage (e.g., SSDs can handle higher values)
tmp_table_size = 64M
max_heap_table_size = 64M

After modifying MySQL configuration, restart the MySQL service:

sudo systemctl restart mysql # Or mysqld, depending on your OS

Laravel Specific Optimizations

Beyond infrastructure, Laravel itself offers tuning opportunities.

Configuration Caching

Cache your Laravel configuration to reduce the overhead of reading configuration files on each request.

php artisan config:cache

Important: If you run this command, ensure your configuration files are stable. Changes to configuration will not be reflected until you clear the cache (`php artisan config:clear`) and re-cache.

Route Caching

Similar to configuration, route definitions can be cached.

php artisan route:cache

Important: This is not suitable if you use route closures or dynamic route definitions. Clear with `php artisan route:clear`.

View Caching

Blade views are compiled and cached by default. Ensure this is enabled.

php artisan view:cache

Clear with `php artisan view:clear`.

Composer Autoloader Optimization

Optimize the Composer autoloader for faster class loading.

composer dump-autoload --optimize --no-dev

The `–no-dev` flag is crucial for production to exclude development dependencies.

Gunicorn/PHP-FPM Process Management (if using Gunicorn)

If your Laravel application is served via Gunicorn (often in a Python/WSGI context, though less common for pure PHP Laravel), the process management of Gunicorn itself needs tuning. However, for typical Laravel deployments on OVH using Nginx + PHP-FPM, the PHP-FPM tuning above is the primary focus. If you *are* using Gunicorn to proxy to PHP-FPM (e.g., via `php-fpm-socket`), the Gunicorn worker count should be set based on available CPU cores, and the PHP-FPM pool should be configured as detailed previously.

Monitoring and Iteration

Tuning is an iterative process. Continuously monitor your server’s performance using tools like:

  • htop / top for CPU and memory usage.
  • iotop for disk I/O.
  • netstat / ss for network connections.
  • MySQL’s `SHOW GLOBAL STATUS;` and `SHOW ENGINE INNODB STATUS;`.
  • PHP-FPM’s status page (if enabled).
  • Application Performance Monitoring (APM) tools like New Relic, Datadog, or Sentry for deeper insights into application-level bottlenecks.

Adjust settings incrementally and observe the impact. What works best will depend on your specific Laravel application’s workload, traffic patterns, and the OVH instance type you are using.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala