When you start a Flask application using the standard flask run command, you'll see a prominent warning: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. This message is crucial – it indicates that the built-in server provided by Flask (Werkzeug's development server) is designed only for local development and testing, not for handling live traffic on a production website.
This guide explains why the development server is unsuitable for production and introduces recommended production-ready WSGI servers like Waitress and Gunicorn.
Understanding the Warning: Development vs. Production Servers
- Development Server (
flask run): Provided by the Werkzeug library (Flask's dependency). It's optimized for ease of use during development, featuring:- Automatic code reloading (
--reloadflag). - An interactive debugger in the browser (if enabled).
- Relatively simple, single-process, often single-threaded operation.
- Automatic code reloading (
- Production WSGI Server: Applications like Waitress, Gunicorn, or uWSGI are specifically designed to run Python web applications (following the WSGI standard) in a live production environment. They focus on:
- Performance (handling multiple requests concurrently).
- Stability and Reliability.
- Security (fewer debugging features exposed).
- Scalability (often running multiple worker processes).
The warning exists because the development server lacks the performance, security, and robustness features required to handle real user traffic reliably.
When the Warning Appears (flask run)
You will see this warning whenever you start your Flask application using the standard flask run command in your terminal.
Example app.py:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1>Hello from Flask!</h1>"Running the Development Server:
export FLASK_APP=app # Linux/macOS
set FLASK_APP=app # Windows CMD
$env:FLASK_APP = "app" # Windows PowerShell
flask run
python -m flask runOutput:
* Environment: development
* Debug mode: off # (or on)
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead. # <<< THE WARNING
* Running on http://127.0.0.1:5000
Press CTRL+C to quitWhy the Development Server is Not for Production
- Performance: It typically handles only one request at a time (single-threaded/process). Under load, requests will queue up, leading to slow response times.
- Security: If run with the debugger enabled (
FLASK_ENV=developmentorflask run --debug), it exposes a powerful debugger that could allow attackers to execute arbitrary code if accessible externally. - Stability: It's not designed for long-running, high-availability scenarios and may lack robustness compared to dedicated WSGI servers.
Solution: Use a Production WSGI Server
To deploy your Flask app, you need to use a production-grade Web Server Gateway Interface (WSGI) server. Popular choices include Waitress, Gunicorn, and uWSGI.
Option 1: Waitress (Cross-Platform)
Waitress is a pure-Python WSGI server that works well on Windows, macOS, and Linux. It's known for its simplicity.
Installation
Install Waitress into your project's virtual environment.
pip install waitressRunning with waitress-serve (Command Line)
This is a common way to start your app using Waitress from the terminal.
waitress-serve --host=0.0.0.0 --port=8080 app:app--host=0.0.0.0: Makes the server accessible on your network (use127.0.0.1for localhost only).--port=8080: Specifies the port number.app:app: Points to theappvariable (yourFlask(__name__)instance) inside theapp.pyfile. Adjust if your filename or variable name differs (e.g.,my_project.main:my_flask_app).
Running Programmatically (in app.py)
You can also start Waitress from within your Python script. This is useful for simple deployments or embedding. Modify your app.py:
from flask import Flask
from waitress import serve
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1>Hello from Flask via Waitress!</h1>"
if __name__ == "__main__":
print("Starting Waitress server on http://0.0.0.0:8080")
serve(app, host="0.0.0.0", port=8080)Now, instead of flask run, you run the script directly:
python app.pyOption 2: Gunicorn (Linux/macOS)
Gunicorn ('Green Unicorn') is a very popular WSGI server for Unix-like systems (Linux, macOS). It's known for its performance and ease of use. It does not run natively on Windows.
Installation
pip install gunicornRunning with gunicorn (Command Line)
gunicorn --bind 127.0.0.1:8000 --workers=4 app:app--bind: Specifies the address and port to listen on.--workers: Number of worker processes to handle requests (adjust based on CPU cores).app:app: Points to your Flask app instance within your module.
Other Production Options (uWSGI, etc.)
- uWSGI: Another powerful and widely used WSGI server, often paired with a reverse proxy like Nginx for high-performance deployments. Configuration can be more complex than Gunicorn or Waitress.
- Nginx/Apache + WSGI Server: In typical production setups, you often run Gunicorn or uWSGI behind a web server like Nginx or Apache, which handles incoming HTTP requests, serves static files, and forwards dynamic requests to the WSGI server.
Importance of Virtual Environments
Always install your Flask application dependencies, including your chosen WSGI server (Waitress, Gunicorn), inside a project-specific virtual environment (venv). This isolates dependencies and avoids conflicts.
Conclusion
The Flask warning WARNING: This is a development server... is a critical reminder not to use the server started by flask run for live applications. It lacks the necessary performance, security, and stability.
To deploy your Flask application correctly:
- Choose a production WSGI server:
Waitress(cross-platform) orGunicorn(Linux/macOS) are excellent choices. - Install the chosen server into your project's virtual environment (
pip install waitressorpip install gunicorn). - Run your application using the command provided by the WSGI server (e.g.,
waitress-serve ... app:apporgunicorn ... app:app) instead offlask run.
This ensures your application is served by a robust server capable of handling production loads.