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

Vengala Vinay

Having 9+ Years of Experience in Software Development

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

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and MongoDB on Linode for WooCommerce

Nginx as a High-Performance Frontend for WooCommerce

When deploying WooCommerce, especially on a platform like Linode, Nginx serves as an indispensable frontend. Its event-driven architecture excels at handling concurrent connections, making it ideal for serving static assets and proxying dynamic requests to your application server. Proper tuning is critical for maximizing throughput and minimizing latency.

Nginx Configuration Tuning

The primary configuration file for Nginx is typically located at /etc/nginx/nginx.conf. We’ll focus on tuning the http block and individual server blocks.

Global Nginx Settings

Within the /etc/nginx/nginx.conf file, the http block contains global settings that affect all server blocks. Key parameters to adjust include:

  • worker_processes: Set this to the number of CPU cores available on your Linode instance. This allows Nginx to utilize all available processing power.
  • worker_connections: This defines the maximum number of simultaneous connections that each worker process can handle. A common starting point is 1024 or higher, depending on your expected traffic.
  • multi_accept: Setting this to on allows worker processes to accept as many new connections as possible at once.
  • keepalive_timeout: Controls how long an idle keep-alive connection will remain open. A value between 60 and 120 seconds is often a good balance.
  • sendfile: Set to on to enable efficient file transfers by allowing the kernel to send files directly from a file descriptor to the socket without data copying.
  • tcp_nopush and tcp_nodelay: These can improve network performance by optimizing packet transmission. Setting tcp_nopush to on and tcp_nodelay to on is generally recommended.

Here’s an example snippet for the http block:

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

    keepalive_timeout  65;
    types_hash_max_size 2048;

    # Adjust based on your Linode instance's CPU cores
    worker_processes    auto; # or specify number of cores
    worker_connections  4096;
    multi_accept        on;

    # ... other http configurations
}

Server Block Optimization for WooCommerce

For your WooCommerce site, the server block (within /etc/nginx/sites-available/your_woocommerce_site) needs specific directives. This includes caching, Gzip compression, and proxying to your PHP application server (Gunicorn or PHP-FPM).

Caching Static Assets

Leveraging browser caching for static assets like CSS, JavaScript, and images significantly reduces server load and improves page load times for repeat visitors. We can set long expiration times for these resources.

server {
    listen 80;
    server_name your_domain.com www.your_domain.com;
    root /var/www/your_woocommerce_site/public_html; # Adjust to your WooCommerce root directory
    index index.php index.html index.htm;

    # Caching for static assets
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|webp)$ {
        expires 365d;
        add_header Cache-Control "public, no-transform";
        access_log off;
        log_not_found off;
    }

    # ... other configurations
}

Gzip Compression

Enabling Gzip compression reduces the size of text-based assets (HTML, CSS, JS) sent over the network, leading to faster downloads. Ensure it’s enabled globally or within your server block.

http {
    # ... other http configurations

    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 image/svg+xml;
    gzip_disable "msie6"; # Disable for older IE versions if necessary
}

Proxying to PHP Application Server

For dynamic content, Nginx acts as a reverse proxy. The configuration depends on whether you’re using PHP-FPM or Gunicorn (for Python-based applications like a custom WooCommerce API or headless setup).

Nginx with PHP-FPM

This is the standard setup for WordPress/WooCommerce. Nginx passes PHP requests to PHP-FPM via a Unix socket or TCP port.

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    # With php-fpm (or other unix sockets):
    fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Adjust PHP version and path as needed
    # With php-cgi (or other tcp sockets):
    # fastcgi_pass 127.0.0.1:9000;
}
Nginx with Gunicorn (for Headless WooCommerce)

If you’re using a Python backend (e.g., Django, Flask) for a headless WooCommerce setup, Nginx will proxy requests to Gunicorn.

location / {
    proxy_pass http://unix:/path/to/your/gunicorn.sock; # Or http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Gunicorn Tuning for Python Applications

For headless WooCommerce or custom Python backends, Gunicorn is a popular WSGI HTTP Server. Its performance is heavily influenced by the number of worker processes and threads.

Gunicorn Worker Processes and Threads

The key to Gunicorn performance lies in its worker configuration. The recommended approach is to use a combination of worker processes and threads.

  • --workers: This is the number of worker processes. A common recommendation is (2 * CPU_CORES) + 1. For a Linode instance with 4 cores, this would be 9 workers.
  • --threads: This is the number of threads per worker process. For I/O-bound applications (like most web applications), using threads can significantly increase concurrency without a proportional increase in memory usage. A value of 2 to 5 is often a good starting point.

Consider your Linode instance’s RAM. Each worker process consumes memory. If you have limited RAM, you might need to reduce the number of workers or threads.

Gunicorn Configuration Example

You can configure Gunicorn via command-line arguments or a Python configuration file. Using a configuration file is generally cleaner for production deployments.

# gunicorn_config.py
import multiprocessing

bind = "unix:/path/to/your/gunicorn.sock" # Or "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
threads = 2 # Adjust based on I/O bound nature of your app
worker_class = "gthread" # Use 'gthread' for threaded workers

# Optional: Adjust timeout and graceful shutdown
timeout = 120
graceful_timeout = 120

# Optional: Logging configuration
# loglevel = "info"
# accesslog = "/var/log/gunicorn/access.log"
# errorlog = "/var/log/gunicorn/error.log"

To run Gunicorn with this configuration:

gunicorn -c gunicorn_config.py your_app.wsgi:application

PHP-FPM Tuning for WordPress/WooCommerce

PHP-FPM (FastCGI Process Manager) is the de facto standard for running PHP applications. Its performance is governed by how it manages worker processes.

PHP-FPM Process Manager Settings

The PHP-FPM configuration file is typically found at /etc/php/X.Y/fpm/pool.d/www.conf (where X.Y is your PHP version). The key directives are within the pool configuration.

  • pm: Process Manager control. Options are static, dynamic, and ondemand.
    • static: Keeps a fixed number of child processes running. Good for predictable loads.
    • dynamic: Starts a minimum number of processes and spawns more up to a maximum as needed.
    • ondemand: Starts no processes initially and spawns them only when requests arrive.
  • pm.max_children: The maximum number of child processes that will be spawned. This is the most critical setting. Set it based on your server’s RAM. A common rule of thumb is to calculate the total RAM required by a single PHP-FPM process (including WordPress/WooCommerce overhead) and divide your total available RAM by that figure.
  • pm.start_servers: The number of child processes to start when PHP-FPM starts.
  • pm.min_spare_servers: The minimum number of idle (spare) processes to maintain.
  • pm.max_spare_servers: The maximum number of idle (spare) processes to maintain.
  • pm.max_requests: The number of requests each child process will serve before respawning. This helps prevent memory leaks. A value between 500 and 1000 is typical.

For a busy WooCommerce site on a Linode instance, dynamic is often a good choice. Let’s assume a single PHP-FPM process with WordPress/WooCommerce consumes approximately 30-50MB of RAM. For a 4GB RAM Linode, you might reserve 1GB for the OS and other services, leaving 3GB for PHP-FPM. This could allow for around 60-90 max_children.

; /etc/php/7.4/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = /var/run/php/php7.4-fpm.sock # Ensure this matches your Nginx config
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 90       ; Adjust based on RAM
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 750

; Other settings
request_terminate_timeout = 120s
php_admin_value[memory_limit] = 256M
php_admin_value[upload_max_filesize] = 64M
php_admin_value[post_max_size] = 64M
php_admin_value[max_execution_time] = 120

MongoDB Tuning for WooCommerce Data

While WooCommerce primarily uses MySQL, if you’re using MongoDB for specific features (e.g., caching, logging, custom data storage, or a headless CMS integration), tuning it is crucial.

MongoDB Configuration (`mongod.conf`)

The main configuration file is typically /etc/mongod.conf. Key parameters for performance include:

  • storage.wiredTiger.engineConfig.cacheSizeGB: This is arguably the most important setting. It defines the amount of RAM allocated to the WiredTiger cache. A common recommendation is to allocate 50% of your system’s RAM to the cache, ensuring you leave enough for the OS and other processes.
  • operationProfiling.slowOpThresholdMs: Set this to a reasonable value (e.g., 100 or 200) to log slow queries, which is vital for identifying performance bottlenecks.
  • net.bindIp: Ensure this is set to allow connections from your application server.
  • sharding.clusterRole: If you’re sharding, this is essential.
# /etc/mongod.conf
systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
      cacheSizeGB: 2 # Adjust based on your Linode instance RAM (e.g., 2GB for 4GB RAM instance)
    collectionConfig:
      blockSize: 4KB
    indexConfig:
      prefixCompression: true
net:
  port: 27017
  bindIp: 0.0.0.0 # Or specific IPs for security
# security:
#   authorization: enabled
# sharding:
#   clusterRole: configsvr
#   configsvrFilePermissionsString: "600"
#   localLogComponentVector:
#     - component: STORAGE
#       verbosity: 0
#     - component: COMMAND
#       verbosity: 0
#     - component: NETWORK
#       verbosity: 0
#     - component: QUERYPLANNING
#       verbosity: 0
#     - component: REPLICATION
#       verbosity: 0
#     - component: JOURNAL
#       verbosity: 0
#     - component: WRITEBACK_STAGED
#       verbosity: 0
#     - component: LOCKS
#       verbosity: 0
#     - component: INDEX
#       verbosity: 0
#     - component: ARBITER
#       verbosity: 0
#     - component: BALANCER
#       verbosity: 0
#     - component: APPLICATION_MESSAGE
#       verbosity: 0
#     - component: CONTROL
#       verbosity: 0
#     - component: INTERNAL
#       verbosity: 0
#     - component: TRANSFER
#       verbosity: 0
#     - component: SCANNER
#       verbosity: 0
#     - component: TIMER
#       verbosity: 0
#     - component: ALL
#       verbosity: 0
operationProfiling:
  mode: "slowOp"
  slowOpThresholdMs: 100 # Log operations slower than 100ms
processManagement:
  fork: true
  pidFilePath: /var/run/mongodb/mongod.pid

Monitoring and Diagnostics

Regular monitoring is key to identifying performance issues before they impact users. Use tools like:

  • Nginx: nginx -t for configuration testing, nginx -s reload to apply changes, and access/error logs (/var/log/nginx/access.log, /var/log/nginx/error.log).
  • PHP-FPM: Check PHP-FPM logs (often in /var/log/phpX.Y-fpm.log) and use systemctl status phpX.Y-fpm.
  • Gunicorn: Monitor its logs and use systemctl status your_gunicorn_service if managed by systemd.
  • MongoDB: Use mongostat and mongotop for real-time statistics, and analyze slow query logs.
  • System Resources: Tools like htop, vmstat, and iostat are invaluable for understanding overall system load, CPU, memory, and I/O utilization.

By systematically tuning these components, you can build a robust and high-performing WooCommerce infrastructure on Linode.

Primary Sidebar

A little about the Author

Having 9+ Years of Experience in Software Development.
Expertised in Php Development, WordPress Custom Theme Development (From scratch using underscores or Genesis Framework or using any blank theme or Premium Theme), Custom Plugin Development. Hands on Experience on 3rd Party Php Extension like Chilkat, nSoftware.

Recent Posts

  • Step-by-Step: Diagnosing indexing lock conflicts and high CPU during bulk stock updates on DigitalOcean Servers
  • How to Debug and Fix memory leaks and socket exhaustion in daemon processes in Modern C++ Applications
  • Infrastructure as Code: Provisioning Secure PHP Clusters on DigitalOcean Using Terraform
  • Fixing Slow Largest Contentful Paint (LCP) caused by unoptimized database queries in Legacy Laravel Codebases Without Breaking API Contracts
  • An Auditor’s Checklist for Securing Laravel Backends on Google Cloud

Copyright © 2026 · Vinay Vengala