• 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 Linode for WordPress

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MySQL on Linode for WordPress

Nginx Configuration for WordPress Performance

Optimizing Nginx is crucial for serving WordPress efficiently. We’ll focus on caching, worker processes, and connection handling.

Worker Processes and Connections

The worker_processes directive should ideally be set to the number of CPU cores available. worker_connections dictates the maximum number of simultaneous connections a worker can handle. A common starting point is to set worker_connections to a value that, when multiplied by worker_processes, exceeds your expected peak concurrent users, considering other processes on the server.

Example Nginx Configuration Snippet

worker_processes auto; # Or set to the number of CPU cores
worker_connections 4096; # Adjust based on server load and RAM
events {
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    server_tokens off; # Important for security

    # Gzip Compression
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    # Buffers
    client_body_buffer_size 10K;
    client_header_buffer_size 1K;
    large_client_header_buffers 2 4K;
    output_buffers 1 32K;
    post_process_buffer_size 16K;

    # Caching
    proxy_cache_path /var/cache/nginx/wordpress levels=1:2 keys_zone=wordpress:10m max_size=10g inactive=60m use_temp_path=off;
    proxy_temp_path /var/tmp/nginx/proxy_temp; # Ensure this directory exists and is writable by nginx user

    server {
        listen 80;
        server_name your_domain.com www.your_domain.com;
        root /var/www/your_wordpress_site;
        index index.php index.html index.htm;

        # WordPress specific rules
        location / {
            try_files $uri $uri/ /index.php?$args;
        }

        # Serve static files directly
        location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|webp|woff|woff2)$ {
            expires 30d;
            add_header Cache-Control "public, no-transform";
            access_log off;
        }

        # PHP-FPM configuration
        location ~ \.php$ {
            include snippets/fastcgi-php.conf;
            fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # Adjust to your PHP-FPM version and socket path
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            include fastcgi_params;

            # Caching for PHP-FPM output
            proxy_cache wordpress;
            proxy_cache_valid 200 302 10m; # Cache for 10 minutes
            proxy_cache_valid 404 1m;
            proxy_cache_key "$scheme$request_method$host$request_uri";
            add_header X-Cache-Status $upstream_cache_status;
        }

        # Deny access to sensitive files
        location ~* /(?:uploads|files)/.*\.php$ {
            deny all;
        }

        location ~ /\.ht {
            deny all;
        }
    }
}

Caching Implementation

Nginx’s built-in proxy caching is highly effective. The proxy_cache_path directive defines the location and parameters for the cache. keys_zone creates a shared memory zone to store cache keys, and max_size limits the total cache size. inactive specifies how long an item can remain in the cache without being accessed before it’s removed.

Within the server block, proxy_cache wordpress; enables caching for the defined zone. proxy_cache_valid sets the duration for which specific HTTP response codes are cached. The X-Cache-Status header is invaluable for debugging cache hits and misses.

Gunicorn/PHP-FPM Tuning for WordPress

The choice between Gunicorn (for Python-based frameworks often used with WordPress via plugins or headless setups) and PHP-FPM (the standard for traditional PHP WordPress) dictates the tuning approach. We’ll cover both.

PHP-FPM Optimization

PHP-FPM’s performance hinges on its process manager settings. The pm directive can be set to static, dynamic, or ondemand. For most WordPress sites on Linode, dynamic offers a good balance between resource utilization and responsiveness.

Dynamic Process Manager Settings

pm.max_children: The maximum number of child processes that will be spawned. This is a critical parameter. Too low, and requests will queue up. Too high, and you’ll exhaust server memory. A good starting point is (Total RAM - RAM for OS/Nginx/MySQL) / Average PHP-FPM Child Memory Usage.

pm.start_servers: The number of child processes to start when PHP-FPM starts.

pm.min_spare_servers: The minimum number of idle spare servers to maintain.

pm.max_spare_servers: The maximum number of idle spare servers to maintain.

