• 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 DynamoDB on OVH for Ruby

The Ultimate DevOps Playbook: Tuning Nginx, Gunicorn/FPM, and DynamoDB on OVH for Ruby

Nginx Configuration for Ruby Applications on OVH

Optimizing Nginx as a reverse proxy for Ruby applications, especially those using Gunicorn or Puma, on OVH infrastructure requires a granular approach. We’ll focus on key directives that impact connection handling, request buffering, and static file serving. This setup assumes a typical OVH VPS or dedicated server environment where you have root access.

Worker Processes and Connections

The `worker_processes` directive dictates how many worker processes Nginx will spawn. A common starting point is to set this to the number of CPU cores available. `worker_connections` defines the maximum number of simultaneous connections that each worker process can handle. The total maximum connections will be `worker_processes * worker_connections`.

For a typical 4-core OVH VPS, a good starting point would be:

worker_processes 4; # Or auto to let Nginx decide based on CPU cores

events {
    worker_connections 1024; # Adjust based on expected load and server memory
    # multi_accept on; # Can improve performance by accepting multiple connections at once
}

Buffering and Timeouts

Buffering directives control how Nginx handles request and response bodies. For upstream applications, it’s often beneficial to disable client request body buffering if your application can handle large uploads directly or if you want to reduce memory usage on the Nginx server. Timeouts are crucial to prevent hanging connections from consuming resources.

Consider these settings within your `server` block:

http {
    # ... other http settings ...

    client_body_buffer_size 128k;
    client_max_body_size 100m; # Adjust based on your application's needs for file uploads
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    send_timeout 60s;
    client_body_timeout 60s;
    client_header_timeout 60s;
    keepalive_timeout 65s;
    keepalive_requests 100;

    # Disable client request body buffering for upstream communication
    # This can be useful if your app server (Gunicorn/Puma) handles large uploads directly
    # client_body_in_file_only off;
    # client_body_in_single_buffer on;

    # Proxy settings
    proxy_connect_timeout 60s;
    proxy_send_timeout 60s;
    proxy_read_timeout 60s;
    proxy_buffer_size 16k;
    proxy_buffers 8 16k;
    proxy_busy_buffers_size 32k;
    proxy_temp_file_write_size 32k;

    # ... rest of http config ...
}

Gzip Compression

Enabling Gzip compression can significantly reduce bandwidth usage and improve perceived load times for text-based assets. Ensure your upstream application server is configured to handle compressed requests if you enable `Accept-Encoding` for upstream.

http {
    # ... other http settings ...

    gzip on;
    gzip_vary on;
    gzip_proxied any; # Compress responses for all proxied requests
    gzip_comp_level 6; # Compression level (1-9)
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
    gzip_min_length 1000; # Minimum response length to compress
    gzip_disable "msie6"; # Disable for older IE versions if necessary

    # ... rest of http config ...
}

Static File Serving

Offloading static file serving to Nginx is a fundamental optimization. Configure Nginx to serve static assets directly, bypassing your Ruby application entirely. This involves setting `expires` headers for caching and using `try_files` to efficiently locate files.

server {
    listen 80;
    server_name your_domain.com www.your_domain.com;

    # Serve static assets directly
    location ~ ^/(assets|images|javascripts|stylesheets)/ {
        root /path/to/your/rails/public; # Adjust to your Rails public directory
        expires 30d;
        add_header Cache-Control "public";
        access_log off; # Optionally disable access logs for static files
        try_files $uri $uri/ =404;
    }

    # Proxy all other requests to your application server
    location / {
        proxy_pass http://unix:/path/to/your/app.sock; # Or http://127.0.0.1:8000 for TCP
        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;
        proxy_read_timeout 120s; # Longer timeout for application processing
        proxy_send_timeout 120s;
    }

    # ... other server configurations ...
}

Gunicorn/Puma Tuning for Ruby on Rails

The choice between Gunicorn and Puma often depends on the application’s I/O patterns and threading model. Both require careful tuning of worker processes, threads, and timeouts.

Gunicorn Configuration

Gunicorn is a WSGI HTTP Server. Its performance is heavily influenced by the number of worker processes and the worker class used. For CPU-bound tasks, a process-per-core model is often effective. For I/O-bound tasks, a threaded worker class might be beneficial.

A typical Gunicorn configuration file (e.g., gunicorn_config.py):

import multiprocessing

# Number of worker processes. A good starting point is 2 * number_of_cores + 1
workers = multiprocessing.cpu_count() * 2 + 1

# Worker class. 'sync' is the default and most stable.
# 'gevent' or 'eventlet' can be used for I/O bound applications with async libraries.
worker_class = 'sync'

# Bind to a Unix socket or TCP port.
# For Nginx proxying via Unix socket:
bind = "unix:/path/to/your/app.sock"
# For Nginx proxying via TCP:
# bind = "127.0.0.1:8000"

# Timeout for worker requests. Adjust based on your application's longest-running tasks.
timeout = 120

# Maximum number of requests a worker can handle before restarting.
# Helps prevent memory leaks.
max_requests = 5000
max_requests_jitter = 500 # Randomize max_requests to spread restarts

# Logging configuration
loglevel = 'info'
accesslog = '-' # Log to stdout, which can be captured by systemd/Docker
errorlog = '-'

# Threads for threaded worker classes (if not using 'sync')
# threads = 2 # Example for gevent/eventlet

To run Gunicorn with this configuration:

gunicorn --config gunicorn_config.py your_app.wsgi:application

Puma Configuration

Puma is a multi-threaded, multi-process web server for Ruby. It excels at handling concurrent requests due to its threading model. Tuning involves setting the number of workers (processes) and threads per worker.

A common way to configure Puma is via a config/puma.rb file in your Rails application:

# config/puma.rb

# Change to match your CPU core count
workers ENV.fetch("RAILS_MAX_THREADS") { 4 }.to_i

# Min threads per worker to use.
# A good starting point is 5.
min_threads_by_instance = ENV.fetch("RAILS_MIN_THREADS") { 5 }.to_i

# Max threads per worker to use.
# A good starting point is 5.
max_threads_by_instance = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i

threads min_threads_by_instance, max_threads_by_instance

# Bind to a Unix socket or TCP port.
# For Nginx proxying via Unix socket:
bind "unix:///path/to/your/app.sock"
# For Nginx proxying via TCP:
# bind "tcp://127.0.0.1:9292"

# Set the environment
environment ENV.fetch("RAILS_ENV") { "production" }

# Logging
stdout_redirect "/var/log/puma.stdout.log", "/var/log/puma.stderr.log", true

# Allow Puma to be restarted by `rails restart` command.
plugin :tmp_restart

# If using systemd, this is often handled by the service file
# pidfile "/path/to/your/app.pid"

# Increase worker timeout for long-running requests
worker_timeout 120

# Preload the application code to speed up worker startup
preload_app!

on_worker_boot do
  # Worker specific setup for Rails.
  # This is called after worker boot and before the worker starts accepting requests.
  ActiveRecord::Base.establish_connection if defined?(ActiveRecord::Base)
end

# Allow workers to share connections to the database, etc.
# This is a good idea for performance.
before_fork do
  ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord::Base)
end

To run Puma in clustered mode:

bundle exec puma -C config/puma.rb

DynamoDB Performance Tuning on OVH

While DynamoDB is a managed AWS service, its performance can be indirectly impacted by network latency and application-level interactions, especially when your application is hosted on OVH. Optimizing your DynamoDB usage involves understanding throughput, data modeling, and query patterns.

Throughput Provisioning

DynamoDB operates on a provisioned throughput model (or on-demand). For predictable workloads, provisioned throughput is often more cost-effective. Monitor your consumed read and write capacity units (RCUs and WCUs) and adjust provisioned capacity accordingly. OVH’s network latency to AWS regions will add to the round-trip time for every DynamoDB operation.

Use CloudWatch metrics to track:

  • ConsumedReadCapacityUnits
  • ConsumedWriteCapacityUnits
  • ProvisionedReadCapacityUnits
  • ProvisionedWriteCapacityUnits
  • ThrottledRequests (indicates you need more capacity)

Consider using DynamoDB Auto Scaling to automatically adjust provisioned throughput based on actual usage, which can help manage costs and prevent throttling.

Data Modeling and Query Optimization

The way you model your data in DynamoDB is paramount. Avoid full table scans. Design your primary keys (partition key and sort key) to support your most frequent access patterns. Use Global Secondary Indexes (GSIs) and Local Secondary Indexes (LSIs) judiciously to enable efficient querying on attributes other than the primary key.

