Skip to main content

Introduction

After developing your Flask application, you’ll want to make it available to users. When developing locally, you’re probably using Flask’s built-in development server, debugger, and reloader. These should never be used in production.
Do not use the development server when deploying to production. It is intended for use only during local development. It is not designed to be particularly secure, stable, or efficient.
“Production” means “not development”, which applies whether you’re serving your application publicly to millions of users or privately to a single user.

WSGI Architecture

Flask is a WSGI application. A WSGI server is used to run the application, converting incoming HTTP requests to the standard WSGI environ, and converting outgoing WSGI responses to HTTP responses.

Basic Setup

A typical production setup involves:
  1. WSGI Server - Runs your Flask application (e.g., Gunicorn, uWSGI, Waitress)
  2. HTTP Server / Reverse Proxy - Handles external requests, TLS, static files (e.g., Nginx, Apache)
  3. Application Code - Your Flask application
Client → HTTP Server (Nginx) → WSGI Server (Gunicorn) → Flask App

Self-Hosted Options

WSGI Servers

Flask can be deployed with various WSGI servers, each with different characteristics:
ServerProsConsBest For
GunicornEasy to use, pure Python, good performanceNo Windows support (except WSL)Linux/Unix production deployments
uWSGIVery fast, extensive featuresComplex configuration, requires compilerHigh-performance production
WaitressCross-platform, easy setup, pure PythonSingle process, no streamingWindows deployments, simpler apps
mod_wsgiIntegrated with ApacheRequires Apache, complex setupApache-based infrastructure

Reverse Proxy Servers

While WSGI servers have HTTP servers built-in, a dedicated reverse proxy is recommended for production:
  • Nginx - Fast, lightweight, excellent for static files and load balancing
  • Apache httpd - Feature-rich, mature, extensive module ecosystem
A reverse proxy sits in front of your WSGI server and handles incoming requests, TLS termination, load balancing, and serving static files more efficiently.

Hosting Platforms

Many services offer managed hosting without requiring server maintenance:
  • PythonAnywhere - Python-focused hosting with free tier
  • Google Cloud - App Engine and Cloud Run options
  • AWS Elastic Beanstalk - Managed application platform
  • Microsoft Azure - App Service with Python support
  • Heroku - Simple deployment with git push
  • DigitalOcean App Platform - Managed container platform
When using hosting platforms, you’ll typically need to configure proxy headers using Flask’s ProxyFix middleware.

Key Deployment Considerations

Security

Never Run as Root

WSGI servers should not run as root to prevent your application code from running with elevated privileges.

Use HTTPS

Always use TLS/SSL certificates in production. Let’s Encrypt provides free certificates.

Secret Key

Use a strong, random secret key and never commit it to version control.

Debug Mode Off

Ensure DEBUG = False in production to prevent information leakage.

Performance

Worker Processes Most WSGI servers use multiple worker processes to handle concurrent requests. A common starting point:
workers = (CPU cores * 2) + 1
For a 4-core server:
gunicorn -w 9 'myapp:app'
Worker Types
  • Sync workers - Default, suitable for most applications
  • Async workers - For applications with many concurrent connections (using gevent or eventlet)
  • Thread workers - For I/O-bound applications

Environment Variables

Use environment variables for configuration:
import os

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY')
    DATABASE_URL = os.environ.get('DATABASE_URL')
    DEBUG = os.environ.get('FLASK_DEBUG', 'False') == 'True'

Logging

Configure proper logging for production:
import logging
from logging.handlers import RotatingFileHandler

if not app.debug:
    handler = RotatingFileHandler('app.log', maxBytes=10000000, backupCount=3)
    handler.setLevel(logging.INFO)
    app.logger.addHandler(handler)

Deployment Checklist

Before deploying to production:
  • Set DEBUG = False
  • Use a production WSGI server
  • Configure environment variables
  • Set up proper logging
  • Use a strong, random SECRET_KEY
  • Configure a reverse proxy (Nginx/Apache)
  • Set up TLS/SSL certificates
  • Configure database connection pooling
  • Set up monitoring and error tracking
  • Configure firewall rules
  • Set up automated backups
  • Test error pages (404, 500, etc.)

Next Steps

WSGI Servers

Learn how to configure Gunicorn, uWSGI, and other WSGI servers

Production Best Practices

Implement security, monitoring, and optimization strategies

Additional Resources

Build docs developers (and LLMs) love