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

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

Nginx as a High-Performance Frontend for WooCommerce

When deploying WooCommerce on AWS, Nginx serves as an indispensable frontend, handling static asset delivery, SSL termination, and reverse proxying to your application servers (Gunicorn for Python/Django or PHP-FPM for PHP). Optimizing Nginx is crucial for minimizing latency and maximizing throughput.

Nginx Configuration Tuning

The primary Nginx configuration file, typically located at /etc/nginx/nginx.conf, and site-specific configurations in /etc/nginx/sites-available/ (symlinked to /etc/nginx/sites-enabled/) are the starting points. Key directives to scrutinize include:

Worker Processes and Connections

The worker_processes directive determines how many worker processes Nginx will spawn. Setting this to auto is generally recommended, allowing Nginx to detect the number of CPU cores. The worker_connections directive limits the number of simultaneous connections a single worker process can handle. This value should be set high enough to accommodate peak traffic, considering that each connection consumes memory.

worker_processes auto;
events {
    worker_connections 4096; # Adjust based on available RAM and expected load
    multi_accept on;
}

Keepalive Connections

Enabling HTTP keep-alive connections reduces the overhead of establishing new TCP connections for each request. The keepalive_timeout directive controls how long an idle keep-alive connection will remain open. A value between 60 and 120 seconds is a good starting point. keepalive_requests limits the number of requests that can be made over a single keep-alive connection.

http {
    # ... other http directives ...
    keepalive_timeout 75;
    keepalive_requests 1000;
    # ...
}

Buffering and Caching

Nginx uses buffers to handle request and response data. Tuning client_body_buffer_size and client_header_buffer_size can improve performance, especially for large uploads or complex requests. For static assets, leveraging Nginx’s proxy_cache is paramount. Configure cache zones and set appropriate cache expiration times.

http {
    # ...
    client_body_buffer_size 128k;
    client_header_buffer_size 4k;

    proxy_cache_path /var/cache/nginx/woocommerce levels=1:2 keys_zone=wc_cache:10m max_size=1g inactive=60m use_temp_path=off;

    server {
        # ...
        location / {
            proxy_pass http://your_app_backend;
            proxy_cache wc_cache;
            proxy_cache_valid 200 302 10m; # Cache successful responses for 10 minutes
            proxy_cache_valid 404 1m;      # Cache 404s for 1 minute
            add_header X-Cache-Status $upstream_cache_status;
        }
        # ...
    }
    # ...
}

Gzip Compression

Enabling Gzip compression significantly reduces the size of text-based assets (HTML, CSS, JS, JSON), leading to faster load times. Ensure you configure it correctly to avoid compressing already compressed content (like images).

http {
    # ...
    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;
    # ...
}

Gunicorn Tuning for Python/Django WooCommerce Deployments

For Python-based WooCommerce backends (e.g., using Django), Gunicorn is a popular WSGI HTTP Server. Its performance is heavily influenced by the number of worker processes and threads.

Worker Processes and Threads

Gunicorn’s --workers flag determines the number of worker processes. A common recommendation is (2 * number_of_cores) + 1. The --threads flag (available in Gunicorn 20.0+) allows for multi-threading within each worker process, which can be beneficial for I/O-bound tasks. However, be mindful of Python’s Global Interpreter Lock (GIL) for CPU-bound tasks.

# Example: If you have 4 CPU cores
gunicorn --workers 9 --threads 2 your_project.wsgi:application --bind 0.0.0.0:8000

Worker Types

Gunicorn supports various worker types. The default is sync, which is a simple, blocking worker. For I/O-bound applications, gevent or eventlet (asynchronous workers) can offer better concurrency by using green threads. If using async workers, ensure your application code is compatible with asynchronous operations.

# Using gevent workers
gunicorn --worker-class gevent --workers 9 --threads 2 your_project.wsgi:application --bind 0.0.0.0:8000

Timeouts and Graceful Restarts

The --timeout flag prevents workers from hanging indefinitely. Set it to a reasonable value (e.g., 30 seconds) to avoid issues with slow requests. Use --graceful-timeout for graceful worker restarts, allowing existing requests to complete.

gunicorn --workers 9 --threads 2 --timeout 30 --graceful-timeout 60 your_project.wsgi:application --bind 0.0.0.0:8000

PHP-FPM Tuning for PHP-Based WooCommerce Deployments

For PHP-based WooCommerce, PHP-FPM (FastCGI Process Manager) is the standard. Its configuration, typically found in /etc/php/[version]/fpm/php-fpm.conf and pool configurations in /etc/php/[version]/fpm/pool.d/www.conf, is critical.

Process Manager Settings

The pm directive controls how PHP-FPM manages child processes. Common values are static, dynamic, and ondemand. For busy WooCommerce sites, dynamic or static are often preferred. If using dynamic, tune pm.max_children, pm.start_servers, pm.min_spare_servers, and pm.max_spare_servers.

; /etc/php/[version]/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = /run/php/php[version]-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 100       ; Adjust based on server RAM and expected load
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.process_idle_timeout = 10s
pm.max_requests = 500       ; Restart worker after this many requests to prevent memory leaks

If using static, pm.max_children is the fixed number of children. This can be simpler to manage but less flexible. For ondemand, processes are spawned only when needed, which can save resources but might introduce latency on initial requests.

; Example for static pm
pm = static
pm.max_children = 150

Request Execution Time and Memory Limits

request_terminate_timeout in php-fpm.conf (or pool config) sets the maximum time a script can run. WooCommerce operations, especially during checkout or complex product queries, can be lengthy. Set this appropriately, but be cautious not to set it too high, as it can mask underlying performance issues. memory_limit in php.ini should also be sufficient for your application’s needs.

