Python Web App Production Deployment: Flask, Django, FastAPI
Python has three dominant web frameworks: Flask for minimal APIs, Django for full-stack applications, and FastAPI for high-performance async services. Each has different production requirements — particularly around their server stack. This guide covers how to deploy all three correctly on [PandaStack](https://pandastack.io).
Choosing the Right Server
Python web frameworks are not standalone servers. They implement either WSGI (Web Server Gateway Interface) or ASGI (Asynchronous Server Gateway Interface) and require an application server to handle HTTP:
| Framework | Interface | Recommended Server |
|---|---|---|
| Flask | WSGI | Gunicorn |
| Django | WSGI | Gunicorn |
| FastAPI | ASGI | Uvicorn + Gunicorn |
Never run flask run, python manage.py runserver, or uvicorn main:app --reload in production — these are development servers only.
Flask Production Setup
# app.py
from flask import Flask, jsonify
import os
app = Flask(__name__)
@app.route('/health')
def health():
return jsonify({'status': 'ok'}), 200
@app.route('/api/items')
def get_items():
return jsonify({'items': []})
if __name__ == '__main__':
# Only for local development
app.run(debug=True)# Dockerfile for Flask
FROM python:3.12-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser
USER appuser
EXPOSE 8000
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", "--workers", "4", "--timeout", "30"]# requirements.txt for Flask
flask>=3.0.0
gunicorn>=21.2.0
psycopg2-binary>=2.9.0
flask-sqlalchemy>=3.1.0Django Production Setup
# Dockerfile for Django
FROM python:3.12-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DJANGO_SETTINGS_MODULE=myproject.settings.production
RUN apt-get update && apt-get install -y --no-install-recommends libpq-dev build-essential && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3"]FastAPI Production Setup
# Dockerfile for FastAPI
FROM python:3.12-slim
WORKDIR /app
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["gunicorn", "main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]FastAPI requires the Uvicorn worker class to handle async requests correctly through Gunicorn's process manager.
Shared pandastack.json Pattern
All three frameworks follow the same pandastack.json pattern — container deployment with a health check path:
{
"type": "container",
"healthCheckPath": "/health"
}Implement the /health endpoint in each framework to return HTTP 200. PandaStack polls this endpoint after every deployment and only routes traffic to the container once it responds successfully.
Gunicorn Worker Count
The standard formula for Gunicorn workers:
workers = (2 × CPU_cores) + 1For most PandaStack containers (2 vCPU), start with -w 5. Adjust based on memory usage — each Gunicorn worker is a separate Python process.
# Gunicorn command with recommended settings
gunicorn app:app --bind 0.0.0.0:8000 --workers 5 --timeout 30 --keepalive 5 --access-logfile - --error-logfile -Logging to - (stdout/stderr) lets PandaStack capture your logs in the dashboard.
Environment Variables
All three frameworks should read configuration from environment variables. Set them in [dashboard.pandastack.io](https://dashboard.pandastack.io):
# Common across Flask, Django, FastAPI
DATABASE_URL=postgresql://user:pass@host:5432/mydb
REDIS_URL=redis://redis.internal:6379
SECRET_KEY=your-application-secret
# Django-specific
DJANGO_SETTINGS_MODULE=myproject.settings.production
ALLOWED_HOST=yourdomain.com
# Flask-specific
FLASK_ENV=productionProvisioning Databases
PandaStack provides managed PostgreSQL, MySQL, Redis, and MongoDB databases. Provision from the Databases section at [dashboard.pandastack.io](https://dashboard.pandastack.io) and use the connection string in DATABASE_URL.
Connect with the appropriate library for your framework:
# Flask + SQLAlchemy
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
# Django
DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql', 'NAME': ...}}
# FastAPI + asyncpg
import databases
database = databases.Database(os.environ['DATABASE_URL'])GitHub Integration and Deployment
Connect your GitHub repository from the PandaStack dashboard. Every push to your deployment branch triggers an automatic Docker build and deploy. For manual or scripted deploys:
npm install -g @pandastack/cli
panda deployProduction Checklist (All Frameworks)
- Gunicorn (or Gunicorn + Uvicorn worker for FastAPI) is the application server
DEBUG/FLASK_DEBUGis off in production- All secrets are environment variables — no hardcoded values
/healthreturns HTTP 200 and is specified inpandastack.json- Logs output to stdout/stderr
- Database connection uses a pool, not individual connections
- Static files handled by framework (WhiteNoise for Django, Flask-Static for Flask)
- GitHub integration connected for automatic deploys
Visit [docs.pandastack.io](https://docs.pandastack.io) for the full deployment documentation.