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

Vengala Vinay

Having 12+ 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 DigitalOcean for Magento 2

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

Nginx Configuration for Magento 2 Performance

Optimizing Nginx is crucial for serving static assets efficiently and proxying requests to your Magento backend. We’ll focus on key directives that impact performance and security.

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. worker_connections defines the maximum number of simultaneous connections that each worker process can handle. A common starting point is 1024, but this can be increased based on your server’s RAM and expected load.

nginx.conf Snippet

worker_processes auto;
worker_connections 4096; # Adjust based on RAM and load

Buffering and Caching

Nginx’s buffering directives control how it handles request and response bodies. For Magento, tuning client_body_buffer_size and client_max_body_size is important, especially for uploads. Caching static assets aggressively is paramount. We’ll leverage proxy_cache for dynamic content and browser caching for static files.

Static Asset Caching (Server Block)

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

Proxy Caching (Server Block)

This configuration assumes you have a proxy_cache_path defined in your main nginx.conf. For Magento, it’s often beneficial to cache pages for logged-out users. Be cautious with caching for logged-in users due to personalization.

# Define proxy_cache_path in nginx.conf:
# proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=magento_cache:100m max_size=10g inactive=60m use_temp_path=off;

# In your Magento server block:
proxy_cache magento_cache;
proxy_cache_valid 200 302 10m; # Cache successful responses for 10 minutes
proxy_cache_valid 404 1m;      # Cache 404s for 1 minute
proxy_cache_key "$scheme$request_method$host$request_uri";
proxy_cache_bypass $http_pragma $http_authorization;
proxy_no_cache $http_pragma $http_authorization;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
add_header X-Cache-Status $upstream_cache_status;

# Exclude certain requests from caching (e.g., AJAX, admin, checkout)
location ~* ^/(admin|checkout|rest|V1)/ {
    proxy_cache off;
}
location ~* AJAX/ {
    proxy_cache off;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
    expires max;
    add_header Cache-Control "public, immutable";
}

Gzip Compression

Enabling Gzip compression significantly reduces the size of text-based assets (HTML, CSS, JS), leading to faster load times. Ensure you’re not double-compressing already compressed assets like images.

gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
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;
gzip_disable "msie6"; # Disable for older IE versions

HTTP/2 and TLS Optimization

HTTP/2 offers multiplexing and header compression, improving performance. TLS 1.3 is faster and more secure. Ensure your SSL certificate is valid and your cipher suites are modern.

listen 443 ssl http2;
listen [::]:443 ssl http2;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s; # Use your preferred DNS resolvers
resolver_timeout 5s;

Gunicorn/PHP-FPM Tuning for Magento 2

The application server (Gunicorn for Python-based frameworks, PHP-FPM for PHP) is the bridge between Nginx and your Magento application. Proper tuning here is critical for handling concurrent requests and managing resources.

Gunicorn Configuration (Python/Magento 2)

For a Python-based Magento implementation (less common but possible with frameworks like Django/Flask), Gunicorn’s worker types and counts are key. The sync worker type is the default and simplest, but gevent or event workers can offer better concurrency under I/O-bound loads.

Worker Count Calculation

A common starting point for worker processes is (2 * number_of_cores) + 1. However, for I/O-bound applications like Magento, you might increase this. Monitor CPU and memory usage closely.

Gunicorn Command Line Example

gunicorn --workers 4 --worker-class gevent --bind 0.0.0.0:8000 myapp.wsgi:application

PHP-FPM Configuration (PHP/Magento 2)

PHP-FPM is the standard for PHP applications. The pm (process manager) setting is crucial. dynamic is often a good balance, allowing FPM to scale workers up and down. ondemand can save memory but might introduce latency on initial requests. static provides predictable performance but can be memory-intensive.

PHP-FPM Pool Configuration (www.conf)

Locate your PHP-FPM pool configuration file (e.g., /etc/php/8.1/fpm/pool.d/www.conf). Adjust the following directives:

; pm = dynamic ; pm.max_children = 50 ; pm.start_servers = 5 ; pm.min_spare_servers = 2 ; pm.max_spare_servers = 10 ; pm.process_idle_timeout = 10s ; pm.max_requests = 500 ; request_terminate_timeout = 120s ; listen.owner = www-data ; listen.group = www-data ; listen.mode = 0660

