• 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 Elasticsearch on OVH for WooCommerce

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and Elasticsearch on OVH for WooCommerce

Nginx Configuration for High-Traffic WooCommerce

Optimizing Nginx is paramount for serving static assets, handling SSL termination, and acting as a reverse proxy to your PHP application server (Gunicorn or PHP-FPM). For a WooCommerce site on OVH, we’ll focus on caching, connection management, and security headers.

Caching Strategies

Leveraging Nginx’s FastCGI cache for PHP-FPM or proxy_cache for Gunicorn can drastically reduce backend load. For static assets, browser caching is key.

FastCGI Caching (for PHP-FPM)

This is crucial for dynamic content that doesn’t change on every request. We’ll cache full pages and specific WooCommerce query parameters.

Nginx Configuration Snippet
# Define cache zone
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=wc_cache:100m inactive=60m;
fastcgi_temp_path /var/tmp/nginx/fastcgi_temp;

server {
    listen 80;
    server_name your_domain.com;

    # SSL Configuration (if applicable)
    # listen 443 ssl http2;
    # ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    # include /etc/letsencrypt/options-ssl-nginx.conf;
    # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Static files
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # Main application entry point
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Adjust PHP version as needed

        # Cache settings
        fastcgi_cache wc_cache;
        fastcgi_cache_valid 200 302 10m; # Cache successful responses for 10 minutes
        fastcgi_cache_valid 404 1m;      # Cache 404s for 1 minute
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_cache_bypass $http_pragma $http_authorization;
        fastcgi_cache_use_stale error timeout updating http_503;

        # Ignore cache for logged-in users or specific cookies
        fastcgi_cache_min_uses 3;
        fastcgi_cache_lock on;
        fastcgi_hide_header X-Powered-By;

        # WooCommerce specific cache bypass rules
        if ($http_cookie ~* "woocommerce_items_in_cart|woocommerce_recently_viewed|wordpress_logged_in") {
            fastcgi_cache_bypass 1;
        }
        if ($request_method = POST) {
            fastcgi_cache_bypass 1;
        }
        if ($request_uri ~* "/cart/|/checkout/|/my-account/") {
            fastcgi_cache_bypass 1;
        }
    }

    # Deny access to sensitive files
    location ~ /\.ht {
        deny all;
    }
}

Explanation:

  • fastcgi_cache_path: Defines the location and parameters for the cache. levels controls directory structure, keys_zone names the cache and its size, inactive purges items not accessed for this duration.
  • fastcgi_temp_path: Directory for temporary files during cache operations.
  • fastcgi_cache: Enables caching for the specified zone.
  • fastcgi_cache_valid: Sets cache durations for different HTTP status codes.
  • fastcgi_cache_key: Defines how cache keys are generated.
  • fastcgi_cache_bypass: Conditions under which caching is bypassed (e.g., POST requests, specific cookies).
  • fastcgi_cache_use_stale: Allows serving stale content if backend is unavailable.
  • fastcgi_cache_lock: Prevents multiple requests from hitting the backend simultaneously for the same cache entry.

Proxy Caching (for Gunicorn/Python WSGI)

If you’re using Gunicorn with a Python framework like Django or Flask for your WooCommerce backend (less common but possible), Nginx can cache responses from Gunicorn.

Nginx Configuration Snippet
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=wc_proxy_cache:100m inactive=60m max_size=10g;
proxy_temp_path /var/tmp/nginx/proxy_temp;

server {
    listen 80;
    server_name your_domain.com;

    # ... (SSL, static files as above) ...

    location / {
        proxy_pass http://your_gunicorn_backend; # e.g., 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;

        # Proxy cache settings
        proxy_cache wc_proxy_cache;
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_bypass $http_pragma $http_authorization;
        proxy_cache_use_stale error timeout updating http_503;
        proxy_cache_lock on;
        proxy_cache_lock_timeout 5s;

        # WooCommerce specific cache bypass rules (similar to PHP-FPM)
        if ($http_cookie ~* "woocommerce_items_in_cart|woocommerce_recently_viewed|wordpress_logged_in") {
            proxy_cache_bypass 1;
        }
        if ($request_method = POST) {
            proxy_cache_bypass 1;
        }
        if ($request_uri ~* "/cart/|/checkout/|/my-account/") {
            proxy_cache_bypass 1;
        }
    }
}

Connection and Performance Tuning

Optimizing worker processes, keepalive connections, and buffer sizes can significantly improve Nginx’s ability to handle concurrent users.

