Deployment - Uvicorn (2023)

Server deployment is a complex area, that will depend on what kind of service you're deploying Uvicorn onto.

As a general rule, you probably want to:

  • Run uvicorn --reload from the command line for local development.
  • Run gunicorn -k uvicorn.workers.UvicornWorker for production.
  • Additionally run behind Nginx for self-hosted deployments.
  • Finally, run everything behind a CDN for caching support, and serious DDOS protection.

Running from the command line

Typically you'll run uvicorn from the command line.

$ uvicorn example:app --reload --port 5000

The ASGI application should be specified in the form

When running locally, use --reload to turn on auto-reloading.

The --reload and --workers arguments are mutually exclusive.

To see the complete set of available options, use uvicorn --help:

$ uvicorn --helpUsage: uvicorn [OPTIONS] APPOptions: --host TEXT Bind socket to this host. [default:] --port INTEGER Bind socket to this port. [default: 8000] --uds TEXT Bind to a UNIX domain socket. --fd INTEGER Bind to socket from this file descriptor. --reload Enable auto-reload. --reload-dir PATH Set reload directories explicitly, instead of using the current working directory. --reload-include TEXT Set glob patterns to include while watching for files. Includes '*.py' by default; these defaults can be overridden with `--reload- exclude`. This option has no effect unless watchfiles is installed. --reload-exclude TEXT Set glob patterns to exclude while watching for files. Includes '.*, .py[cod], .sw.*, ~*' by default; these defaults can be overridden with `--reload-include`. This option has no effect unless watchfiles is installed. --reload-delay FLOAT Delay between previous and next check if application needs to be. Defaults to 0.25s. [default: 0.25] --workers INTEGER Number of worker processes. Defaults to the $WEB_CONCURRENCY environment variable if available, or 1. Not valid with --reload. --loop [auto|asyncio|uvloop] Event loop implementation. [default: auto] --http [auto|h11|httptools] HTTP protocol implementation. [default: auto] --ws [auto|none|websockets|wsproto] WebSocket protocol implementation. [default: auto] --ws-max-size INTEGER WebSocket max size message in bytes [default: 16777216] --ws-ping-interval FLOAT WebSocket ping interval [default: 20.0] --ws-ping-timeout FLOAT WebSocket ping timeout [default: 20.0] --ws-per-message-deflate BOOLEAN WebSocket per-message-deflate compression [default: True] --lifespan [auto|on|off] Lifespan implementation. [default: auto] --interface [auto|asgi3|asgi2|wsgi] Select ASGI3, ASGI2, or WSGI as the application interface. [default: auto] --env-file PATH Environment configuration file. --log-config PATH Logging configuration file. Supported formats: .ini, .json, .yaml. --log-level [critical|error|warning|info|debug|trace] Log level. [default: info] --access-log / --no-access-log Enable/Disable access log. --use-colors / --no-use-colors Enable/Disable colorized logging. --proxy-headers / --no-proxy-headers Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to populate remote address info. --server-header / --no-server-header Enable/Disable default Server header. --date-header / --no-date-header Enable/Disable default Date header. --forwarded-allow-ips TEXT Comma separated list of IPs to trust with proxy headers. Defaults to the $FORWARDED_ALLOW_IPS environment variable if available, or ''. --root-path TEXT Set the ASGI 'root_path' for applications submounted below a given URL path. --limit-concurrency INTEGER Maximum number of concurrent connections or tasks to allow, before issuing HTTP 503 responses. --backlog INTEGER Maximum number of connections to hold in backlog --limit-max-requests INTEGER Maximum number of requests to service before terminating the process. --timeout-keep-alive INTEGER Close Keep-Alive connections if no new data is received within this timeout. [default: 5] --ssl-keyfile TEXT SSL key file --ssl-certfile TEXT SSL certificate file --ssl-keyfile-password TEXT SSL keyfile password --ssl-version INTEGER SSL version to use (see stdlib ssl module's) [default: 17] --ssl-cert-reqs INTEGER Whether client certificate is required (see stdlib ssl module's) [default: 0] --ssl-ca-certs TEXT CA certificates file --ssl-ciphers TEXT Ciphers to use (see stdlib ssl module's) [default: TLSv1] --header TEXT Specify custom default HTTP response headers as a Name:Value pair --version Display the uvicorn version and exit. --app-dir TEXT Look for APP in the specified directory, by adding this to the PYTHONPATH. Defaults to the current working directory. [default: .] --h11-max-incomplete-event-size INTEGER For h11, the maximum number of bytes to buffer of an incomplete event. --factory Treat APP as an application factory, i.e. a () -> <ASGI app> callable. --help Show this message and exit.

See the settings documentation for more details on the supported options for running uvicorn.

(Video) Django Deployment: How to deploy Django app to server using Nginx + Uvicorn | Django deploy tutorial

Running programmatically

To run directly from within a Python program, you should use, **config). For example:

The set of configuration options is the same as for the command line tool.

Note that the application instance itself can be passed instead of the appimport string., host="", port=5000, log_level="info")

However, this style only works if you are not using multiprocessing (workers=NUM)or reloading (reload=True), so we recommend using the import string style.

Also note that in this case, you should put into if __name__ == '__main__' clause in the main module.


The reload and workers parameters are mutually exclusive.

Using a process manager

Running Uvicorn using a process manager ensures that you can run multiple processes in a resilient manner, and allows you to perform server upgrades without dropping requests.

(Video) Deploying your FastAPI project with docker in 4 minutes

A process manager will handle the socket setup, start-up multiple server processes, monitor process aliveness, and listen for signals to provide for processes restarts, shutdowns, or dialing up and down the number of running processes.

Uvicorn provides a lightweight way to run multiple worker processes, for example --workers 4, but does not provide any process monitoring.


Gunicorn is probably the simplest way to run and manage Uvicorn in a production setting. Uvicorn includes a gunicorn worker class that means you can get set up with very little configuration.

The following will start Gunicorn with four worker processes:

gunicorn -w 4 -k uvicorn.workers.UvicornWorker

The UvicornWorker implementation uses the uvloop and httptools implementations. To run under PyPy you'll want to use pure-python implementation instead. You can do this by using the UvicornH11Worker class.

gunicorn -w 4 -k uvicorn.workers.UvicornH11Worker

Gunicorn provides a different set of configuration options to Uvicorn, so some options such as --limit-concurrency are not yet supported when running with Gunicorn.

If you need to pass uvicorn's config arguments to gunicorn workers then you'll have to subclass UvicornWorker:

class MyUvicornWorker(UvicornWorker): CONFIG_KWARGS = {"loop": "asyncio", "http": "h11", "lifespan": "off"}


To use supervisor as a process manager you should either:

  • Hand over the socket to uvicorn using its file descriptor, which supervisor always makes available as 0, and which must be set in the fcgi-program section.
  • Or use a UNIX domain socket for each uvicorn process.

A simple supervisor configuration might look something like this:

(Video) Building Web APIs Using FastAPI


[supervisord][fcgi-program:uvicorn]socket=tcp://localhost:8000command=venv/bin/uvicorn --fd 0 example:Appnumprocs=4process_name=uvicorn-%(process_num)dstdout_logfile=/dev/stdoutstdout_logfile_maxbytes=0

Then run with supervisord -n.


To use circus as a process manager, you should either:

  • Hand over the socket to uvicorn using its file descriptor, which circus makes available as $(circus.sockets.web).
  • Or use a UNIX domain socket for each uvicorn process.

A simple circus configuration might look something like this:


[watcher:web]cmd = venv/bin/uvicorn --fd $(circus.sockets.web) example:Appuse_sockets = Truenumprocesses = 4[socket:web]host = = 8000

Then run circusd circus.ini.

Running behind Nginx

Using Nginx as a proxy in front of your Uvicorn processes may not be necessary, but is recommended for additional resilience. Nginx can deal with serving your static media and buffering slow requests, leaving your application servers free from load as much as possible.

In managed environments such as Heroku, you won't typically need to configure Nginx, as your server processes will already be running behind load balancing proxies.

The recommended configuration for proxying from Nginx is to use a UNIX domain socket between Nginx and whatever the process manager that is being used to run Uvicorn.Note that when doing this you will need to run Uvicorn with --forwarded-allow-ips='*' to ensure that the domain socket is trusted as a source from which to proxy headers.

When fronting the application with a proxy server you want to make sure that the proxy sets headers to ensure that the application can properly determine the client address of the incoming connection, and if the connection was over http or https.

(Video) HOW TO: Use $PORT to deploy Docker app on Heroku? (Python | Uvicorn)

You should ensure that the X-Forwarded-For and X-Forwarded-Proto headers are set by the proxy, and that Uvicorn is run using the --proxy-headers setting. This ensures that the ASGI scope includes correct client and scheme information.

Here's how a simple Nginx configuration might look. This example includes setting proxy headers, and using a UNIX domain socket to communicate with the application server.

It also includes some basic configuration to forward websocket connections. For more info on this, check Nginx recommendations.

http { server { listen 80; client_max_body_size 4G; server_name; location / { proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_redirect off; proxy_buffering off; proxy_pass http://uvicorn; } location /static { # path for static files root /path/to/app/static; } } map $http_upgrade $connection_upgrade { default upgrade; '' close; } upstream uvicorn { server unix:/tmp/uvicorn.sock; }}

Uvicorn's --proxy-headers behavior may not be sufficient for more complex proxy configurations that use different combinations of headers, or where the application is running behind more than one intermediary proxying service.

In those cases, you might want to use an ASGI middleware to set the client and scheme dependant on the request headers.

Running behind a CDN

Running behind a content delivery network, such as Cloudflare or Cloud Front, provides a serious layer of protection against DDOS attacks. Your service will be running behind huge clusters of proxies and load balancers that are designed for handling huge amounts of traffic, and have capabilities for detecting and closing off connections from DDOS attacks.

Proper usage of cache control headers can mean that a CDN is able to serve large amounts of data without always having to forward the request on to your server.

Content Delivery Networks can also be a low-effort way to provide HTTPS termination.

Running with HTTPS

To run uvicorn with https, a certificate and a private key are required.The recommended way to get them is using Let's Encrypt.

For local development with https, it's possible to use mkcertto generate a valid certificate and private key.

$ uvicorn example:app --port 5000 --ssl-keyfile=./key.pem --ssl-certfile=./cert.pem
(Video) WSGI & ASGI Simplified

Running gunicorn worker

It's also possible to use certificates with uvicorn's worker for gunicorn.

$ gunicorn --keyfile=./key.pem --certfile=./cert.pem -k uvicorn.workers.UvicornWorker example:app


Can I use Uvicorn in production? ›

Gunicorn. Gunicorn is probably the simplest way to run and manage Uvicorn in a production setting. Uvicorn includes a gunicorn worker class that means you can get set up with very little configuration. The UvicornWorker implementation uses the uvloop and httptools implementations.

Should I use Gunicorn or Uvicorn? ›

Nevertheless, as of now, Uvicorn's capabilities for handling worker processes are more limited than Gunicorn's. So, if you want to have a process manager at this level (at the Python level), then it might be better to try with Gunicorn as the process manager.

Does FastAPI use Uvicorn? ›

The main thing you need to run a FastAPI application in a remote server machine is an ASGI server program like Uvicorn.

How do you stop Uvicorn? ›

One way is to run it, and then to type ^Z to pause it. And then type "bg" to continue it in the background. And then type "exit" to the shell to make the shell and terminal go away. Alternatively, you could initially run it with "&" on the end of the command line, and elide the ^Z and the "bg".

Why is Uvicorn used? ›

uvicorn is an ASGI (async server gateway interface) compatible web server. It's (simplified) the binding element that handles the web connections from the browser or api client and then allows FastAPI to serve the actual request.

Is Uvicorn worker async? ›

But uvicorn server and sanic server neither support restart workers, so sanic support GunicornWorker for gunicorn server, and uvicorn has UvicornWorker . To meet you requirment, you can use both sanic_worker + sanic_app or uvcorn_worker + sanic_asgi_app through gunicorn server, it's both asynchronous.

Can Uvicorn serve static files? ›

Uvicorn doesn't seem to support static file serving, so you might need something else too (see e.g.

Is FastAPI better than flask? ›

Both Flask and FastAPI can quickly set up web servers and data science apps in Python. They require the same amount of effort when it comes to deployment. How to decide which framework is better for your next project? FastAPI is the best choice when speed and performance are of primary importance.

Is FastAPI production ready? ›

Not only is FastAPI intuitive and straight-forward to use in projects, but the FastAPI code also has 100% test coverage hence it's production-ready robust code.

Can FastAPI replace Flask? ›

FastAPI Framework

It works similarly to Flask which supports the deployment of web applications with a minimal amount of code. However, FastAPI is faster compare to Flask as it is built on ASGI (Asynchronous Server Gateway Interface) whereby it supports concurrency / asynchronous code.

How can I make my API faster? ›

Using FastAPI to Build Python Web APIs
  1. Create a First API.
  2. Run the First API App With Uvicorn.
  3. Check the Response.
  4. Check the Interactive API Documentation.
  5. Check the Alternative Interactive API Documentation.
  6. The First API, Step by Step.
Jul 14, 2021

How can I make my API server run faster? ›

Recap, step by step
  1. Step 1: import FastAPI. from fastapi import FastAPI app = FastAPI() @app. ...
  2. Step 2: create a FastAPI "instance" from fastapi import FastAPI app = FastAPI() @app. ...
  3. Step 3: create a path operation. Path. ...
  4. Step 4: define the path operation function. ...
  5. Step 5: return the content.

How many requests can Uvicorn handle? ›

Yes, with 5 worker processes, each with 8 threads, 40 concurrent requests can be served.

What is Uvicorn standard? ›

Introduction. Uvicorn is an ASGI web server implementation for Python. Until recently Python has lacked a minimal low-level server/application interface for async frameworks. The ASGI specification fills this gap, and means we're now able to start building a common set of tooling usable across all async frameworks.

How many employees does Gunicorn have? ›

Gunicorn should only need 4-12 worker processes to handle hundreds or thousands of requests per second. Gunicorn relies on the operating system to provide all of the load balancing when handling requests.

Is Uvicorn a web server? ›

Uvicorn is an ASGI web server implementation for Python. Until recently Python has lacked a minimal low-level server/application interface for async frameworks. The ASGI specification fills this gap, and means we're now able to start building a common set of tooling usable across all async frameworks.

How do you use a Uvicorn with a flask? ›

  1. Step 1: Creating a Python Virtual Environment for your Project. Before you get started, you need to set up your Python developer environment. ...
  2. Step 2: Creating a Minimal Flask App. ...
  3. Step 3: Setting Up Your Gunicorn Configuration. ...
  4. Step 4: Pushing the Site to GitHub. ...
  5. Step 5: Deploying to DigitalOcean with App Platform.
Sep 29, 2021

Can Gunicorn run ASGI? ›

Although Gunicorn is traditionally used to deploy WSGI applications, it also provides a pluggable interface to provide ASGI deployment.

What is the difference between ASGI and WSGI? ›

WSGI stands for Web Server Gateway Interface, and ASGI stands for Asynchronous Server Gateway interface. They both specify the interface and sit in between the web server and a Python web application or framework. One of their jobs is to handle incoming requests from the client, but they go about it in different ways.

What is the use of Gunicorn? ›

Gunicorn is a pure-Python HTTP server for WSGI applications. It allows you to run any Python application concurrently by running multiple Python processes within a single dyno. It provides a perfect balance of performance, flexibility, and configuration simplicity.

What is ASGI PY? ›

ASGI (Asynchronous Server Gateway Interface) is a spiritual successor to WSGI, intended to provide a standard interface between async-capable Python web servers, frameworks, and applications.

How do I use Django with Uvicorn? ›

Running Django in Uvicorn

Uvicorn needs to be called with the location of a module containing an ASGI application object, followed by what the application is called (separated by a colon). This will start one process listening on 127.0. 0.1:8000 .

Can Gunicorn server static files? ›

Gunicorn is meant to serve dynamic content, it should not be used to serve static files. We will add nginx to serve static files.

What is Uvicorn in Python? ›

Uvicorn is an ASGI web server implementation for Python. Until recently Python has lacked a minimal low-level server/application interface for async frameworks. The ASGI specification fills this gap, and means we're now able to start building a common set of tooling usable across all async frameworks.

Is FastAPI the future? ›

Many developers and teams already depend on FastAPI for their projects (including me and my team). But still, there are many improvements and features to come. FastAPI has a great future ahead. And your help is greatly appreciated.

Is FastAPI faster than Django? ›

Performance: Since the FastAPI has its main focus on high performance we can say it is the fastest framework among all of them, Flask is also a high-performance API because of its micro-framework feature and gives higher performance than Django.

Can FastAPI replace Django? ›

FastAPI tried to solve most of Django's problems and for the most part it did. It implemented most of the features that Django is missing and even added some more like auto validation of incoming requests, great editor support, and GraphQL support.

Which companies are using FastAPI? ›

Tech giants like Microsoft, Netflix, Uber amongst many other corporations are already started building their APIs with the FastAPI library. The framework is designed to optimize the experience so that we can write simple code to build production-ready APIs with best practices by default.

How FastAPI is faster? ›

Performance. FastAPI is fast! , it is much faster than the flask because it's built over ASGI (Asynchronous Server Gateway Interface) instead of WSGI (Web Server Gateway Interface) s the flask is built on.

Is FastAPI asynchronous? ›

The most exciting feature of FastAPI is that it supports asynchronous code out of the box using the async/await Python keywords. Testing FastAPI endpoints are really straightforward and can be done using TestClient provided by FastAPI.

Is FastAPI better than NodeJS? ›

Express (NodeJS) is ~1.5x faster than FastAPI (Python) and, these frameworks are ~7.5 and ~11.35 times slower than Fiber (as per multi-core async performance). However, this doesn't mean that you no longer use Python or NodeJS based frameworks.

Is FastAPI a microframework? ›

FastAPI: (uses Starlette) an API microframework with several additional features for building APIs, with data validation, etc.

Is Flask abandoned? ›

According to, the Flask Restplus is most probably dead and abandoned. The last commit was on October 1, 2018. It looks like the project is not being actively maintained anymore.

Who made FastAPI? ›

Sebastián Ramírez

What is FastAPI and REST API? ›

REST APIs are stateless, cacheable, and consistent. They're great for building general-purpose and scalable web applications. The three major Python frameworks are Django, Flask, and FastAPI. Today, we're going to explore FastAPI, an open-source web framework used to build APIs with Python.

Is an API a database? ›

An API is not a database. It is an access point to an app that can access a database. In this post, we will focus on these specific kinds of APIs — web based APIs that return data in response to a request made by a client. They allow us to go get data from outside sources.


1. Deploying FastAPI Apps Over HTTPS with Traefik Proxy
(Traefik Labs)
2. How to use Django with Uvicorn : The lightning-fast ASGI server
(Mukul Mantosh)
3. Deploy FastAPI on Heroku in just 6 minutes
4. All You Need to Know about WSGI
(Django Lessons)
5. Unix & Linux: deploy gunicorn and uvicorn using systemd
(Roel Van de Paar)
6. Python Tutorial | Flask + Gunicorn Hello World
(Andrew Porter)
Top Articles
Latest Posts
Article information

Author: Carmelo Roob

Last Updated: 13/07/2023

Views: 6270

Rating: 4.4 / 5 (45 voted)

Reviews: 92% of readers found this page helpful

Author information

Name: Carmelo Roob

Birthday: 1995-01-09

Address: Apt. 915 481 Sipes Cliff, New Gonzalobury, CO 80176

Phone: +6773780339780

Job: Sales Executive

Hobby: Gaming, Jogging, Rugby, Video gaming, Handball, Ice skating, Web surfing

Introduction: My name is Carmelo Roob, I am a modern, handsome, delightful, comfortable, attractive, vast, good person who loves writing and wants to share my knowledge and understanding with you.