When querying from an OVH-hosted application, minimize the number of requests. Batch operations (BatchGetItem, BatchWriteItem) can reduce network overhead. However, be mindful of their limitations (e.g., 100 items per batch for BatchGetItem).

# Example using Boto3 (Python SDK) for batch get
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('YourTableName')

response = table.batch_get_item(
    RequestItems={
        'YourTableName': {
            'Keys': [
                {'id': 'item1', 'range': 'sub1'},
                {'id': 'item2', 'range': 'sub2'},
                # ... up to 100 items
            ],
            # Optionally specify attributes to retrieve
            # 'ProjectionExpression': 'attribute1, attribute2'
        }
    }
)

items = response['Responses']['YourTableName']
# Handle unprocessed keys if any
if 'UnprocessedKeys' in response:
    print("Unprocessed keys:", response['UnprocessedKeys'])

Network Latency Considerations

The physical distance between your OVH servers and the AWS region hosting your DynamoDB table will introduce latency. Choose an AWS region geographically closest to your OVH data center to minimize this. Regularly test network performance between your OVH instances and AWS endpoints using tools like ping and traceroute.

# Example: Ping an AWS endpoint (replace with your region's endpoint)
ping dynamodb.us-east-1.amazonaws.com

# Example: Traceroute to an AWS endpoint
traceroute dynamodb.eu-west-2.amazonaws.com

If latency is a significant bottleneck, consider caching frequently accessed DynamoDB data in your application’s memory or using a distributed cache like Redis (which can also be hosted on OVH) to reduce direct DynamoDB calls.

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

  • Top 100 Automated PDF & Document Generation Tool Ideas for Developers that Will Dominate the Software Industry in 2026
  • Top 5 Automated PDF & Document Generation Tool Ideas for Developers in Highly Competitive Technical Niches
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers without Relying on Paid Advertising Budgets
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Double User Engagement and Session Duration
  • Building a Reactive Frontend Framework inside Theme Security Auditing: Mitigating XSS, CSRF, and SQLi Vulnerabilities under Heavy Concurrent Load Conditions

Categories

  • apache (1)
  • Business & Monetization (390)
  • Centos (4)
  • Comparisons & Decision Making (55)
  • Debian (2)
  • Debugging & Troubleshooting (580)
  • DevOps (7)
  • DevOps & Cloud Scaling (955)
  • Django (1)
  • Migration & Architecture (184)
  • MySQL (1)
  • Performance & Optimization (776)
  • PHP (5)
  • Plugins & Themes (238)
  • Security & Compliance (543)
  • SEO & Growth (488)
  • Server (23)
  • Ubuntu (9)
  • WordPress (22)
  • WordPress Plugin Development (7)
  • WordPress Theme Development (340)

Recent Posts

  • Top 100 Automated PDF & Document Generation Tool Ideas for Developers that Will Dominate the Software Industry in 2026
  • Top 5 Automated PDF & Document Generation Tool Ideas for Developers in Highly Competitive Technical Niches
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers without Relying on Paid Advertising Budgets
  • Top 50 Automated PDF & Document Generation Tool Ideas for Developers to Double User Engagement and Session Duration
  • Building a Reactive Frontend Framework inside Theme Security Auditing: Mitigating XSS, CSRF, and SQLi Vulnerabilities under Heavy Concurrent Load Conditions
  • Deep Dive: Memory Leak Prevention in Virtual CSS Variables and Dynamic Style Interpolation Using Custom Action and Filter Hooks

Top Categories

  • DevOps & Cloud Scaling (955)
  • Performance & Optimization (776)
  • Debugging & Troubleshooting (580)
  • Security & Compliance (543)
  • SEO & Growth (488)
  • Business & Monetization (390)

Our Products

  • School Management & Student Administration System
  • Integrated Hospital & Clinic Management System
  • Real Estate Directory & Agent Portal
  • Restaurant POS & Table Booking System
  • Retail Inventory POS & Billing System
  • Pharmacy Inventory & Clinic Billing System

Our Services

  • Vibe Engineering & AI Code Auditing Services
  • Prompt Engineering & "Vibe Coding" Workflow Consulting
  • AI-Augmented "Vibe Coding" & Rapid MVP Development
  • Figma to Shopify Liquid Theme Customization
  • Figma to WooCommerce Frontend Development
  • Figma to Magento 2 Theme Development

Copyright © 2026 · Vinay Vengala