Production Configuration
Multiple workers, quieter logs, trusted proxies and worker recycling. Behind a reverse proxy that terminates TLS, drop the ssl_* arguments.
import uvicorn
import os
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=int(os.getenv("PORT", 8000)),
workers=int(os.getenv("WEB_CONCURRENCY", 4)),
log_level="warning",
access_log=False,
proxy_headers=True,
forwarded_allow_ips=os.getenv("TRUSTED_PROXIES", "127.0.0.1"),
limit_max_requests=10000, # Recycle workers to prevent memory leaks
limit_max_requests_jitter=1000, # Stagger worker restarts
timeout_graceful_shutdown=30,
ssl_keyfile="./ssl/key.pem",
ssl_certfile="./ssl/cert.pem"
)
Development with Auto-Reload
With reload=True, the app must be passed as an import string so the reloader can import it again. Install watchfiles (included in uvicorn[standard]) to use reload_includes and reload_excludes.
import uvicorn
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="127.0.0.1",
port=8000,
reload=True,
reload_dirs=["./app"],
reload_includes=["*.py", "*.html"],
log_level="debug"
)
Config and Server Objects
uvicorn.run() is a thin wrapper around Config and Server. Use them directly to start the server inside an existing event loop.
import uvicorn
from uvicorn.config import Config
from uvicorn.server import Server
async def run_server():
config = Config(
"app.main:app",
host="0.0.0.0",
port=8000,
log_level="info",
access_log=True,
use_colors=True
)
server = Server(config)
await server.serve()
if __name__ == "__main__":
import asyncio
asyncio.run(run_server())
Factory Mode (Application Factory)
With factory=True, uvicorn calls the function to build the app, in each worker and after each reload.
import uvicorn
# In app/main.py:
# def create_app():
# app = FastAPI()
# # Configure app with dependencies
# return app
if __name__ == "__main__":
uvicorn.run(
"app.main:create_app",
factory=True, # Treat as factory function
host="0.0.0.0",
port=8000,
reload=True
)
Environment-Based Configuration
Keep one entry point and switch settings with an environment variable.
import uvicorn
import os
def get_config():
if os.getenv("ENVIRONMENT") == "production":
return {
"host": "0.0.0.0",
"port": int(os.getenv("PORT", 8000)),
"workers": int(os.getenv("WORKERS", 4)),
"log_level": "warning",
"access_log": False
}
else:
return {
"host": "127.0.0.1",
"port": 8000,
"reload": True,
"log_level": "debug"
}
if __name__ == "__main__":
config = get_config()
uvicorn.run("app.main:app", **config)
Testing Environment
Start a real server in a background thread for end-to-end tests.
import uvicorn
import threading
import time
def start_test_server():
uvicorn.run(
"tests.app:app",
host="127.0.0.1",
port=8001,
log_level="critical",
access_log=False
)
# Start server in background for testing
server_thread = threading.Thread(target=start_test_server, daemon=True)
server_thread.start()
time.sleep(1) # Wait for server to start
# Run your tests here