• 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 AWS for WooCommerce

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

Nginx as a High-Performance Frontend for WooCommerce

When deploying WooCommerce on AWS, Nginx serves as the de facto standard for a high-performance web server and reverse proxy. Its event-driven, asynchronous architecture excels at handling a large number of concurrent connections, making it ideal for the often-bursty traffic patterns of e-commerce sites. The key to unlocking its full potential lies in meticulous configuration, particularly around worker processes, connection limits, and caching.

Nginx Worker Processes and Connections

The `worker_processes` directive dictates how many worker processes Nginx will spawn. Setting this to `auto` is generally recommended, allowing Nginx to dynamically adjust based on the number of CPU cores available. This ensures optimal utilization of your EC2 instance’s processing power. The `worker_connections` directive, on the other hand, defines the maximum number of simultaneous connections that each worker process can handle. This value, combined with `worker_processes`, determines the total connection capacity. A common starting point is 1024, but this should be tuned based on your instance type and expected load.

Crucially, the operating system’s file descriptor limit must be high enough to accommodate Nginx’s needs. Each connection consumes a file descriptor. You can check the current limit with ulimit -n and increase it by editing /etc/security/limits.conf.

Nginx Configuration Snippet

Here’s a foundational Nginx configuration snippet for a WooCommerce deployment. This assumes you’re using Gunicorn (for Python-based backends) or PHP-FPM. Adjust `worker_processes` and `worker_connections` based on your EC2 instance’s CPU cores and expected load.

Global Nginx Settings

Place these directives in your main nginx.conf file, typically in the http block.

worker_processes auto;
# Adjust worker_connections based on your instance type and expected load.
# A common starting point is 1024. Ensure OS limits are also increased.
worker_connections 4096;
multi_accept on;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    # This should be at least worker_connections
    worker_connections 4096;
}

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;

    # Gzip compression for static and dynamic content
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_min_length 256;
    gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;

    # Buffering settings for proxying
    proxy_buffer_size 128k;
    proxy_buffers 4 256k;
    proxy_busy_buffers_size 256k;

    # Client body buffer size - adjust if you have large uploads
    client_max_body_size 100M;
    client_body_buffer_size 100M;

    # Access log configuration
    access_log /var/log/nginx/access.log;

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

WooCommerce Server Block (Example)

This configuration assumes your WooCommerce application is served by Gunicorn (Python) or PHP-FPM. Adapt the proxy_pass directive accordingly.

server {
    listen 80;
    server_name your_domain.com www.your_domain.com;
    root /var/www/your_woocommerce_app/public; # Adjust to your app's public directory

    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    # For PHP-FPM
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        # Adjust the socket path to your PHP-FPM pool
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock; # Example for PHP 7.4
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # For Gunicorn (Python)
    # 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;
    # }

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

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

    # Prevent access to wp-config.php and other sensitive files
    location ~* (wp-config\.php|readme\.html|license\.txt) {
        deny all;
    }

    # Serve static files directly
    location ~ ^/(images|javascript|js|css|flash|media|static)/ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}

Gunicorn/PHP-FPM Tuning for WooCommerce

The application server (Gunicorn for Python, PHP-FPM for PHP) is the engine that processes your WooCommerce requests. Optimizing its configuration is paramount for responsiveness and scalability.

Gunicorn Configuration

Gunicorn’s performance is largely dictated by its worker class and the number of worker processes. For I/O-bound applications like WooCommerce, the gevent worker class is often preferred due to its ability to handle many concurrent connections efficiently. The number of workers is typically set to (2 * number_of_cores) + 1 as a starting point.

Consider using a Unix socket for communication between Nginx and Gunicorn if they are on the same host. This can offer a slight performance improvement over TCP/IP sockets.

Gunicorn Command Line Example

gunicorn --workers 4 --worker-class gevent --bind unix:/path/to/your/gunicorn.sock your_app.wsgi:application --log-level info --access-logfile /var/log/gunicorn/access.log --error-logfile /var/log/gunicorn/error.log

Explanation:

  • --workers 4: Sets the number of worker processes. Adjust based on your CPU cores.
  • --worker-class gevent: Uses the gevent worker class for asynchronous I/O.
  • --bind unix:/path/to/your/gunicorn.sock: Binds Gunicorn to a Unix socket. Alternatively, use --bind 127.0.0.1:8000 for a TCP socket.
  • your_app.wsgi:application: Points to your application’s WSGI entry point.

PHP-FPM Configuration

PHP-FPM (FastCGI Process Manager) is the standard for serving PHP applications. Its performance tuning involves managing the number of child processes and their lifecycle. The pm (process manager) setting is crucial. For production, pm = dynamic or pm = ondemand are generally recommended over pm = static, as they allow PHP-FPM to scale its worker pool based on demand, preventing resource exhaustion.

Key directives to tune within your PHP-FPM pool configuration (e.g., /etc/php/7.4/fpm/pool.d/www.conf):

PHP-FPM Pool Configuration Example

; For a dynamic process manager
pm = dynamic
; Maximum number of children that can be started.
pm.max_children = 100
; Maximum number of children that can be started at one time.
pm.start_servers = 10
; Minimum number of children that should always be running.
pm.min_spare_servers = 5
; Maximum number of children that can stay idle in the meantime.
pm.max_spare_servers = 20
; The number of requests each child process should execute before respawning.
; This helps to prevent memory leaks.
pm.max_requests = 500

