Server Workers - Gunicorn with Uvicorn
The current page still doesn’t have a translation for this language.
But you can help translating it: Contributing.
Let’s check back those deployment concepts from before:
- Security - HTTPS
- Running on startup
- Restarts
- Memory
- Previous steps before starting
Up to this point, with all the tutorials in the docs, you have probably been running a server program like Uvicorn, running a single process.
When deploying applications you will probably want to have some replication of processes to take advantage of multiple cores and to be able to handle more requests.
As you saw in the previous chapter about , there are multiple strategies you can use.
Here I’ll show you how to use Gunicorn with Uvicorn worker processes.
Info
If you are using containers, for example with Docker or Kubernetes, I’ll tell you more about that in the next chapter: .
In particular, when running on Kubernetes you will probably not want to use Gunicorn and instead run a single Uvicorn process per container, but I’ll tell you about it later in that chapter.
Gunicorn is mainly an application server using the WSGI standard. That means that Gunicorn can serve applications like Flask and Django. Gunicorn by itself is not compatible with FastAPI, as FastAPI uses the newest .
But Gunicorn supports working as a process manager and allowing users to tell it which specific worker process class to use. Then Gunicorn would start one or more worker processes using that class.
And Uvicorn has a Gunicorn-compatible worker class.
Using that combination, Gunicorn would act as a process manager, listening on the port and the IP. And it would transmit the communication to the worker processes running the Uvicorn class.
Install Gunicorn and Uvicorn
That will install both Uvicorn with the extra packages (to get high performance) and Gunicorn.
Then you can run Gunicorn with:
Let’s see what each of those options mean:
main:app
: This is the same syntax used by Uvicorn,main
means the Python module named “main
“, so, a filemain.py
. Andapp
is the name of the variable that is the FastAPI application.You can imagine that
main:app
is equivalent to a Pythonimport
statement like:So, the colon in
main:app
would be equivalent to the Pythonimport
part in .--workers
: The number of worker processes to use, each will run a Uvicorn worker, in this case, 4 workers.--worker-class
: The Gunicorn-compatible worker class to use in the worker processes.Here we pass the class that Gunicorn can import and use with:
import uvicorn.workers.UvicornWorker
--bind
: This tells Gunicorn the IP and the port to listen to, using a colon (:
) to separate the IP and the port.
In the output, you can see that it shows the PID (process ID) of each process (it’s just a number).
You can see that:
- The Gunicorn process manager starts with PID
19499
(in your case it will be a different number). - Then it starts .
- Then it detects that it has to use the worker class at
uvicorn.workers.UvicornWorker
. - And then it starts 4 workers, each with its own PID:
19511
,19513
,19514
, and19515
.
Gunicorn would also take care of managing dead processes and restarting new ones if needed to keep the number of workers. So that helps in part with the restart concept from the list above.
Uvicorn with Workers
Uvicorn also has an option to start and run several worker processes.
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.
In any case, you would run it like this:
The only new option here is --workers
telling Uvicorn to start 4 worker processes.
You can also see that it shows the PID of each process, 27365
for the parent process (this is the process manager) and one for each worker process: 27368
, 27369
, , and 27367
.
Here you saw how to use Gunicorn (or Uvicorn) managing Uvicorn worker processes to parallelize the execution of the application, take advantage of multiple cores in the CPU, and be able to serve more requests.
From the list of deployment concepts from above, using workers would mainly help with the replication part, and a little bit with the restarts, but you still need to take care of the others:
- Security - HTTPS
- Running on startup
- Restarts
- Replication (the number of processes running)
- Memory
- Previous steps before starting
Containers and Docker
In the next chapter about I’ll tell some strategies you could use to handle the other deployment concepts.
I’ll also show you the official Docker image that includes Gunicorn with Uvicorn workers and some default configurations that can be useful for simple cases.
There I’ll also show you how to build your own image from scratch to run a single Uvicorn process (without Gunicorn). It is a simple process and is probably what you would want to do when using a distributed container management system like Kubernetes.
You can use Gunicorn (or also Uvicorn) as a process manager with Uvicorn workers to take advantage of multi-core CPUs, to run multiple processes in parallel.
You could use these tools and ideas if you are setting up your own deployment system while taking care of the other deployment concepts yourself.
Check out the next chapter to learn about FastAPI with containers (e.g. Docker and Kubernetes). You will see that those tools have simple ways to solve the other deployment concepts as well. ✨