• 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 » Installing and Tuning Uvicorn + Gunicorn process trees on Ubuntu 24.04 LTS for high-traffic FastAPI Backends

Installing and Tuning Uvicorn + Gunicorn process trees on Ubuntu 24.04 LTS for high-traffic FastAPI Backends

System Preparation and Initial Setup

This guide focuses on deploying and optimizing FastAPI applications using Uvicorn and Gunicorn on Ubuntu 24.04 LTS. We’ll cover the installation, configuration, and advanced tuning required for high-traffic scenarios. Ensure your system is up-to-date before proceeding.

Begin by updating your package lists and upgrading existing packages:

sudo apt update && sudo apt upgrade -y

Next, install Python 3, pip, and the `venv` module, which is crucial for isolated Python environments. Ubuntu 24.04 typically ships with Python 3.12, which is well-suited for modern FastAPI development.

sudo apt install python3 python3-pip python3-venv -y

Creating a Virtual Environment and Installing Dependencies

It’s best practice to isolate your application’s dependencies. Create a dedicated directory for your FastAPI application and set up a Python virtual environment.

mkdir ~/my_fastapi_app
cd ~/my_fastapi_app
python3 -m venv venv
source venv/bin/activate

With the virtual environment activated, install FastAPI, Uvicorn (as an ASGI server), and Gunicorn (as a process manager). We’ll also install `uvicorn[standard]` for enhanced performance features.

pip install fastapi uvicorn[standard] gunicorn

Create a simple FastAPI application for testing purposes. Save this as main.py within your application directory.

from fastapi import FastAPI
import time

app = FastAPI()

@app.get("/")
async def read_root():
    # Simulate some work
    time.sleep(0.1)
    return {"Hello": "World"}

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}

Running with Uvicorn Directly (for Development/Testing)

Before moving to Gunicorn, verify your application runs correctly with Uvicorn. This command starts Uvicorn with 4 worker processes, suitable for initial testing.

uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

You can test this locally by navigating to http://localhost:8000 in your browser or using curl.

curl http://localhost:8000

Configuring Gunicorn with Uvicorn Workers

Gunicorn will act as the master process, spawning and managing Uvicorn worker processes. This provides better process management, signal handling, and stability under load.

Create a Gunicorn configuration file, typically named gunicorn_config.py, in your application’s root directory. This file allows for fine-grained control over Gunicorn’s behavior.

import multiprocessing

# Bind to a specific IP and port
bind = "0.0.0.0:8000"

# Number of worker processes. A common starting point is (2 * number_of_cores) + 1.
# We'll use a dynamic approach here.
workers = multiprocessing.cpu_count() * 2 + 1

# Use Uvicorn workers
# The 'worker_class' should be set to 'uvicorn.workers.UvicornWorker'
worker_class = "uvicorn.workers.UvicornWorker"

# Maximum number of requests a worker can handle before restarting.
# This helps prevent memory leaks.
max_requests = 1000

# Timeout in seconds for worker processes.
# Adjust based on your application's typical request latency.
timeout = 30

# Logging configuration
loglevel = "info"
accesslog = "-" # Log to stdout
errorlog = "-"  # Log to stderr

# Optional: Threads per worker (if using Uvicorn's asyncio workers)
# threads = 2 # This is more relevant for Uvicorn's default workers, but can be set.

Now, run your application using Gunicorn, pointing it to your FastAPI app instance and specifying the configuration file.

gunicorn -c gunicorn_config.py main:app

Setting up Systemd for Production Deployment

For production, you need a robust way to manage your Gunicorn process. Systemd is the standard init system on Ubuntu and is ideal for this. Create a systemd service file.

First, create a dedicated user for your application to run under, enhancing security.

sudo useradd -r -m -s /bin/false myfastapiuser

Now, create the systemd service file. Replace /path/to/your/app with the actual path to your application directory and myfastapiuser with the user you just created.

[Unit]
Description=Gunicorn instance to serve my FastAPI application
After=network.target

[Service]
User=myfastapiuser
Group=myfastapiuser
WorkingDirectory=/path/to/your/app
ExecStart=/path/to/your/app/venv/bin/gunicorn \
          --workers 4 \
          --bind unix:/run/myfastapi.sock \
          main:app

# Optional: If you prefer to use the gunicorn_config.py file
# ExecStart=/path/to/your/app/venv/bin/gunicorn \
#           -c /path/to/your/app/gunicorn_config.py \
#           main:app

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Save this file as /etc/systemd/system/myfastapi.service. Ensure the path to gunicorn points to the executable within your virtual environment.

Reload the systemd daemon, start the service, and enable it to start on boot.

sudo systemctl daemon-reload
sudo systemctl start myfastapi
sudo systemctl enable myfastapi

Check the status of your service:

sudo systemctl status myfastapi

