Skip to main content

FastAPI Uvicorn Configuration

When deploying FastAPI applications to production, proper configuration of the Uvicorn server is essential for performance, reliability, and security. In this guide, we'll explore how to configure Uvicorn to get the most out of your FastAPI applications.

What is Uvicorn?

Uvicorn is an ASGI (Asynchronous Server Gateway Interface) server implementation that serves as the recommended server for running FastAPI applications. It's lightning-fast, built on uvloop and httptools, and designed specifically for asynchronous Python applications.

Basic Uvicorn Configuration

Let's start with a simple FastAPI application and see how to launch it with Uvicorn:

python
# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
return {"message": "Hello World"}

To run this application with Uvicorn, you can use either:

  1. Command line:
bash
uvicorn main:app --reload
  1. Programmatically in Python:
python
# start_server.py
import uvicorn

if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

Core Configuration Options

Uvicorn provides many configuration options that can be set either via command-line arguments or programmatically:

Host and Port

bash
uvicorn main:app --host 0.0.0.0 --port 8000

Programmatically:

python
uvicorn.run("main:app", host="0.0.0.0", port=8000)
  • host="0.0.0.0": Makes the server available externally
  • port=8000: Sets the port number (default is 8000)

Reload Mode

Enable auto-reload when files change (great for development):

bash
uvicorn main:app --reload

Programmatically:

python
uvicorn.run("main:app", reload=True)

You can also specify which directories to watch:

bash
uvicorn main:app --reload --reload-dir=app --reload-dir=utils
python
uvicorn.run("main:app", reload=True, reload_dirs=["app", "utils"])

Production Configuration

For production environments, you'll want to optimize performance and ensure reliability:

Workers

In production, you should run multiple worker processes to utilize all CPU cores:

bash
uvicorn main:app --workers 4

A good rule of thumb is to use 2 * number_of_cores + 1 workers.

note

To use multiple workers directly with Uvicorn, you'll need to use Gunicorn as a process manager:

bash
gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app

Programmatically with Gunicorn:

python
from gunicorn.app.base import BaseApplication

class StandaloneApplication(BaseApplication):
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()

def load_config(self):
for key, value in self.options.items():
if key in self.cfg.settings and value is not None:
self.cfg.set(key.lower(), value)

def load(self):
return self.application

if __name__ == "__main__":
options = {
"bind": "0.0.0.0:8000",
"workers": 4,
"worker_class": "uvicorn.workers.UvicornWorker",
}

from main import app
StandaloneApplication(app, options).run()

Concurrency and Performance Tuning

Uvicorn offers several options to fine-tune performance:

bash
# Limit the number of concurrent connections
uvicorn main:app --limit-concurrency 1000

# Limit the maximum number of requests per worker
uvicorn main:app --limit-max-requests 10000

Programmatically:

python
uvicorn.run(
"main:app",
host="0.0.0.0",
port=8000,
limit_concurrency=1000,
limit_max_requests=10000
)

Timeout Configuration

Set timeouts to protect your application from slow clients:

bash
# Keep-alive timeout (seconds)
uvicorn main:app --timeout-keep-alive 5

Programmatically:

python
uvicorn.run("main:app", timeout_keep_alive=5)

HTTPS Configuration

For secure HTTPS connections, provide SSL certificate files:

bash
uvicorn main:app --ssl-keyfile key.pem --ssl-certfile cert.pem

Programmatically:

python
uvicorn.run(
"main:app",
host="0.0.0.0",
port=443,
ssl_keyfile="key.pem",
ssl_certfile="cert.pem"
)

Logging Configuration

Configure logging to help with debugging and monitoring:

bash
# Set log level
uvicorn main:app --log-level debug

# Enable access log
uvicorn main:app --access-log

Programmatically:

python
uvicorn.run("main:app", log_level="debug", access_log=True)

You can also configure a custom logging configuration:

bash
uvicorn main:app --log-config logging.conf
python
uvicorn.run("main:app", log_config="logging.conf")

Full Production Example

Let's create a comprehensive production setup for a FastAPI application:

python
# production.py
import multiprocessing
import uvicorn
import os

if __name__ == "__main__":
# Determine number of workers based on CPU cores
workers_count = (multiprocessing.cpu_count() * 2) + 1

# Get port from environment variable or use default
port = int(os.environ.get("PORT", 8000))

# Configure Uvicorn with production settings
uvicorn.run(
"main:app",
host="0.0.0.0",
port=port,
workers=workers_count,
log_level="info",
access_log=True,
limit_concurrency=1000,
timeout_keep_alive=5,

# Enable HTTPS if certificates are available
ssl_keyfile=os.environ.get("SSL_KEYFILE"),
ssl_certfile=os.environ.get("SSL_CERTFILE"),

# Disable reload in production
reload=False
)

Real-World Application: API Service with Health Checks

Here's a more practical example of a FastAPI application with health checks and Uvicorn configuration:

python
# main.py
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
import psutil
import os

app = FastAPI(title="Production API Service")

# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Lock this down in production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

# Health check endpoint for load balancers
@app.get("/health")
async def health_check():
# Check system resources
memory = psutil.virtual_memory()
disk = psutil.disk_usage('/')

return {
"status": "healthy",
"system": {
"memory_usage": f"{memory.percent}%",
"disk_usage": f"{disk.percent}%",
"cpu_usage": f"{psutil.cpu_percent()}%"
}
}

@app.get("/api/data")
async def get_data():
return {"data": "This is your API data"}

# server.py
import uvicorn
import os

if __name__ == "__main__":
# Get configuration from environment variables (for containerized deployments)
host = os.getenv("HOST", "0.0.0.0")
port = int(os.getenv("PORT", 8000))
workers = int(os.getenv("WORKERS", 1))

# Run with proper production settings
uvicorn.run(
"main:app",
host=host,
port=port,
workers=workers,
log_level="info",
access_log=True,
limit_concurrency=1000,
timeout_keep_alive=5
)

Docker Deployment Example

When deploying with Docker, you can configure Uvicorn like this:

dockerfile
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

# Set environment variables
ENV HOST=0.0.0.0
ENV PORT=8000
ENV WORKERS=4

# Run Uvicorn with the proper configuration
CMD ["python", "server.py"]

Docker compose example:

yaml
version: '3'

services:
fastapi:
build: .
ports:
- "8000:8000"
environment:
- HOST=0.0.0.0
- PORT=8000
- WORKERS=4
- LOG_LEVEL=info
restart: always

Summary

Proper Uvicorn configuration is critical for deploying FastAPI applications that are stable, secure, and performant. Key takeaways include:

  • Use multiple workers in production (2 × CPU cores + 1)
  • Configure proper timeouts to protect against slow clients
  • Set appropriate concurrency limits based on your server's capacity
  • Enable HTTPS for production deployments
  • Configure logging for monitoring and debugging
  • Use environment variables for flexible configuration

By mastering Uvicorn configuration, you can ensure your FastAPI applications perform optimally under various load conditions and deployment environments.

Additional Resources

Exercises

  1. Create a FastAPI application and configure Uvicorn to run it on port 9000 with debug-level logging.
  2. Modify the application to use HTTPS with self-signed certificates.
  3. Create a production-ready configuration that automatically detects the number of CPU cores and sets the appropriate number of workers.
  4. Implement a custom logging configuration that rotates log files daily.
  5. Create a Docker container that runs your FastAPI application with optimal Uvicorn settings.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)