Nginx Configuration Snippet (nginx.conf or conf.d/performance.conf)
user www-data;
worker_processes auto; # Set to number of CPU cores, or 'auto'
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 4096; # Adjust based on server memory and expected load
    multi_accept on;
    use epoll; # Linux specific, highly efficient
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000; # Close connection after N requests
    types_hash_max_size 2048;
    server_names_hash_max_size 2048;
    client_header_buffer_size 16k;
    large_client_header_buffers 4 32k;
    client_max_body_size 100m; # Adjust for WooCommerce uploads

    # 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 image/svg+xml;

    # Buffers
    proxy_buffer_size 16k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 32k;

    # Include other configurations
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # Logging
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log warn;

    # Include server blocks
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Explanation:

  • worker_processes auto;: Dynamically scales based on CPU cores.
  • worker_connections: Maximum concurrent connections per worker. High values require sufficient RAM.
  • sendfile on;: Efficiently transfers files from disk to network socket.
  • tcp_nopush on;: Optimizes packet sending.
  • tcp_nodelay on;: Disables Nagle’s algorithm for lower latency.
  • keepalive_timeout: How long to keep idle connections open.
  • client_max_body_size: Crucial for WooCommerce product image uploads.
  • gzip_*: Enables and configures Gzip compression for faster asset delivery.
  • proxy_buffer_*: Tune buffer sizes for proxying requests.

Security Headers

Enhance security by adding essential HTTP headers.

Nginx Configuration Snippet (within server block)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always; # Adjust as needed
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://apis.google.com https://connect.facebook.net; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://cdn.example.com; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https://api.example.com;" always; # Highly customized for your needs

Note: The Content-Security-Policy (CSP) is highly specific to your site’s external resources. You’ll need to audit your site’s network requests to build an effective CSP. Start with a `report-only` mode to avoid breaking functionality.

Gunicorn Tuning for WooCommerce (Python WSGI)

If your WooCommerce backend is powered by Python (e.g., Django/Flask), Gunicorn needs careful tuning for concurrency and worker management.

Worker Processes and Threads

The optimal number of workers depends on your server’s CPU cores and memory, as well as the nature of your application (CPU-bound vs. I/O-bound).

Gunicorn Command Line / Systemd Service File
# Example using systemd service file (/etc/systemd/system/gunicorn.service)

[Unit]
Description=Gunicorn instance to serve my_app
After=network.target

[Service]
User=my_app_user
Group=my_app_group
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/venv/bin/gunicorn \
    --workers 4 \
    --threads 2 \
    --worker-class gevent \
    --bind unix:/run/gunicorn.sock \
    --timeout 120 \
    --graceful-timeout 60 \
    --log-level info \
    --log-file /var/log/gunicorn/gunicorn.log \
    my_app.wsgi:application

[Install]
[Install]
WantedBy=multi-user.target

Explanation:

  • --workers: Number of worker processes. A common starting point is (2 * CPU_cores) + 1.
  • --threads: Number of threads per worker. Useful for I/O-bound tasks. Requires a worker class that supports threading (e.g., gthread, gevent with monkey patching).
  • --worker-class: sync (default, one request per worker at a time), gevent (asynchronous, good for I/O-bound), gaiohttp (asyncio). For WooCommerce, gevent or a similar async worker class is often beneficial due to external API calls and database interactions.
  • --bind: How Gunicorn listens for connections (Unix socket is preferred when behind Nginx).
  • --timeout: Maximum time a worker can spend on a request before being killed. Crucial for long-running WooCommerce tasks.
  • --graceful-timeout: Time to wait for workers to finish requests during a reload.

Gunicorn Logging

Effective logging is vital for debugging and performance monitoring.

Gunicorn Configuration (via command line or systemd)
# Log to a file
--log-file /var/log/gunicorn/gunicorn.log
--log-level info # or debug, warning, error

# Log to stdout/stderr (useful with Docker/Kubernetes)
# --log-file -

Ensure the log directory exists and the Gunicorn user has write permissions:

sudo mkdir -p /var/log/gunicorn
sudo chown my_app_user:my_app_group /var/log/gunicorn
sudo chmod 755 /var/log/gunicorn

PHP-FPM Tuning for WooCommerce

When using PHP-FPM with Nginx for WordPress/WooCommerce, tuning the FPM pool is critical for handling concurrent requests efficiently.

PHP-FPM Pool Configuration

Edit your FPM pool configuration file, typically located at /etc/php/7.4/fpm/pool.d/www.conf (adjust version and filename as needed).

PHP-FPM Pool Configuration Snippet
; /etc/php/7.4/fpm/pool.d/www.conf

[www]
user = www-data
group = www-data
listen = /var/run/php/php7.4-fpm.sock ; Or a TCP socket like 127.0.0.1:9000

; Process Manager Settings
; pm = dynamic ; or static or ondemand
pm = dynamic
pm.max_children = 100       ; Max number of child processes
pm.start_servers = 5        ; Number of servers to start upon system startup
pm.min_spare_servers = 10   ; Min number of idle servers
pm.max_spare_servers = 20   ; Max number of idle servers
pm.process_idle_timeout = 10s ; Timeout for idle processes

; Request handling
request_terminate_timeout = 120s ; Max execution time for a script
; request_slowlog_timeout = 10s ; Log slow requests (requires slowlog file)
; slowlog = /var/log/php/php7.4-fpm-slow.log

; Resource limits
; memory_limit = 256M ; Adjust based on WooCommerce needs
; max_execution_time = 60 ; Default is 30, increase for heavy operations
; max_input_vars = 3000 ; Crucial for WooCommerce forms/settings

; Error logging
error_log = /var/log/php/php7.4-fpm.log
log_level = notice ; or warning, error, debug