; /etc/php/[version]/fpm/pool.d/www.conf
request_terminate_timeout = 120s ; Allow up to 120 seconds for script execution

; In /etc/php/[version]/fpm/php.ini
memory_limit = 512M

MySQL/MariaDB Tuning for WooCommerce Databases

The database is often the bottleneck in WooCommerce performance. Optimizing MySQL/MariaDB involves tuning its configuration file (my.cnf or files in /etc/mysql/conf.d/) and understanding query performance.

Key Configuration Parameters

Several parameters in my.cnf significantly impact performance:

  • innodb_buffer_pool_size: The most critical setting for InnoDB. It caches data and indexes. Aim for 70-80% of your available RAM on a dedicated database server.
  • innodb_log_file_size: Larger log files can improve write performance but increase recovery time. A common starting point is 256MB or 512MB.
  • innodb_flush_log_at_trx_commit: Setting this to 2 (instead of the default 1) can significantly boost write performance at a slight risk of losing the last second of transactions in a crash. For most WooCommerce sites, this is an acceptable trade-off.
  • max_connections: Ensure this is high enough to handle concurrent application requests, but not so high that it exhausts server memory.
  • query_cache_size (deprecated in MySQL 5.7, removed in 8.0): If using an older version, a small query cache might help for identical, frequently executed read queries, but it can also cause contention. Generally, it’s better to rely on application-level caching and proper indexing.
  • tmp_table_size and max_heap_table_size: Control the size of in-memory temporary tables.
[mysqld]
# General Settings
max_connections = 300
# ...

# InnoDB Settings
innodb_buffer_pool_size = 8G       ; Example for a server with 10GB RAM
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2 ; Performance boost, slight risk
innodb_file_per_table = 1          ; Recommended for better manageability
innodb_io_capacity = 200           ; Tune based on your EBS volume type
innodb_io_capacity_max = 400       ; Tune based on your EBS volume type

# Temporary Tables
tmp_table_size = 64M
max_heap_table_size = 64M

# Query Cache (if applicable and supported)
# query_cache_type = 1
# query_cache_size = 32M

Query Optimization and Indexing

Even with perfect configuration, poorly written queries will cripple performance. Use tools like:

  • EXPLAIN: Prefix your SQL queries with EXPLAIN to understand how MySQL executes them. Look for full table scans (type: ALL) and missing indexes.
  • Slow Query Log: Enable and analyze the slow query log (slow_query_log = 1, long_query_time = 2) to identify problematic queries.
  • Percona Toolkit (pt-query-digest): A powerful tool for analyzing slow query logs.

Common WooCommerce queries that benefit from indexing include those related to product lookups, order processing, user sessions, and cart operations. Pay close attention to tables like wp_posts, wp_options, wp_wc_order_stats, and wp_wc_product_attributes_lookup.

-- Example: Add an index to speed up product meta queries
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key (meta_key);
ALTER TABLE wp_postmeta ADD INDEX idx_meta_value (meta_value(255)); -- Indexing prefixes of long text fields

-- Example: Index for order status lookups
ALTER TABLE wp_posts ADD INDEX idx_post_type_status (post_type, post_status);

AWS Infrastructure Considerations

The underlying AWS infrastructure plays a vital role. Choosing the right EC2 instance types (e.g., compute-optimized for CPU-intensive tasks, memory-optimized for caching), EBS volume types (gp3 for general purpose, io2 for high IOPS), and RDS configurations (if using managed databases) is foundational.

EBS Volume Tuning

For database servers, consider using io2 Block Express volumes for the highest performance and lowest latency. For application servers, gp3 volumes offer a good balance of performance and cost, allowing independent scaling of IOPS and throughput.

RDS Performance Insights

If using Amazon RDS for MySQL/MariaDB, leverage Performance Insights. It provides a visual dashboard to monitor database load and identify performance bottlenecks, SQL queries, and wait events without requiring extensive manual configuration or downtime.

Caching Layers

Beyond Nginx caching, consider implementing:

  • Object Caching (Redis/Memcached): Use plugins like W3 Total Cache or WP Rocket with Redis integration to cache database query results, object data, and transients. This dramatically reduces database load.
  • CDN (CloudFront): Serve static assets (images, CSS, JS) from a Content Delivery Network to reduce latency for global users and offload traffic from your origin servers.

Monitoring and Iteration

Performance tuning is an ongoing process. Implement robust monitoring using tools like:

  • CloudWatch: Monitor EC2 CPU utilization, network I/O, EBS IOPS, and RDS metrics. Set up alarms for critical thresholds.
  • Prometheus/Grafana: For more granular application and system-level metrics.
  • New Relic/Datadog: Application Performance Monitoring (APM) tools to trace requests, identify slow code paths, and monitor database queries in real-time.
  • WebPageTest/GTmetrix: External tools to simulate user experience and identify frontend performance issues.

Regularly review these metrics, identify bottlenecks, and iterate on your Nginx, Gunicorn/PHP-FPM, and MySQL configurations. Small, incremental changes backed by data are more effective than large, speculative overhauls.

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

  • Disaster Recovery 101: Architecting Auto-Failovers for Redis and PHP Deployments on OVH
  • How We Audited a High-Traffic WooCommerce Enterprise Stack on Google Cloud and Mitigated Race conditions during high-concurrency payment processing
  • Disaster Recovery 101: Architecting Auto-Failovers for Elasticsearch and Magento 2 Deployments on DigitalOcean
  • An Auditor’s Checklist for Securing WordPress Backends on OVH
  • Step-by-Step: Diagnosing Perl script high CPU throttling due to unoptimized regular expressions on AWS Servers

Copyright © 2026 · Vinay Vengala