• 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 AWS for Magento 2

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and Elasticsearch on AWS for Magento 2

Nginx Configuration for Magento 2 on AWS

Optimizing Nginx is crucial for serving static assets efficiently and proxying dynamic requests to your Magento 2 application. On AWS, leveraging Elastic Load Balancers (ELBs) or Application Load Balancers (ALBs) in front of Nginx instances requires specific configurations to ensure proper health checks, SSL termination, and request routing.

SSL Termination and HTTP/2

When using an ALB for SSL termination, Nginx will receive unencrypted HTTP traffic. It’s essential to enable HTTP/2 for improved performance. If Nginx is directly exposed (less common in production AWS setups), you’d configure SSL here.

Here’s a sample Nginx configuration snippet for a server block, assuming traffic is coming from an ALB (port 80):

Example Nginx Server Block (from ALB)

server {
    listen 80 http2;
    server_name your-magento-domain.com;

    # Enable 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;

    # Define root and index files
    root /var/www/magento2/public_html;
    index index.php index.html index.htm;

    # Magento 2 specific location blocks
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Static assets caching
    location ~* ^/(media|static)/ {
        expires 365d;
        add_header Cache-Control "public, immutable";
        access_log off;
        log_not_found off;
    }

    # PHP-FPM configuration (assuming FPM is running on a separate socket or port)
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # Adjust PHP version and path
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        fastcgi_param MAGE_RUN_CODE "your_magento_store_code"; # Set your Magento store code
        fastcgi_param MAGE_RUN_TYPE "store"; # Or "website"
    }

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

    # Deny access to .git directory
    location ~ /\.git {
        deny all;
    }

    # Error pages
    error_page 404 /errors/404.php;
    error_page 500 502 503 504 /errors/50x.php;
}

Tuning Nginx Worker Processes and Connections

The worker_processes directive controls how many worker processes Nginx will spawn. Setting it to auto is often a good starting point, allowing Nginx to determine the optimal number based on CPU cores. worker_connections defines the maximum number of simultaneous connections that each worker process can handle.

Nginx Global Configuration Snippet

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 4096; # Adjust based on system limits and expected load
    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

    # Include other configurations
    include /etc/nginx/mime.types;
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Tuning Considerations:

  • worker_processes: Set to auto or the number of CPU cores.
  • worker_connections: This is limited by the system’s file descriptor limit. Ensure ulimit -n is set high enough (e.g., 65536 or more) for the Nginx user.
  • keepalive_timeout: A shorter timeout can free up connections faster, but too short can increase overhead.
  • sendfile on;: Crucial for efficient file transfers.
  • tcp_nopush on; and tcp_nodelay on;: Optimize TCP packet sending.

Gunicorn/PHP-FPM Tuning for Magento 2

Magento 2 is a PHP application. The choice is typically between PHP-FPM (for Nginx) or Gunicorn (if using a Python-based framework or a reverse proxy setup for PHP, which is less common for direct Magento deployments).

PHP-FPM Tuning

PHP-FPM (FastCGI Process Manager) is the standard way to interface PHP with web servers like Nginx. Tuning its process management is critical for handling concurrent requests.

PHP-FPM Pool Configuration (`www.conf`)

The primary configuration file is usually located at /etc/php/8.1/fpm/pool.d/www.conf (adjust version and path as needed). The most important directives are related to process management.

; /etc/php/8.1/fpm/pool.d/www.conf

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

; Process Manager Control
; pm = dynamic ; Options: static, dynamic, ondemand
pm = dynamic

; If pm.max_children is set to 'static', this is the number of child processes.
; If pm.max_children is set to 'dynamic' or 'ondemand', this is the maximum number of child processes that will be spawned.
pm.max_children = 100 ; Adjust based on available RAM and expected load

; If pm.max_children is set to 'dynamic', this is the desired number of child processes on average.
pm.min_spare_servers = 10 ; Adjust based on expected load fluctuations
pm.max_spare_servers = 20 ; Adjust based on expected load fluctuations

; If pm.max_children is set to 'ondemand', this is the number of child processes to be created on startup.
; pm.max_children = 5

; If pm.max_children is set to 'ondemand', this is the maximum number of child processes that will be spawned.
; pm.max_children = 10

; If pm.max_children is set to 'ondemand', this is the number of seconds each child process will live before being killed.
; pm.process_idle_timeout = 10s

; The number of requests each child process should execute before reexecuting.
; Setting this to 0 means infinite.
pm.max_requests = 500 ; Helps prevent memory leaks

; Other important settings
request_terminate_timeout = 60s ; Timeout for script execution
; rlimit_files = 1024 ; Adjust based on system limits
; rlimit_core = 0 ; Set to 0 to disable core dumps
; listen.owner = www-data
; listen.group = www-data
; listen.mode = 0660
; listen.acl =
; listen.backlog = -1
; pm.status_path = /status
; pm.ping.path = /ping
; pm.ping.response = pong
; pm.emergency_restart_threshold = 10
; pm.emergency_restart_interval = 10s
; pm.process_max = 128