Explanation:

  • pm.max_children: The maximum number of child processes that will be created. This is the most critical setting. Calculate based on available RAM. A common formula is (Total RAM - RAM for OS/Nginx) / Average PHP-FPM Process Size.
  • pm.start_servers: Number of child processes to start when PHP-FPM starts.
  • pm.min_spare_servers: Minimum number of idle supervisor processes.
  • pm.max_spare_servers: Maximum number of idle supervisor processes.
  • pm.max_requests: Maximum number of real requests each child process should execute. Setting this helps prevent memory leaks.
  • request_terminate_timeout: Maximum time a script is allowed to run. Crucial for preventing runaway scripts.

PHP Settings for Magento

Beyond FPM, core PHP settings in php.ini significantly impact Magento performance. Ensure you have sufficient memory limits and execution times.

memory_limit = 512M
max_execution_time = 300
max_input_vars = 3000
upload_max_filesize = 64M
post_max_size = 64M
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.enable_cli=1

MySQL Tuning for Magento 2

MySQL is often the bottleneck in Magento deployments. Aggressive tuning of its configuration is essential. We’ll focus on the mysqld section of my.cnf.

InnoDB Buffer Pool

The innodb_buffer_pool_size is the most critical setting for InnoDB performance. It caches data and indexes. A common recommendation is 70-80% of available RAM on a dedicated database server. On a shared server, adjust accordingly.

[mysqld]
innodb_buffer_pool_size = 4G ; Adjust based on available RAM (e.g., 4GB for an 8GB droplet)
innodb_buffer_pool_instances = 4 ; Number of buffer pool instances (typically 1 per GB of buffer pool size)

Query Cache (Deprecated/Removed in MySQL 8+)

The MySQL query cache is deprecated and removed in MySQL 8.0. If you are on an older version, it can sometimes help, but it often causes more contention than benefit in high-write environments like Magento. It’s generally recommended to disable it or ensure it’s off.

[mysqld]
query_cache_type = 0
query_cache_size = 0

Connection Handling

max_connections should be set high enough to accommodate your application’s needs but not so high that it exhausts server memory. thread_cache_size can improve performance by reusing threads.

[mysqld]
max_connections = 200 ; Adjust based on application needs and server RAM
thread_cache_size = 16 ; Cache threads for reuse

Logging and I/O

Disabling unnecessary logging in production can improve I/O performance. The slow query log is invaluable for debugging but should be configured carefully.

[mysqld]
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2 ; Log queries taking longer than 2 seconds
log_queries_not_using_indexes = 1 ; Log queries that don't use indexes

# For production, consider disabling general log if not actively debugging
# general_log = 0
# general_log_file = /var/log/mysql/mysql.log

Other Important Settings

[mysqld]
innodb_flush_log_at_trx_commit = 2 ; Trade-off between durability and performance. 2 is faster than 1.
innodb_flush_method = O_DIRECT ; Avoid double buffering with OS cache.
innodb_log_file_size = 512M ; Larger log files can improve write performance.
innodb_io_capacity = 2000 ; Adjust based on disk I/O capabilities.
innodb_io_capacity_max = 4000 ; Adjust based on disk I/O capabilities.
table_open_cache = 2000
table_definition_cache = 1000

Monitoring and Diagnostics

Tuning is an iterative process. Continuous monitoring is essential to identify bottlenecks and validate your changes. Use a combination of system-level and application-level tools.

System Monitoring

Tools like htop, iotop, vmstat, and netstat provide real-time insights into CPU, memory, disk I/O, and network usage.

# Monitor CPU and Memory
htop

# Monitor Disk I/O
sudo iotop

# Monitor System Statistics
vmstat 5

# Monitor Network Connections
sudo netstat -tulnp | grep -E 'nginx|php-fpm|mysqld'

Nginx Status and Cache

Enable Nginx’s status module to view active connections and cache performance.

# In nginx.conf:
# load_module modules/ngx_http_stub_status_module.so;

# In your server block:
location /nginx_status {
    stub_status;
    allow 127.0.0.1; # Restrict access
    deny all;
}

Access http://yourdomain.com/nginx_status to see metrics like:

  • Active connections: Current number of active client connections.
  • server accepts handled requests: Total requests handled.
  • reading writing waiting: Breakdown of worker connections.

Check the X-Cache-Status header in your browser’s developer tools to verify proxy cache hits/misses.

