All posts

Flask Production Deployment Checklist

Complete Flask deployment checklist covering WSGI servers, security configuration, database connection pooling, and monitoring setup.

Flask Production Deployment Checklist

Flask's built-in server is for development only. Here's everything you need for a production deployment.

WSGI Server

Never use app.run() in production. Use Gunicorn:

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

Worker count formula: (2 * CPU_CORES) + 1. For I/O-heavy apps, consider gevent workers:

gunicorn --workers 4 --worker-class gevent --bind 0.0.0.0:8000 wsgi:app

Security Checklist

  • [ ] DEBUG = False in production config
  • [ ] SECRET_KEY loaded from environment variable
  • [ ] HTTPS enforced with Talisman
  • [ ] Session cookies marked secure and httponly
  • [ ] CSRF protection enabled
from flask_talisman import Talisman

Talisman(app, force_https=True)
app.config['SECRET_KEY'] = os.environ['SECRET_KEY']
app.config['SESSION_COOKIE_SECURE'] = True

Database

  • [ ] Connection pooling configured (SQLAlchemy pool size)
  • [ ] Database URL from environment variable
  • [ ] Migrations tested (flask db upgrade)
  • [ ] Connection timeout and retry logic
app.config['SQLALCHEMY_POOL_SIZE'] = 10
app.config['SQLALCHEMY_POOL_TIMEOUT'] = 30
app.config['SQLALCHEMY_POOL_RECYCLE'] = 1800

Monitoring

  • [ ] Health check endpoint
  • [ ] Error tracking with Bugsly for exception visibility
  • [ ] Structured logging to stdout for container environments
  • [ ] Request duration metrics
@app.route('/health')
def health():
    return {'status': 'healthy', 'version': os.environ.get('APP_VERSION', 'unknown')}

Infrastructure

  • [ ] Reverse proxy (nginx) in front of Gunicorn
  • [ ] Static files served by nginx or CDN
  • [ ] Process supervisor (systemd, Docker)
  • [ ] Graceful shutdown configured
  • [ ] Log rotation set up
  • [ ] Backup strategy for database

Pre-Deployment Verification

# Test config loading
FLASK_ENV=production flask shell -c "print(app.config['DEBUG'])"
# Run migrations dry-run
flask db upgrade --sql
# Verify health endpoint
curl http://localhost:8000/health

Try Bugsly Free

AI-powered error tracking that explains your bugs. Set up in 2 minutes, free forever for small projects.

Get Started Free