Tuning Considerations:

  • pm: dynamic is generally recommended. static can offer slightly better performance but consumes more memory. ondemand is good for very low traffic but can have higher latency on initial requests.
  • pm.max_children: This is the most critical setting. It dictates how many PHP processes can run concurrently. Calculate this based on your server’s RAM. A rough estimate: (Total RAM - RAM for OS/Nginx/DB) / Average RAM per PHP process. Magento processes can be memory-intensive. Start conservatively and monitor.
  • pm.max_requests: Setting this prevents memory leaks from accumulating over time. A value between 250-1000 is common.
  • request_terminate_timeout: Ensure this is long enough for your longest-running Magento operations but not so long that it hangs indefinitely.

Gunicorn Tuning (If Applicable)

While not directly used for serving Magento 2 PHP, Gunicorn might be used in a microservices architecture or for other components. Its tuning focuses on worker processes and threads.

Example Gunicorn Command Line

gunicorn --workers 3 --threads 2 --bind 0.0.0.0:8000 myapp.wsgi:application

Tuning Considerations:

  • --workers: Typically set to (2 * number_of_cpu_cores) + 1.
  • --threads: For I/O-bound applications, increasing threads can improve concurrency.
  • --worker-class: Consider gevent or eventlet for asynchronous I/O.

Elasticsearch Tuning on AWS

Elasticsearch is vital for Magento 2’s catalog search and other features. Performance tuning involves JVM heap size, shard allocation, and indexing settings.

JVM Heap Size Configuration

The JVM heap size is configured in jvm.options, typically found in /etc/elasticsearch/jvm.options or similar paths depending on your installation method (e.g., Docker, package manager).

Example `jvm.options`

# /etc/elasticsearch/jvm.options

# Enable GC logging
-Xlog:gc*:file=/var/log/elasticsearch/gc.log:time,uptime,level,tags:filecount=32,filesize=64m

# Heap Size
# Set Xms and Xmx to the same value to prevent resizing
# Rule of thumb: No more than 50% of system RAM, and not exceeding 30-32GB.
-Xms4g
-Xmx4g

Tuning Considerations:

  • Set -Xms and -Xmx to the same value.
  • Allocate no more than 50% of the server’s RAM to the Elasticsearch heap.
  • Avoid exceeding 30-32GB due to compressed ordinary object pointers (compressed oops). If you need more than 32GB, consider alternative JVMs or architectures.
  • Monitor garbage collection (GC) activity. Frequent or long GC pauses indicate heap issues.

Shard Allocation and Indexing Settings

Proper shard management and indexing settings are crucial for search performance and stability.

Index Settings API Example

You can adjust settings dynamically using the Index Settings API. For Magento 2, the primary index is usually named `magento2`. You can check current settings with:

GET /magento2/_settings

To update settings (e.g., number of replicas, refresh interval):

PUT /magento2/_settings
{
  "index" : {
    "number_of_shards" : "5",
    "number_of_replicas" : "1",
    "refresh_interval" : "30s"
  }
}

Tuning Considerations:

  • number_of_shards: Should ideally match the number of data nodes in your cluster for even distribution. Too many shards can increase overhead. Magento’s default is often reasonable, but can be tuned.
  • number_of_replicas: Set to 1 for high availability. Increase for read-heavy workloads if performance is bottlenecked by read capacity.
  • refresh_interval: The default is 1s, making documents searchable almost immediately. For high-volume indexing, increasing this to 5s, 10s, or even 30s can significantly improve indexing throughput at the cost of slightly delayed search visibility.
  • Consider using Index Lifecycle Management (ILM) for managing indices over time, especially if you have time-series data or need to archive/delete old data.

AWS Specific Considerations

When deploying on AWS, leverage managed services and instance types optimized for your workload.

  • EC2 Instance Types: Choose instance types with sufficient vCPUs and RAM for Nginx, PHP-FPM, and Elasticsearch. Memory-optimized (R series) or compute-optimized (C series) instances are often suitable.
  • EBS Volumes: Use provisioned IOPS (io1/io2) or General Purpose SSD (gp3) volumes for Elasticsearch data directories to ensure consistent I/O performance.
  • Security Groups: Configure security groups to allow traffic only from necessary sources (e.g., ALB to Nginx, Nginx to PHP-FPM, application to Elasticsearch).
  • CloudWatch: Set up comprehensive monitoring for CPU utilization, memory usage, disk I/O, network traffic, and application-specific metrics (e.g., PHP-FPM active processes, Elasticsearch cluster health).
  • Elasticsearch Service (AWS Managed Elasticsearch): Consider using AWS Elasticsearch Service for managed Elasticsearch clusters. This offloads operational burden but requires careful configuration of instance types, storage, and access policies.

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