pm.process_idle_timeout: The number of seconds after which an idle process will be killed.

pm.max_requests: The number of requests each child process should execute before respawning. This helps mitigate memory leaks.

Example PHP-FPM Pool Configuration (www.conf)

This configuration is typically found in /etc/php/8.1/fpm/pool.d/www.conf (adjust version and path as needed).

; Start a new pool
[www]

; Unix user/group of processes
user = www-data
group = www-data

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on TCP socket, e.g. 127.0.0.1:9000
;   '::1:port'             - to listen on TCP socket, e.g. [::1]:9000
;   '/path/to/socket.sock' - to listen on Unix socket
listen = /var/run/php/php8.1-fpm.sock

; Listen permissions
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

; Process manager settings
pm = dynamic
pm.max_children = 100       ; Adjust based on server RAM and typical child process size
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 10s
pm.max_requests = 500       ; Helps prevent memory leaks

; Other useful settings
request_terminate_timeout = 60s ; Timeout for script execution
; rlimit_files = 1024        ; Max open files per process
; rlimit_core = 0            ; Core dump size

Gunicorn Optimization (for Python/Headless WordPress)

If you’re using Gunicorn to serve a Python application that interacts with WordPress (e.g., via REST API), tuning involves worker types and counts.

Worker Types and Count

Gunicorn offers several worker types: sync (synchronous, default), eventlet, gevent, and tornado. For I/O-bound applications, asynchronous workers like gevent or eventlet are often preferred. The number of workers is typically set to (2 * Number of CPU Cores) + 1 as a starting point.

Example Gunicorn Command Line

gunicorn --workers 4 --worker-class gevent --bind 0.0.0.0:8000 your_app.wsgi:application

In this example:

  • --workers 4: Sets the number of worker processes. Adjust based on CPU cores.
  • --worker-class gevent: Uses the gevent asynchronous worker class.
  • --bind 0.0.0.0:8000: Binds Gunicorn to all network interfaces on port 8000.
  • your_app.wsgi:application: Points to your application’s WSGI entry point.

MySQL Tuning for WordPress

Database performance is often a bottleneck. Tuning MySQL involves adjusting buffer pools, query cache (though often disabled in modern MySQL versions), and connection limits.

Key MySQL Configuration Parameters

innodb_buffer_pool_size: This is arguably the most critical setting for InnoDB. It’s the memory area where InnoDB caches table and index data. Set it to 50-80% of your available RAM on a dedicated database server. On a shared Linode, be more conservative.

innodb_log_file_size and innodb_log_buffer_size: Larger log files can improve write performance but increase recovery time. A common recommendation is 256MB to 1GB for innodb_log_file_size.

max_connections: The maximum number of simultaneous client connections. WordPress sites can sometimes open many connections, especially with poorly written plugins. Monitor your actual usage and set this appropriately, but avoid excessively high values that can lead to resource exhaustion.

query_cache_size and query_cache_type: The query cache is often disabled in MySQL 5.7+ and removed in MySQL 8.0 due to scalability issues. If you are on an older version and have a read-heavy workload with many identical queries, it might offer a benefit, but generally, it’s better to rely on application-level or Nginx caching.

Example MySQL Configuration (my.cnf)

This snippet would be added to your my.cnf file (e.g., /etc/mysql/mysql.conf.d/mysqld.cnf or /etc/my.cnf).

[mysqld]
# General Settings
user                    = mysql
pid-file                = /var/run/mysqld/mysqld.pid
socket                  = /var/run/mysqld/mysqld.sock
port                    = 3306
basedir                 = /usr
datadir                 = /var/lib/mysql
tmpdir                  = /tmp
lc_messages_dir         = /usr/share/mysql
lc_messages             = en_US
skip-external-locking