; Other useful settings
; opcache.enable=1
; opcache.memory_consumption=128
; opcache.interned_strings_buffer=16
; opcache.max_accelerated_files=10000
; opcache.revalidate_freq=1
; opcache.validate_timestamps=1 ; Set to 0 in production for performance, but requires cache clearing on deploy
; opcache.enable_cli=1

Explanation:

  • pm: Process Manager control. dynamic is generally recommended, balancing resource usage and responsiveness. static is best for predictable high load.
  • pm.max_children: The most critical setting. Too high can exhaust server memory; too low can lead to request queuing. Monitor server load and adjust.
  • pm.start_servers, pm.min_spare_servers, pm.max_spare_servers: These tune the dynamic scaling of worker processes.
  • request_terminate_timeout: Essential for WooCommerce operations that might take longer than the default PHP max_execution_time.
  • max_input_vars: WooCommerce often uses many POST variables for settings and product data. Increasing this prevents “POST too large” or data loss issues.
  • opcache.*: Ensure OPcache is enabled and configured appropriately for significant performance gains. Adjust memory and file counts based on your codebase size.

Restarting PHP-FPM

After modifying the pool configuration, restart PHP-FPM:

sudo systemctl restart php7.4-fpm # Adjust version as needed

Elasticsearch Tuning for WooCommerce Search

For advanced search capabilities in WooCommerce, Elasticsearch is often used. Tuning its JVM heap size and cluster settings is crucial for performance and stability.

JVM Heap Size Configuration

The JVM heap size directly impacts Elasticsearch’s performance. It’s recommended to set it to half of your available RAM, but not exceeding 30-32GB. This is configured via environment variables or the jvm.options file.

Elasticsearch Configuration Snippet (jvm.options)
# Example: For a server with 16GB RAM
-Xms8g
-Xmx8g

# Example: For a server with 64GB RAM (max recommended)
# -Xms16g
# -Xmx16g

This file is typically located at /etc/elasticsearch/jvm.options or similar. After changing, restart Elasticsearch:

sudo systemctl restart elasticsearch

Index Settings and Mappings

Proper index settings and mappings prevent performance degradation over time. For WooCommerce, consider:

  • Number of Shards and Replicas: Start with a reasonable number of primary shards (e.g., 1-5) and replicas (e.g., 1-2 for high availability). Too many shards increase overhead.
  • Refresh Interval: The default is 1 second, making documents searchable quickly but consuming resources. For WooCommerce search, a slightly longer interval (e.g., 5-10 seconds) might be acceptable if near real-time search isn’t critical.
  • Mappings: Define explicit mappings for your product fields (e.g., text, keyword, numeric, date) to ensure correct indexing and efficient querying. Avoid dynamic mapping for production.
Example Index Creation (using Elasticsearch API)
PUT /my_woocommerce_products
{
  "settings": {
    "index": {
      "number_of_shards": 3,
      "number_of_replicas": 1,
      "refresh_interval": "5s"
    }
  },
  "mappings": {
    "properties": {
      "product_id": { "type": "integer" },
      "name": { "type": "text", "analyzer": "english" },
      "description": { "type": "text", "analyzer": "english" },
      "price": { "type": "float" },
      "categories": { "type": "keyword" },
      "tags": { "type": "keyword" },
      "sku": { "type": "keyword" },
      "stock_quantity": { "type": "integer" },
      "attributes": { "type": "object" },
      "image_url": { "type": "keyword" },
      "date_created": { "type": "date" }
    }
  }
}

You can use tools like curl or Kibana’s Dev Tools to execute these API calls.

Monitoring and Diagnostics

Regular monitoring is key to identifying bottlenecks before they impact users.

  • Nginx: Monitor access.log and error.log for errors, slow requests, and high traffic patterns. Use tools like ngx_http_stub_status_module for real-time metrics.
  • PHP-FPM: Check the FPM error log for script errors. Monitor the number of active processes via pm.status_path (requires configuration in Nginx to access).
  • Gunicorn: Monitor Gunicorn logs for application errors and worker restarts. Use tools like htop or glances to observe CPU/memory usage per worker.
  • Elasticsearch: Use the Elasticsearch API (e.g., _cat/nodes, _cat/indices, _cluster/health) and tools like Kibana’s Monitoring UI to track cluster health, JVM heap usage, indexing rates, and query latency.
  • System Resources: Continuously monitor CPU, RAM, disk I/O, and network usage on your OVH instances using standard Linux tools (top, htop, vmstat, iostat).

By meticulously tuning these components, you can build a robust, high-performance WooCommerce infrastructure on OVH capable of handling significant traffic loads.

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 thread pools deadlock during concurrent ActiveRecord transaction processing on Linode Servers
  • Securing Your E-commerce APIs: Preventing SQL Injection (SQLi) in customized checkout queries in WooCommerce Implementations
  • Disaster Recovery 101: Architecting Auto-Failovers for MySQL and Ruby Deployments on Linode
  • High-Throughput Caching Strategies: Scaling MySQL for Perl Application APIs
  • Disaster Recovery 101: Architecting Auto-Failovers for DynamoDB and Laravel Deployments on DigitalOcean

Copyright © 2026 · Vinay Vengala