How to Limit Uvicorn to a Single Worker Process When Running FastAPI
Set --workers 1 in the Uvicorn CLI or pass workers=1 to uvicorn.run() to force a single worker process, as the default behavior already spawns only one worker unless explicitly overridden.
When deploying a FastAPI application with Uvicorn, you might observe multiple worker processes spawning when you only need a single instance. According to the tiangolo/fastapi source code and Uvicorn's implementation, the server actually defaults to one worker, but configuration flags or environment variables can override this behavior. Understanding how to explicitly control the uvicorn run single worker configuration ensures predictable resource usage and simplifies debugging in containerized environments.
Understanding Uvicorn's Default Worker Behavior
Uvicorn's process manager spawns workers based on the --workers flag. By default, this value is 1, meaning only a single worker process starts alongside the parent process. If you observe three workers in your process list, the --workers parameter has been explicitly set to 3 somewhere in your deployment pipeline—commonly in Docker entrypoint scripts, systemd service files, or environment variable injections.
The FastAPI documentation in docs/en/docs/deployment/server-workers.md explains that the --workers option controls how many worker processes are spawned, with each worker appearing as a separate PID in the logs. Similarly, the FastAPI CLI documentation in docs/en/docs/fastapi-cli.md shows that the fastapi run command passes through to Uvicorn and supports the same worker configuration.
Method 1: Command Line Configuration
To explicitly enforce a single worker when launching Uvicorn directly, use the --workers flag with a value of 1. This overrides any environment defaults that might be setting a higher count.
# Explicit single worker
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 1
# Omitting --workers also defaults to 1
uvicorn main:app --host 0.0.0.0 --port 8000
The argument parsing occurs in Uvicorn's CLI implementation (uvicorn/__main__.py), which translates the --workers flag into the workers parameter passed to the process manager.
Method 2: FastAPI CLI Configuration
When using the FastAPI CLI (fastapi run), the command internally invokes Uvicorn and accepts the same --workers parameter. This is documented in docs/en/docs/fastapi-cli.md and provides a convenient wrapper while maintaining full control over worker count.
# Default single worker
fastapi run main.py
# Explicitly set one worker
fastapi run main.py --workers 1
The FastAPI CLI passes the --workers value directly to Uvicorn's configuration, ensuring consistent behavior whether you use the wrapper or call Uvicorn directly.
Method 3: Programmatic Configuration
When launching Uvicorn programmatically from within a Python script, pass workers=1 to the uvicorn.run() function. This approach is common for custom entry points or when embedding the server in larger applications.
import uvicorn
from myapp import app # Your FastAPI application instance
if __name__ == "__main__":
uvicorn.run(
app,
host="0.0.0.0",
port=8000,
workers=1, # Force single worker process
)
Setting workers=1 in the programmatic API corresponds to the --workers 1 CLI flag, as both configure Uvicorn's process manager to spawn exactly one worker instance.
Troubleshooting Persistent Multiple Workers
If you have explicitly set --workers 1 but still observe three processes, investigate external configuration sources. Common culprits include:
- Docker Compose files: Check for
command: uvicorn main:app --workers 3in service definitions - Entrypoint scripts: Shell scripts wrapping the Uvicorn launch may hardcode worker counts
- Environment variables: Some deployment platforms inject
UVICORN_WORKERS=3automatically - Process managers: Supervisor, systemd, or PM2 configurations may spawn multiple instances independently of Uvicorn's internal worker model
Use ps aux | grep uvicorn to verify the exact command line arguments being passed to each process, confirming whether --workers 3 appears in the invocation.
Summary
- Uvicorn defaults to one worker process; observing multiple workers indicates an explicit
--workersoverride somewhere in your deployment stack - Use
--workers 1in the CLI orworkers=1inuvicorn.run()to enforce a single instance - The FastAPI CLI (
fastapi run) accepts the same--workersparameter and passes it through to Uvicorn - If multiple workers persist despite configuration, inspect Docker files, entrypoint scripts, and environment variables for hidden
--workers 3settings
Frequently Asked Questions
Why does Uvicorn spawn multiple workers by default?
Uvicorn does not spawn multiple workers by default. The default value for the --workers flag is 1, meaning only a single worker process starts. If you observe three or more workers, an external configuration is explicitly setting --workers 3, or you are using a process manager that spawns multiple Uvicorn instances independently.
Can I use reload mode with multiple workers?
No, Uvicorn's reload mode (--reload) is incompatible with multiple workers. When --reload is enabled, Uvicorn automatically restricts the worker count to 1 because the file watcher and reloader cannot coordinate across multiple processes. Attempting to set --workers greater than 1 with --reload will result in an error or the workers parameter being ignored.
How do I verify how many workers are actually running?
Run ps aux | grep uvicorn in your terminal or container to list all Uvicorn processes. Each worker appears as a separate process with the same command line arguments. If you see multiple lines with your application module (e.g., main:app), check the full command for the --workers flag to confirm the configuration source.
Does the FastAPI CLI handle workers differently than Uvicorn?
No, the FastAPI CLI (fastapi run) passes the --workers argument directly to Uvicorn's configuration. As documented in docs/en/docs/fastapi-cli.md, the CLI is a convenience wrapper that ultimately invokes uvicorn.run() with the same parameters. Setting --workers 1 with fastapi run produces identical behavior to calling uvicorn directly with the same flag.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →