Gunicorn: a pre-fork WSGI and ASGI server for UNIX deployments
gunicorn 'Green Unicorn' is a WSGI HTTP Server for UNIX, fast clients and sleepy applications.
At a glance
- What is it?
- Gunicorn sits between nginx and a Python application, forking worker processes that share a listening socket. It is the default answer for Django and Flask deployments, and the README now also advertises ASGI and beta HTTP/2 support.
- Who is it for?
- Adopt Gunicorn if you run a WSGI framework such as Django, Flask or Pyramid on Linux or macOS behind a reverse proxy, and you want a process model you can reason about from the command line. Do not adopt it on Windows, and do not reach for it as a primary ASGI server if your framework already ships a native one.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 23 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap Gunicorn fills between a reverse proxy and a Python app
A Python web framework gives you a callable. It does not give you a process that survives a crash, binds port 80, or spreads requests across more than one CPU core. Gunicorn is the layer that does. The README describes it as a "Python WSGI HTTP Server for UNIX" built on a pre-fork worker model ported from Ruby's Unicorn project, and that description is accurate about both its scope and its limits. It speaks WSGI, so Django, Flask, Pyramid and any other WSGI framework work with it without an adapter. The audience is narrow on purpose: people deploying Python applications on POSIX systems, usually behind nginx, usually on Linux. The pyproject.toml classifiers list macOS and POSIX as operating systems and CPython and PyPy as implementations. Windows is not among them. If your deployment target is a Windows host, this is the wrong tool and the README does not pretend otherwise.
Pre-fork workers, a shared socket, and where the arbiter fits
The mechanism is the part worth understanding before you tune anything. A master process, which the project calls the arbiter, starts first, binds the listening socket, then forks worker processes that inherit that socket. Because the socket is opened before the fork, every worker can accept connections on the same port without a separate load balancer in front of them. The arbiter does not handle requests; it watches workers and replaces the ones that die. That is the whole reason a Gunicorn deployment survives a segfault in one worker.
Worker type is a configuration choice, not a fixed property. The README lists sync, gthread, gevent and asgi as the available worker classes. Sync workers handle one request at a time, which is fine for CPU-bound or fast-returning views and bad for anything that blocks on a slow upstream. Gevent workers are installed through an optional dependency group; the pyproject.toml pins gevent at 24.10.1 or newer. The README also mentions two beta features worth flagging: dirty arbiters for heavy workloads such as ML models and long-running tasks, and per-app worker allocation for those arbiters. Beta is the project's own label, so treat both as things to evaluate rather than defaults. HTTP/2 support is likewise marked beta in the README, described as multiplexed streams. If you need HTTP/2 today and cannot tolerate a beta label, terminate it at your proxy instead.
Installing Gunicorn and serving a first application
The README gives a two-line quick start. The first line installs the package from PyPI, the second runs it against a module-level callable. The trailing colon syntax means the object named after the colon is looked up inside the module named before it.
pip install gunicorn
gunicorn myapp:app --workers 4After the second command the server binds and starts printing access lines to the terminal. Four worker processes are forked, so you should see the arbiter plus four children if you inspect the process list. For an ASGI application the README adds a worker class flag rather than a different entry point:
gunicorn myapp:app --worker-class asgiThat is the documented route for FastAPI, Starlette and Quart. Note that the README's feature list names those three frameworks explicitly under ASGI support, so the flag is not a general-purpose escape hatch for arbitrary async code. For a Flask or Django application the first form is what you want. Configuration can also live in a file; the repository ships examples/gunicorn_rc and examples/example_config.py, which is where to look for the shape of a config rather than inventing keys. The Makefile shows the development path if you are working from a checkout: a virtualenv, an editable install, then requirements_dev.txt.
Where Gunicorn is the wrong choice
The most obvious failure mode is platform. The package metadata targets POSIX and macOS only, and the README's own description says UNIX. Attempting a Windows deployment is not a configuration problem to solve; it is outside what the project claims to support.
The second limitation is subtler and more common. Gunicorn is a process manager and an HTTP server, not a static file server and not a TLS terminator with a mature feature set. The repository ships examples/nginx.conf, and the README lists uWSGI binary protocol support for nginx integration, which tells you the intended architecture: nginx in front, Gunicorn behind. Deployments that put Gunicorn directly on the internet give up the buffering, connection handling and static file serving that the proxy was doing.
Third, worker count and timeout are the two settings most likely to be wrong in a real deployment, and neither has a safe universal default. Too few sync workers and a single slow request stalls a queue. Too many and you exhaust memory or database connections. The README points at the settings reference rather than prescribing numbers, which is honest but leaves the tuning to you. If your application is dominated by long-lived streaming responses, the sync worker is a poor fit and you should be looking at gthread or gevent.
Gunicorn against uvicorn and the ASGI question
The comparison people actually search for is Gunicorn versus uvicorn, and the difference is architectural rather than a matter of preference. Uvicorn is an ASGI server first; its process model is built around an event loop. Gunicorn is a WSGI server first, with ASGI support added through a worker class, as the README's `--worker-class asgi` example shows. If your application is a FastAPI or Starlette service and nothing else, running Uvicorn directly avoids a layer. If you already run Django or Flask and are adding one async endpoint, keeping Gunicorn and switching the worker class for that app is the smaller change.
The comparison with nginx is a different question and not really a competition. Gunicorn does not replace nginx in the deployments the repository documents; examples/nginx.conf exists precisely because the two are meant to sit together. The uWSGI binary protocol support in the README is the integration point. Treat the pair as one deployment unit rather than choosing between them.
Maintenance, releases and what the licence actually says
The repository is not archived, and the last push was on 2026-09-06, which is recent enough that describing the project as actively maintained is fair on the evidence available. Release cadence supports that: 26.2.0 on 2026-08-24, 26.2.1 on 2026-09-05, and 26.2.2 on 2026-09-06, so two patch releases landed within about a day of each other. A reader upgrading should pin a version rather than track the latest, because that cadence means a new patch can appear while you are mid-deploy.
The licence situation needs one clarification. The repository metadata field reports NOASSERTION, but the README states that Gunicorn is released under the MIT License and points at the LICENSE file, and pyproject.toml declares `license = "MIT"` with `license-files = ["LICENSE"]`. The NOASSERTION value is what an automated classifier produced, not a statement by the project. For a permissive-licence review, MIT is the operative claim and the LICENSE file is the authority. That is a description of what the files say, not legal advice; if your organisation requires a specific licence determination, read LICENSE yourself.
Upgrade cost is low for the common case. The package requires Python 3.10 or newer, so an upgrade is blocked only if you are still on 3.9. The README notes that per-app worker allocation and HTTP/2 are new in v25 and both beta, which means an upgrade that does not touch those flags changes little. The project is maintained by volunteers and asks for sponsorship in the README, which is worth knowing when you weigh how quickly a reported bug will be addressed.
Editorial conclusion
Adopt Gunicorn if you run a WSGI framework such as Django, Flask or Pyramid on Linux or macOS behind a reverse proxy, and you want a process model you can reason about from the command line. Do not adopt it on Windows, and do not reach for it as a primary ASGI server if your framework already ships a native one. Before committing, verify three things against your own application: which worker class you need for your workload, whether your proxy speaks the uWSGI binary protocol or plain HTTP, and what your current timeout and worker count are, since both are set at the command line or in a config file and both change behaviour under load.
Frequently asked questions
What is Gunicorn used for?
It is a WSGI HTTP server for UNIX that runs a Python web application as a set of forked worker processes behind a reverse proxy. The README describes it as broadly compatible with various web frameworks, and lists Django, Flask and Pyramid as WSGI targets.
What is the difference between Gunicorn and Flask?
Flask is a web framework that produces a WSGI callable; Gunicorn is the server that runs that callable in production. They are not alternatives, and the README's quick start assumes you already have an application object to point Gunicorn at.
How do I install Gunicorn?
The README's quick start is `pip install gunicorn`, followed by `gunicorn myapp:app --workers 4`. The package is published on PyPI, and the pyproject.toml requires Python 3.10 or newer.
How do I use Gunicorn with FastAPI?
The README lists FastAPI under ASGI support and gives the command `gunicorn myapp:app --worker-class asgi`. That worker class is the documented route for ASGI applications rather than the default sync worker.
How do I use gevent with Gunicorn?
Gevent is an optional dependency group in pyproject.toml, pinned at gevent 24.10.1 or newer, and the README lists gevent among the available worker types. Installing the extra and selecting the gevent worker class is the documented path.
Can I install Gunicorn on Windows?
The README describes Gunicorn as a WSGI HTTP Server for UNIX, and the pyproject.toml classifiers list only macOS and POSIX operating systems. Windows is not a documented target.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/benoitc-gunicorn)