Is the server bundled with Flask safe for deployment in a production environment? If not, what should I use to deploy Flask in production?
-
This [answer](https://www.reddit.com/r/Python/comments/8bb102/why_shouldnt_one_use_flask_bottle_django_etc/dx5qklz/) gives a wider context to this problem, and explains why using the server bundled with Flask should not be used. – Basj Apr 11 '18 at 11:00
3 Answers
No. The bundled server is a development server. It's not designed with production environments in mind.
- It will not handle more than one request at a time by default.
- If you leave debug mode on and an error pops up, it opens up a shell that allows for arbitrary code to be executed on your server (think
os.system('rm -rf /')
). - The development server doesn't scale well.
Flask uses Werkzeug's development server, and the documentation says the same thing:
The development server is not intended to be used on production systems. It was designed especially for development purposes and performs poorly under high load. For deployment setups have a look at the Application Deployment pages.
The recommended approach is to use a production WSGI server to run your Flask application. There's a whole section dedicated to deployment in the docs: Deployment Options.
Deploying your application is as simple as installing a WSGI server like uWSGI or gunicorn and running that instead of Flask's development server:
gunicorn -w 4 -b 127.0.0.1:4000 myproject:app
If you are serving any static assets like images or videos, need low-level caching, or have higher concurrency demands, it's recommended to use a webserver like nginx and have it handle all of your requests.
In crappy ASCII form:
+----------+
| Client 2 |
+----------+
|
V
+----------+ +-------+ +----------+
| Client 1 |----->| nginx |<-----| Client 3 |
+----------+ +-------+ +----------+
^
|
V
/--------------------\
| useful nginx stuff |
| like asset serving |
| and rate limiting |
\--------------------/
|
V
+-------------+
| WSGI server |
+-------------+
To actually run the WSGI server process, you can use Supervisor. It automatically restarts the server if it fails for some reason, keeps logs, and runs as a daemon so your service starts when the server boots.
-
9I use `supervisor` + `gunicorn` + `nginx`. It is really easy to setup and maintain. – Anton Egorov Oct 14 '13 at 09:15
-
9"It will not handle more than one request at a time" - not true, see threaded and processes arguments : http://werkzeug.pocoo.org/docs/0.11/serving/ – HaveAGuess Jan 13 '16 at 15:23
-
"if an error pops up, it opens up a shell that allows for arbitrary code to be executed on your server" - isn't that debug=True mode ? – HaveAGuess Jan 13 '16 at 15:24
-
1@HaveAGuess: Amended. By default, though, the server will not be multithreaded. Those arguments aren't mentioned anywhere in the Flask docs, so you have to look at Werkzeug's documentation, which I think is more work than most people will do. – Blender Jan 13 '16 at 21:00
-
2@HaveAGuess: From the flask deployment [doc](http://flask.pocoo.org/docs/0.11/deploying/): "Flask’s built-in server is not suitable for production as it doesn’t scale well and **by default serves only one request at a time.**" – mvarge Jun 29 '16 at 16:08
-
@mvarge agreed but we had it scaled up to multiprocesses with *no problems* to handle multiple requests for an internal production app. We are now running on Apache for external exposure – HaveAGuess Jul 07 '16 at 13:21
-
@Blender Sorry to disturb you. I'm writing a post about Werkzeug, and I have some silly questions. Is the server provided by Werkzeug similar to Gunicorn in functionality? Can I call it "WSGI server"? – Grey Li Sep 27 '17 at 14:00
-
1@GreyLi: Yeah, both are WSGI servers. That's why you can swap out the dev server for a production server without any code modifications. – Blender Sep 27 '17 at 15:38
-
1) "It will not handle more than one request at a time by default" => can be changed with `threaded` option. 2) "If you leave debug mode on and an error pops up, it opens up a shell that allows for arbitrary code to be executed" => this could be easily turned off with a few lines of code. 3) "The development server doesn't scale well." => a benchmark (if someone has one) would be interesting to add concrete facts to help people understand why the bundled server is really so bad. I trust you, but everyone [seems](https://stackoverflow.com/a/12269604/1422096) to repeat this without source. – Basj Apr 11 '18 at 11:05
-
1@Basj: I would consider the people who *wrote* the development server to be a canonical source. General-purpose deployment guidelines try to address the common use case, which is deploying a public webservice. Can you get away with using the development server for a low-traffic webservice? Sure, but why waste the effort trying to make the development server into an almost-production server when `pip install uwsgi && uwsgi --http :8000 -w yourapp:app` works just as well and is actually tailored for that use case? – Blender Apr 11 '18 at 16:25
-
1@Haveaguess link is down for me but for the WSGi serving options see here: https://werkzeug.palletsprojects.com/en/1.0.x/serving/. Another alternative to using the development server is to run the Flask app as a service with systemd, nginx proxy and gunicorn: https://edmondchuc.com/deploying-python-flask-with-gunicorn-nginx-and-systemd/ – SeanQuinn781 Sep 06 '20 at 14:52
-
@Blender I do not understand what is yourapp:app there. I start flask server by running: python patch_to_file_with_flask_server.py – Brana Jan 16 '23 at 23:59
Basically, no. The built-in development server is not safe for deployment in a production environment.
The built in development server is for just that. For use in production you should follow one of the steps detailed here.
These include different servers that implement the WSGI specification, such as Apache/mod_wsgi or one of these stand-alone wsgi server http://flask.pocoo.org/docs/deploying/wsgi-standalone/
While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well and by default serves only one request at a time. http://flask.pocoo.org/docs/0.12/deploying/

- 89
- 1
- 3