# InnoDB Settings
innodb_file_per_table   = 1
innodb_flush_method     = O_DIRECT
innodb_buffer_pool_size = 1G  # Adjust based on available RAM (e.g., 50-70% of RAM on dedicated DB server)
innodb_log_file_size    = 512M # Adjust based on write load
innodb_log_buffer_size  = 64M
innodb_flush_log_at_trx_commit = 1 # For ACID compliance, 2 for slightly better performance but less safety

# Connection Settings
max_connections         = 150 # Adjust based on monitoring and application needs
# thread_cache_size       = 16  # Cache threads for reuse

# Query Cache (Generally disable for modern MySQL versions)
# query_cache_type        = 0
# query_cache_size        = 0

# Other performance tuning
# table_open_cache        = 2000
# table_definition_cache  = 1000
# sort_buffer_size        = 2M
# join_buffer_size        = 2M
# read_rnd_buffer_size    = 1M
# tmp_table_size          = 64M
# max_heap_table_size     = 64M

Monitoring and Iteration

Tuning is an iterative process. Use tools like:

  • Nginx: ngx_http_stub_status_module for connection stats, X-Cache-Status header, and access/error logs.
  • PHP-FPM: The FPM status page (requires configuration) and PHP’s built-in profiling tools (e.g., Xdebug, Blackfire.io).
  • MySQL: SHOW GLOBAL STATUS;, SHOW ENGINE INNODB STATUS;, slow query log, and tools like Percona Monitoring and Management (PMM).
  • System: top, htop, vmstat, iostat to monitor CPU, memory, I/O, and network usage.

Start with conservative settings, monitor performance under load, and gradually adjust parameters. Document all changes and their impact.

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

  • Top 100 Developer Tooling and Productivity SaaS Ideas to Launch in 2026 to Boost Organic Search Growth by 200%
  • Top 100 Developer-Centric Code Snippet Managers and Customization Plugins to Double User Engagement and Session Duration
  • Top 5 API Monetization Frameworks and Gateway Strategies for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Premium Newsletter and Subscription Business Models for Devs for High-Traffic Technical Portals

Categories

  • apache (1)
  • Business & Monetization (386)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (536)
  • DevOps (7)
  • DevOps & Cloud Scaling (937)
  • Django (1)
  • Migration & Architecture (124)
  • MySQL (1)
  • Performance & Optimization (694)
  • PHP (5)
  • Plugins & Themes (165)
  • Security & Compliance (530)
  • SEO & Growth (465)
  • Server (23)
  • Ubuntu (9)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (164)

Recent Posts

  • Top 100 Developer Tooling and Productivity SaaS Ideas to Launch in 2026 to Boost Organic Search Growth by 200%
  • Top 100 Developer-Centric Code Snippet Managers and Customization Plugins to Double User Engagement and Session Duration
  • Top 5 API Monetization Frameworks and Gateway Strategies for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Minimize Server Costs and Load Overhead
  • Top 50 Premium Newsletter and Subscription Business Models for Devs for High-Traffic Technical Portals
  • Top 100 SEO and Schema Markup Plugins for Headless Decoupled Sites for Independent Web Developers and Indie Hackers

Top Categories

  • DevOps & Cloud Scaling (937)
  • Performance & Optimization (694)
  • Debugging & Troubleshooting (536)
  • Security & Compliance (530)
  • SEO & Growth (465)
  • Business & Monetization (386)

Our Products

  • School Management & Student Administration System
  • Integrated Hospital & Clinic Management System
  • Real Estate Directory & Agent Portal
  • Restaurant POS & Table Booking System
  • Retail Inventory POS & Billing System
  • Pharmacy Inventory & Clinic Billing System

Our Services

  • Vibe Engineering & AI Code Auditing Services
  • Prompt Engineering & "Vibe Coding" Workflow Consulting
  • AI-Augmented "Vibe Coding" & Rapid MVP Development
  • Figma to Shopify Liquid Theme Customization
  • Figma to WooCommerce Frontend Development
  • Figma to Magento 2 Theme Development

Copyright © 2026 · Vinay Vengala