PHP-FPM Status

Enable the PHP-FPM status page for insights into process management.

; In your PHP-FPM pool config (e.g., www.conf):
pm.status_path = /fpm_status
; Add to your Nginx server block:
location ~ ^/fpm_status {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock; # Adjust socket path
    allow 127.0.0.1;
    deny all;
}

Access http://yourdomain.com/fpm_status for metrics like pool, process manager, start time, accepted conn, listen queue, max listen queue, idle processes, active processes, total processes, max active processes, max children reached.

MySQL Slow Query Log Analysis

Regularly analyze the slow query log to identify and optimize inefficient queries. Tools like pt-query-digest from Percona Toolkit are invaluable.

# Install Percona Toolkit (example for Debian/Ubuntu)
sudo apt-get update
sudo apt-get install percona-toolkit

# Analyze the slow query log
sudo pt-query-digest /var/log/mysql/mysql-slow.log > /var/log/mysql/mysql-slow-report.txt

Magento Specific Tools

Utilize Magento’s built-in profiling and caching mechanisms. Ensure you’re using Redis for session and cache storage where appropriate.

# Enable Magento Profiler (for development/debugging)
# app/etc/env.php
'profiler' => [
    'enabled' => true
],

# Clear Magento Cache
bin/magento cache:clean
bin/magento cache:flush

Conclusion

This playbook provides a robust starting point for tuning Nginx, Gunicorn/PHP-FPM, and MySQL for Magento 2 on DigitalOcean. Remember that every environment is unique. Continuously monitor, test, and iterate on these configurations based on your specific workload and hardware. Prioritize understanding the impact of each setting before applying it to a production environment.

Primary Sidebar

A little about the Author

Having 12+ Years of Experience in Software Development, Vinay is a principal software architect, senior systems engineer, and elite technical consultant. He specializes in bespoke PHP/WordPress development, high-performance Magento 2 & Shopify architectures, custom plugin/theme development from scratch, and legacy code modernization (including VB6, VB.NET, PyQt, and Crystal Reports). Known for solving complex database bottlenecks, speed optimization (Core Web Vitals), and advanced security code auditing, Vinay engineers production-ready systems designed to scale under heavy concurrent load conditions.



Chat on WhatsApp

Recent Posts

  • Orchestrating Serverless PHP 9 with AWS Lambda and API Gateway: A Deep Dive into Performance and Cost Optimization
  • Leveraging PHP 8.3 JIT and Vectorization for Extreme Performance in Laravel Applications
  • Leveraging PHP 9’s JIT Compiler and Concurrent Execution for High-Performance Laravel Microservices
  • Leveraging PHP 8.3 JIT and Vectorization for High-Throughput Microservices in a Laravel Ecosystem
  • Leveraging Laravel Octane and Docker Swarm for High-Performance, Scalable WordPress Headless Deployments

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (664)
  • Desktop Applications (14)
  • DevOps (11)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (6)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (873)
  • PHP (19)
  • PHP Development (49)
  • Plugins & Themes (244)
  • Programming Languages (10)
  • Python (20)
  • Ruby on Rails (1)
  • Security & Compliance (650)
  • SEO & Growth (492)
  • Server (118)
  • Softwares (1)
  • Ubuntu (9)
  • Uncategorized (24)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (26)
  • WordPress Plugin Development (728)
  • WordPress Theme Development (357)

Recent Posts

  • Orchestrating Serverless PHP 9 with AWS Lambda and API Gateway: A Deep Dive into Performance and Cost Optimization
  • Leveraging PHP 8.3 JIT and Vectorization for Extreme Performance in Laravel Applications
  • Leveraging PHP 9's JIT Compiler and Concurrent Execution for High-Performance Laravel Microservices

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (728)
  • Debugging & Troubleshooting (664)
  • Security & Compliance (650)
  • SEO & Growth (492)

Our Products

  • ERP & LMS Systems (4)
  • Directories & Marketplaces (4)
  • Healthcare Portals (3)
  • Point of Sale (POS) (2)
  • E-Commerce Engines (2)

Our Services

  • E-Commerce Development (10)
  • WordPress Development (8)
  • Python & Desktop GUI (7)
  • General Consulting (7)
  • Legacy Modernization (5)
  • Mobile App Development (4)

Copyright © 2026 · Vinay Vengala