Flask’s built-in server is for development only. Production deployment uses Gunicorn (or uWSGI) behind Nginx.

Application Factory

  # app/__init__.py
from flask import Flask
import os

def create_app():
    app = Flask(__name__)
    app.config.from_mapping(
        SECRET_KEY=os.environ.get("SECRET_KEY", "dev"),
        SQLALCHEMY_DATABASE_URI=os.environ["DATABASE_URL"],
        SQLALCHEMY_TRACK_MODIFICATIONS=False,
    )

    from .routes import main
    app.register_blueprint(main)

    return app
  
  # wsgi.py
from app import create_app
app = create_app()
  

Gunicorn

  pip install gunicorn
gunicorn wsgi:app --bind 0.0.0.0:8000 --workers 4 --timeout 120
  

Docker

  FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt gunicorn
COPY . .
EXPOSE 8000
CMD ["gunicorn", "wsgi:app", "--bind", "0.0.0.0:8000", "--workers", "4"]
  

Environment Variables

Never hardcode secrets:

  # .env (not committed)
SECRET_KEY=your-random-secret-key
DATABASE_URL=postgresql://user:pass@db:5432/myapp
FLASK_ENV=production
  
  import os
app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]
  

Health Check

  @app.route("/health")
def health():
    return {"status": "ok"}, 200
  

Production Checklist

  • DEBUG = False
  • Strong SECRET_KEY from environment
  • Gunicorn with multiple workers
  • Nginx for SSL termination and static files
  • PostgreSQL instead of SQLite
  • Database connection pooling
  • Logging configured
  • Health check endpoint
  • Rate limiting on public endpoints

Flask’s simplicity extends to deployment — a minimal WSGI setup is all you need.