Skip to content

How to Deploy a Flask App to Production (Gunicorn + PostgreSQL, 2026)

Take Flask from app.run() to production: Gunicorn, configuration from the environment, PostgreSQL with Flask-SQLAlchemy, migrations and a live HTTPS URL.

Published
Reading time
3 min
On this page

Key takeaways

  • Never use Flask's built-in server (app.run) in production: run under Gunicorn, which DockHosting does for you.
  • Load SECRET_KEY and DATABASE_URL from the environment; Flask-SQLAlchemy reads DATABASE_URL directly.
  • The default start command is gunicorn app:app, and you can override it if your app object lives elsewhere.

Flask's development server prints a warning for a reason: it's for your laptop. In production you want a real WSGI server, configuration from the environment, and a database that isn't SQLite on a disk that disappears. Here's the whole path to a live HTTPS URL.

1. Structure the app

python
# app.py
import os
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
 
app = Flask(__name__)
app.config["SECRET_KEY"] = os.environ["SECRET_KEY"]
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"].replace(
    "postgresql://", "postgresql+psycopg://", 1
)
db = SQLAlchemy(app)
 
class Note(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    text = db.Column(db.String(500), nullable=False)
 
@app.get("/health")
def health():
    return {"status": "ok"}
 
@app.get("/notes")
def notes():
    return jsonify([{"id": n.id, "text": n.text} for n in Note.query.all()])

The replace call selects the psycopg 3 driver for SQLAlchemy.

text
# requirements.txt
flask
flask-sqlalchemy
flask-migrate
gunicorn
psycopg[binary]

2. Gunicorn, configured for you

DockHosting detects Flask from flask in your requirements and runs it under Gunicorn:

bash
gunicorn app:app

That's module:variable. If you use an application factory, point Gunicorn at it by overriding the start command in the project settings:

bash
gunicorn "myapp:create_app()" --workers 2 --bind 0.0.0.0:$PORT

Two workers per 512 MB is a safe start. Each worker is a full copy of your app in memory.

3. Migrations with Flask-Migrate

bash
flask --app app db init       # once, locally
flask --app app db migrate -m "notes table"

Commit the migrations/ folder, and apply migrations on each release as part of the start command:

bash
flask --app app db upgrade && gunicorn app:app

4. Deploy

bash
curl -fsSL https://cli.dockhosting.dev/install.sh | sh   # Windows: irm https://cli.dockhosting.dev/install.ps1 | iex
dock login
dock deploy

Then:

  1. Create a managed PostgreSQL database and attach it. DATABASE_URL is injected over the private network.
  2. Set SECRET_KEY in the environment variables (python -c "import secrets; print(secrets.token_hex(32))").
  3. dock restart, then open https://<project>.dockhosting.cloud/health.

5. Production checklist

  • SECRET_KEY comes from the environment, never from the code.
  • Debug is off, and app.run() isn't called at import time.
  • Gunicorn workers are sized to your plan's memory (512 MB on Free, 1 GB on Hobby).
  • Static files are served from static/ or a CDN for heavy assets.
  • A /health route makes failed deploys obvious.

Seeing 502s? Work through the 8 causes of a 502. Building a larger app? Compare with the Django and FastAPI guides.

Frequently asked questions

Do I need a Procfile to deploy Flask?

No. DockHosting detects Flask from your requirements and runs it under Gunicorn (gunicorn app:app by default). If your app is created elsewhere, for example by a factory in wsgi.py, override the start command in the project settings.

Why does Flask say 'WARNING: This is a development server'?

Because app.run() starts Werkzeug's development server, which isn't built for production traffic or security. Use Gunicorn instead.

Which Python versions are supported?

Python 3.11 and 3.12, with pip (requirements.txt) or Poetry (pyproject.toml).

  • Flask
  • Python
  • Gunicorn
  • PostgreSQL
  • Tutorial

Written by Doughmi ILYAS

Doughmi builds DockHosting, the developer-first platform behind dock deploy: the build system, the managed databases and the dashboard. On this blog: guides to shipping apps without running servers, written with the commands the platform actually ships.

Summarize with

Share

All posts

Create an account, run dock deploy, and get a live HTTPS URL in minutes.