Integrating with Nginx as a Reverse Proxy

For production, Nginx is an excellent choice for a reverse proxy, handling SSL termination, load balancing, and serving static files efficiently. We’ll configure Nginx to proxy requests to the Gunicorn socket.

Install Nginx if you haven’t already:

sudo apt install nginx -y

Create an Nginx server block configuration file for your application. Replace your_domain.com with your actual domain name.

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

    location / {
        proxy_pass http://unix:/run/myfastapi.sock;
        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;
    }

    # Optional: Serve static files directly if your FastAPI app doesn't handle them
    # location /static/ {
    #     alias /path/to/your/app/static/;
    # }

    # Optional: Add SSL configuration here for HTTPS
    # listen 443 ssl;
    # ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    # ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    # include /etc/letsencrypt/options-ssl-nginx.conf;
    # ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

Save this file as /etc/nginx/sites-available/myfastapi. Then, create a symbolic link to enable the site and test the Nginx configuration.

sudo ln -s /etc/nginx/sites-available/myfastapi /etc/nginx/sites-enabled/
sudo nginx -t

If the test is successful, reload Nginx.

sudo systemctl reload nginx

Performance Tuning and Advanced Considerations

Tuning involves several key areas:

  • Worker Processes (Gunicorn): The workers = multiprocessing.cpu_count() * 2 + 1 formula is a good starting point for I/O-bound applications. For CPU-bound tasks, you might reduce this to multiprocessing.cpu_count(). Monitor CPU and memory usage to find the optimal number.
  • Worker Class (Uvicorn): Ensure you are using uvicorn.workers.UvicornWorker. Uvicorn’s workers are asynchronous and generally perform better than Gunicorn’s default synchronous workers for I/O-bound workloads common in web APIs.
  • Max Requests: Setting max_requests (e.g., 1000) helps mitigate memory leaks by periodically restarting workers. Adjust this value based on your application’s memory footprint over time.
  • Timeouts: The timeout setting in Gunicorn prevents workers from hanging indefinitely. For long-running operations, consider using background task queues (like Celery or RQ) instead of blocking the web server.
  • Keep-Alive Connections: Nginx’s default keep-alive settings are usually sufficient. Ensure your Nginx configuration is optimized for connection handling.
  • Asynchronous Code: Write your FastAPI application using async/await extensively. Blocking I/O operations within async functions will negate the benefits of Uvicorn and FastAPI. Use libraries that support async operations (e.g., httpx for HTTP requests, asyncpg for PostgreSQL).
  • Database Connections: Use an asynchronous database driver (e.g., asyncpg for PostgreSQL, aiomysql for MySQL) and manage connection pools efficiently.
  • Caching: Implement caching strategies (e.g., Redis) for frequently accessed data to reduce database load and response times.
  • Load Testing: Use tools like locust or k6 to simulate high traffic and identify bottlenecks before deploying to production.

For very high-traffic scenarios, consider a multi-process, multi-worker setup with Nginx acting as a load balancer across multiple Gunicorn instances, potentially on different servers.

Monitoring and Logging

Effective monitoring and logging are critical for identifying and resolving issues in production.

  • Systemd Journal: Gunicorn logs to stdout/stderr by default when configured via systemd. You can access these logs using journalctl.
sudo journalctl -u myfastapi -f
  • Nginx Logs: Monitor Nginx access and error logs for issues related to request handling and proxying.
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log
  • Application-Level Logging: Implement structured logging within your FastAPI application using libraries like structlog or Python’s built-in logging module, configured to output JSON for easier parsing by log aggregation tools (e.g., ELK stack, Splunk).
  • Performance Monitoring: Integrate Application Performance Monitoring (APM) tools like Datadog, New Relic, or Sentry to gain deep insights into request latency, error rates, and resource utilization.

By following these steps, you can establish a robust, scalable, and performant deployment of your FastAPI application on Ubuntu 24.04 LTS, ready to handle significant traffic loads.

Reader Interactions

Leave a Reply Cancel reply

You must be logged in to post a comment.

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

  • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
  • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
  • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store
  • How to refactor legacy event ticket registers queries using modern WP_Query and custom Transient caching
  • Step-by-Step Guide: Offloading high-frequency member profile directories metadata writes to a Redis KV store

Categories

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

Recent Posts

  • Debugging Guide: Diagnosing PHP-FPM child process pool exhaustion in multi-site network environments with modern tools
  • Debugging and Resolving complex namespace class loading collisions issues during heavy concurrent database traffic
  • Step-by-Step Guide: Offloading high-frequency customer support tickets metadata writes to a Redis KV store

Top Categories

  • DevOps & Cloud Scaling (962)
  • Performance & Optimization (873)
  • WordPress Plugin Development (726)
  • Debugging & Troubleshooting (662)
  • Security & Compliance (647)
  • 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