; If using 'ondemand' process manager
; pm = ondemand
; pm.max_children = 50
; pm.process_idle_timeout = 10s
; pm.max_requests = 500

; Adjust listen socket to match Nginx configuration
listen = /var/run/php/php7.4-fpm.sock
; listen.owner = www-data
; listen.group = www-data
; listen.mode = 0660

; Adjust user and group to match your web server user
user = www-data
group = www-data

; Adjust request termination timeout
request_terminate_timeout = 120s

; Adjust idle timeout
; pm.idle_timeout = 10s

; Adjust slowlog for debugging
; slowlog = /var/log/php/php7.4-fpm.slow.log

Tuning Notes:

  • pm.max_children: This is the most critical setting. It should be high enough to handle peak load but not so high that it exhausts server memory. Monitor your server’s memory usage and adjust accordingly.
  • pm.start_servers, pm.min_spare_servers, pm.max_spare_servers: These control how PHP-FPM manages its worker pool. Dynamic settings are generally preferred for fluctuating loads.
  • pm.max_requests: Essential for preventing memory leaks in long-running PHP processes. A value between 100 and 500 is typical.
  • request_terminate_timeout: Set this to a reasonable value to prevent long-running scripts from holding up workers indefinitely.

MongoDB Performance Tuning for WooCommerce

While WooCommerce primarily relies on MySQL, MongoDB can be used for caching, session storage, or specific plugins. Optimizing MongoDB is crucial for these use cases.

MongoDB WiredTiger Storage Engine

The WiredTiger storage engine is the default and recommended engine for MongoDB. Its performance is heavily influenced by its cache size. The WiredTiger cache aims to hold the working set of your data and indexes in RAM for fast access.

WiredTiger Cache Configuration

storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true
  engine: wiredTiger
  wiredTiger:
    engineConfig:
      cacheSizeGB: 0.75 # Allocate 75% of available RAM, or a fixed value like 4GB
    collectionConfig:
      cacheResource:
        - block:
            size: 4KB
    indexConfig:
      prefixCompression: true
      cacheResource:
        - block:
            size: 256B

Tuning Notes:

  • cacheSizeGB: This is the most critical parameter. A common recommendation is to allocate 50-75% of the system’s RAM to the WiredTiger cache. However, ensure enough RAM is left for the OS and other processes. For a dedicated MongoDB instance, you might allocate more. For a shared instance, be more conservative. Monitor db.serverStatus().wiredTiger.cache for cache hit rates. Aim for a high hit rate (e.g., > 90%).
  • indexConfig.prefixCompression: Enabling prefix compression for indexes can significantly reduce their size, improving cache efficiency and read performance.

MongoDB Query Optimization and Indexing

Inefficient queries and missing indexes are common performance bottlenecks. Regularly analyze your MongoDB slow query log to identify problematic queries.

Identifying Slow Queries

Ensure slow query logging is enabled in your mongod.conf:

# mongod.conf
systemLog:
  destination: file
  path: /var/log/mongodb/mongod.log
  logAppend: true
  verbosity: 0
  quiet: false
  slowms: 100 # Log queries slower than 100ms
  traceSampleRates:
    query: 1 # Sample 1% of all queries
    command: 1 # Sample 1% of all commands

Use the db.collection.find().explain("executionStats") method in the MongoDB shell to analyze query performance. Look for high totalKeysExamined relative to totalDocsExamined, and a high totalKeysExamined overall.

Creating Effective Indexes

Based on your slow query analysis, create appropriate indexes. For example, if you frequently query a `products` collection by `category` and `status`, an index like this would be beneficial:

db.products.createIndex( { category: 1, status: 1 } )

Consider compound indexes, covering indexes, and TTL indexes where appropriate. Regularly review and optimize your indexes using tools like Percona Monitoring and Management (PMM) or MongoDB Atlas’s performance tools.

AWS Infrastructure Considerations

The underlying AWS infrastructure plays a significant role. Choosing the right EC2 instance types, EBS volume types, and network configurations is crucial.

EC2 Instance Selection

For compute-intensive workloads like WooCommerce, consider EC2 instances with good CPU performance (e.g., C-series). For memory-intensive caching layers (e.g., Redis, or if MongoDB is heavily used), R-series instances are suitable. Network-optimized instances (e.g., N-series) can be beneficial for high-traffic sites with significant data transfer.

EBS Volume Optimization

If MongoDB is hosted on EC2, use gp3 or io2 EBS volumes for production workloads. gp3 offers a good balance of price and performance, allowing you to provision IOPS and throughput independently. io2 provides higher IOPS and durability for demanding workloads. Avoid gp2 for production due to its burst-based performance model.

Load Balancing and Auto Scaling

Utilize AWS Elastic Load Balancing (ELB) to distribute traffic across multiple EC2 instances running your WooCommerce application. Configure Auto Scaling Groups to automatically adjust the number of instances based on demand, ensuring high availability and cost-efficiency. Ensure your ELB health checks are configured correctly to monitor the responsiveness of your application servers.

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