Deploying Flask: a micro-framework needs micro-configuration, not none
Django ships an ORM, a migration system and an admin out of the box, so a host can safely assume manage.py migrate exists. Flask makes none of those decisions for you — which is exactly the appeal, and exactly why a Flask deploy shouldn’t pretend there’s a framework convention to auto-detect where none exists. The honest version: detect what’s actually a dependency, and stay quiet about everything else.
What’s detected
- Flask itself, from
requirements.txtorpyproject.tomllistingflask. - The web process runs gunicorn against
app:appby default — if the app lives somewhere else, or is built with an app factory, that’s one line to set explicitly:"myapp:create_app()". psycopg/psycopg2as a dependency provisions Postgres and injectsDATABASE_URL; a Redis client (redis,rq) does the same forREDIS_URL.- RQ is offered automatically as a worker when it’s a dependency — RQ has one obvious convention (a queue connected to Redis), so it’s safe to detect.
railyard create my-app https://github.com/me/my-app --addons postgres,redis
What’s deliberately not guessed, and why
Unlike Django, there’s no default release command — because unlike Django, there’s no default migration tool. With Flask-Migrate installed, set the release command to flask db upgrade; with plain Alembic, alembic upgrade head. Same with Celery: there’s no single place a Flask app’s Celery instance lives, so it isn’t auto-detected the way RQ is — one line in a Procfile or on the Workers tab is the honest equivalent of a decision only the app’s own code actually makes:
web: gunicorn app:app --bind 0.0.0.0:$PORT
worker: celery -A myapp.celery worker
railyard scale my-app worker=2
Guessing wrong here wouldn’t just fail — it would silently run the wrong migration tool or point at a Celery app instance that doesn’t exist, which is worse than asking for one line up front.
Config and secrets
SECRET_KEY, FLASK_ENV, and anything else os.environ reads live under Variables, or railyard env:set my-app KEY=VALUE — plain env vars, never baked into the image, so the exact same build runs unchanged from staging through production.
Full reference: Flask docs, Workers and scheduled jobs.