Web App Deployment

Preparing Your App for Production

35 min

A production entry point

wsgi.py:

from app import create_app
app = create_app()

Run with Gunicorn instead of the dev server:

pip install gunicorn
gunicorn wsgi:app --workers 2 --threads 4 --bind 0.0.0.0:$PORT

Keep Gunicorn settings in gunicorn.conf.py reading environment variables, so scaling up is a settings change:

import os
workers = int(os.environ.get("WEB_CONCURRENCY", 2))
threads = int(os.environ.get("GUNICORN_THREADS", 4))
bind = f"0.0.0.0:{os.environ.get('PORT', '8000')}"
timeout = int(os.environ.get("GUNICORN_TIMEOUT", 60))

A rough starting point: memory decides workers. A small Flask app uses roughly 80–150 MB per worker; on a 512 MB instance use 1–2 workers with threads.

Configuration by environment

import os

class Config:
    SECRET_KEY = os.environ["SECRET_KEY"]             # crash early if missing
    SQLALCHEMY_DATABASE_URI = os.environ["DATABASE_URL"]
    SESSION_COOKIE_SECURE = True
    SESSION_COOKIE_HTTPONLY = True
    SESSION_COOKIE_SAMESITE = "Lax"

Generate secrets properly: python -c "import secrets; print(secrets.token_hex(32))".

Some platforms give postgres:// URLs; SQLAlchemy needs postgresql://:

url = os.environ["DATABASE_URL"].replace("postgres://", "postgresql://", 1)

Behind a proxy

Platforms terminate HTTPS at a proxy in front of your app. Tell Flask so redirects use https and the client IP is right:

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)

Static files

Small apps can serve static files with WhiteNoise or let the platform do it; set long cache headers on versioned files. User uploads should go to object storage (S3, Cloudflare R2) or a persistent disk.

Health check endpoint

@app.get("/api/health")
def health():
    db.session.execute(text("SELECT 1"))
    return {"status": "ok"}

The platform calls it to know when a new deploy is ready, and uptime monitors use it to alert you.

Security headers

Add them with a small after_request hook or Flask-Talisman: Strict-Transport-Security, X-Content-Type-Options: nosniff, Referrer-Policy, a Content-Security-Policy and X-Frame-Options: DENY (or CSP frame-ancestors).

Pre-deploy checklist

  • [ ] Debug off; SECRET_KEY from the environment
  • [ ] requirements.txt pinned; app boots from a clean virtual environment
  • [ ] Migrations run as part of the build or release step
  • [ ] Health check route
  • [ ] Logs go to stdout
  • [ ] No secrets in Git (git grep -i secret)

Check yourself

  • Why not use flask run in production?
  • What does ProxyFix fix?
  • What should a health check verify?

Seu progresso fica salvo apenas neste navegador.

Enviar para revisão (10 pontos)