• 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 PostgreSQL on OVH for PHP

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and PostgreSQL on OVH for PHP

Nginx as a High-Performance Frontend for PHP Applications

When deploying PHP applications, especially those leveraging modern frameworks and APIs, Nginx serves as an exceptionally efficient frontend. Its asynchronous, event-driven architecture excels at handling a high volume of concurrent connections, offloading the heavy lifting from your application servers. The key to unlocking Nginx’s full potential lies in meticulous configuration, particularly around worker processes, connection limits, and efficient static file serving.

Tuning Nginx Worker Processes and Connections

The `worker_processes` directive dictates how many worker processes Nginx will spawn. A common best practice is to set this to the number of CPU cores available on your server. This allows Nginx to fully utilize your hardware without excessive context switching. 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. It’s crucial to ensure that the system’s file descriptor limit (`ulimit -n`) is set high enough to accommodate the aggregate connections.

Nginx Configuration Snippet

# /etc/nginx/nginx.conf

user www-data;
worker_processes auto; # Or set to the number of CPU cores, e.g., worker_processes 4;

events {
    worker_connections 4096; # Adjust based on expected load and system limits
    multi_accept on;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    server_tokens off; # Hide Nginx version for security

    # ... other http configurations ...

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Optimizing PHP-FPM or Gunicorn for PHP

For PHP applications, PHP-FPM (FastCGI Process Manager) is the de facto standard for bridging Nginx and PHP. For Python applications serving PHP (less common but possible with frameworks like Flask/Django serving PHP components or via specific integrations), Gunicorn is the go-to WSGI HTTP Server. The tuning of these process managers is critical for application responsiveness and resource utilization.

PHP-FPM Tuning: Process Management and Resource Allocation

PHP-FPM offers several process management strategies: `static`, `dynamic`, and `ondemand`. For production environments with predictable load, `static` often provides the best performance by keeping a fixed pool of workers ready. `dynamic` is a good compromise, scaling workers up and down based on demand but with a slight overhead. `ondemand` is resource-efficient but can introduce latency on initial requests.

PHP-FPM Configuration Snippet (`/etc/php/8.1/fpm/pool.d/www.conf`)

; pm = dynamic ; Default, good for general use
pm = static ; Recommended for predictable high-load production

; For pm = static:
pm.max_children = 50 ; Adjust based on available RAM and expected concurrent requests
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30

; For pm = dynamic:
; pm.max_children = 350
; pm.start_servers = 5
; pm.min_spare_servers = 2
; pm.max_spare_servers = 8
; pm.max_requests = 500 ; Restart a child after this many requests

; Other important settings:
request_terminate_timeout = 60 ; Max execution time for a script
; listen = /run/php/php8.1-fpm.sock ; Default socket, ensure Nginx uses this
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

Important Note: The `pm.max_children` value is paramount. It should be set such that the total memory consumed by all `max_children` processes, plus Nginx and PostgreSQL, does not exceed your server’s available RAM. A common starting point is to estimate the average memory footprint of a PHP-FPM worker and multiply it by your desired `max_children` count. Monitor memory usage closely after deployment.

Gunicorn Tuning (for Python/PHP integrations or Python apps)

If you’re using Gunicorn to serve a Python application that might interact with PHP components or if you’re running a Python-based web service, tuning Gunicorn is essential. The `workers` setting is analogous to PHP-FPM’s `max_children`. A common recommendation is `(2 * number_of_cores) + 1` for the number of worker processes. The `threads` setting can be used for I/O-bound tasks, but be mindful of the Global Interpreter Lock (GIL) in CPython.

Gunicorn Command Line / Configuration Snippet

# Example command line:
gunicorn --workers 4 --threads 2 --bind 0.0.0.0:8000 myapp.wsgi:application

# Example Gunicorn configuration file (e.g., gunicorn_config.py):
# workers = 4
# threads = 2
# bind = "0.0.0.0:8000"
# worker_class = "sync" # or "gevent", "eventlet" for async I/O
# max_requests = 1000
# timeout = 30

PostgreSQL Performance Tuning on OVH

PostgreSQL’s performance is heavily influenced by its configuration parameters, particularly those related to memory allocation, caching, and query planning. On OVH, you’ll typically have dedicated or VPS instances where you can directly tune PostgreSQL. The `postgresql.conf` file is your primary tool.

Key PostgreSQL Configuration Parameters

  • `shared_buffers`: This is arguably the most critical parameter. It defines the amount of memory PostgreSQL can use for caching data. A common recommendation is 25% of your total system RAM, but never more than what your OS can effectively manage for other processes. For a 16GB RAM server, 4GB (`4096MB`) is a reasonable starting point.
  • `work_mem`: Memory used for internal sort operations and hash tables. If `work_mem` is too low, PostgreSQL will spill to disk, significantly slowing down queries involving sorts or hashes. Set this based on the complexity of your queries and available RAM. Start with 16MB and increase if you see “spilling to disk” warnings in logs or slow sort operations.
  • `maintenance_work_mem`: Memory used for maintenance operations like `VACUUM`, `CREATE INDEX`, and `ALTER TABLE`. A larger value can significantly speed up these operations. 128MB to 512MB is common for dedicated database servers.
  • `effective_cache_size`: This parameter informs the query planner about how much memory is available for disk caching by the operating system and PostgreSQL’s shared buffers. A good estimate is 50-75% of total RAM.
  • `max_connections`: The maximum number of concurrent connections. Ensure this is high enough for your application but not so high that it exhausts system resources. Each connection consumes memory.
  • `wal_buffers`: Buffers for Write-Ahead Logging (WAL). A value of -1 (auto-tune) or a small fixed value like 16MB is often sufficient.
  • `checkpoint_completion_target`: Controls how aggressively checkpoints are performed. A value of 0.9 is often recommended to spread checkpoint I/O over time.

PostgreSQL Configuration Snippet (`/etc/postgresql/14/main/postgresql.conf`)

# Example for a server with 16GB RAM

shared_buffers = 4GB
work_mem = 32MB ; Adjust upwards if complex sorts/hashes are slow
maintenance_work_mem = 256MB
effective_cache_size = 12GB
max_connections = 100 ; Adjust based on application needs and server capacity
wal_buffers = 16MB
checkpoint_completion_target = 0.9
random_page_cost = 1.1 ; Lowering this can favor sequential scans if you have fast storage
effective_io_concurrency = 200 ; For SSDs, tune based on IOPS capabilities
max_worker_processes = 8 ; Typically set to number of CPU cores
max_parallel_workers_per_gather = 4 ; Tune based on cores and workload
max_parallel_workers = 8 ; Tune based on cores and workload

# Logging for performance analysis
log_min_duration_statement = 250 ; Log queries slower than 250ms
log_checkpoints = on
log_connections = on
log_disconnections = on
log_lock_waits = on
log_temp_files = 0 ; Log temporary files larger than this size (in KB)
log_autovacuum_min_duration = 1000 ; Log autovacuum actions taking longer than 1s

After modifying `postgresql.conf`, a PostgreSQL service restart is required: sudo systemctl restart postgresql.

Monitoring and Iterative Tuning

Tuning is not a one-time event. Continuous monitoring is essential to identify bottlenecks and validate your optimizations. Key metrics to track include:

Key Monitoring Metrics

  • Nginx: Active connections, requests per second, error rates (4xx, 5xx), worker connections usage. Use `nginx-status` module or Prometheus exporters.
  • PHP-FPM/Gunicorn: Process count, request latency, memory usage per worker, error logs.
  • PostgreSQL: CPU utilization, memory usage, disk I/O, active connections, query execution times, cache hit ratios, WAL activity. Tools like pg_stat_activity, pg_stat_statements, and Prometheus exporters are invaluable.
  • System: Overall CPU load, memory usage (free vs. used, swap usage), disk I/O wait times.

Use tools like Prometheus with Grafana for comprehensive dashboarding and alerting. Regularly review PostgreSQL slow query logs and Nginx error logs. Make incremental changes to configuration parameters and observe their impact. The goal is to find the sweet spot that balances performance, resource utilization, and stability for your specific workload on OVH infrastructure.

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

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability
  • Scala Pekko vs. Go Goroutines: Actor Model vs. CSP for Event-Driven Reactive Systems
  • Java Loom Virtual Threads vs. Go Goroutines: Under-the-Hood Scheduler and Thread Overhead Comparison

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (584)
  • Desktop Applications (14)
  • DevOps (7)
  • DevOps & Cloud Scaling (962)
  • Django (1)
  • Laravel (4)
  • Migration & Architecture (192)
  • Mobile Applications (24)
  • MySQL (1)
  • Performance & Optimization (806)
  • PHP (5)
  • PHP Development (21)
  • Plugins & Themes (244)
  • Programming Languages (9)
  • Python (19)
  • Ruby on Rails (1)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Server (23)
  • Ubuntu (9)
  • VB6 & VB.NET (8)
  • Web Applications & Frontend (19)
  • Web Assembly (Wasm) (2)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (357)

Recent Posts

  • Go Goroutines vs. Node.js Event Loop: Scaling I/O-Bound Microservices Under High Load
  • Elixir Phoenix vs. Go Gin: Concurrency Models and Fault Tolerance Under Peak Request Volume
  • Python Celery vs. Go Channels: Distributed Task Queue Overhead and Memory Reliability

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (806)
  • Debugging & Troubleshooting (584)
  • Security & Compliance (543)
  • SEO & Growth (491)
  • Business & Monetization (390)

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