Deploy a Flask app on Render

From a folder on your laptop to a live URL, step by step.

Render is a platform service: you connect a Git repository, tell it how to install and start your app, and it handles servers, HTTPS and redeploys. This guide takes a minimal Flask app from your laptop to a public URL, and covers the details that usually trip people up the first time.

You'll need: Python 3 installed, Git, a GitHub account and a free Render account. Allow about 30 minutes.

1. Create the app

Make a project folder with a virtual environment, and install Flask plus gunicorn, the production server Render will use:

mkdir flask-render-demo
cd flask-render-demo
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install flask gunicorn

Create app.py:

import os
from flask import Flask, jsonify

app = Flask(__name__)
app.config["SECRET_KEY"] = os.environ.get("SECRET_KEY", "dev-only-change-me")

@app.get("/")
def home():
    return "Hello from Flask on Render!"

@app.get("/api/health")
def health():
    return jsonify(status="ok")

Check it runs locally with Flask's development server:

flask --app app run --debug

Open http://127.0.0.1:5000 and you should see the greeting.

On Windows, gunicorn won't run locally - that's fine. You only need it on Render, which runs Linux. Use flask run for local development.

2. Record dependencies and ignore the right files

Render installs packages from requirements.txt. Generate it from your virtual environment:

pip freeze > requirements.txt

Then create .gitignore so your virtual environment and secrets never reach GitHub:

.venv/
__pycache__/
.env
*.db

Optionally, pin your Python version by adding a .python-version file containing a version such as 3.13, so Render uses the same one you tested with.


3. Push to GitHub

git init
git add .
git commit -m "Flask app ready for Render"

Create an empty repository on GitHub, then follow the commands it shows to add the remote and push.


4. Create the web service on Render

In the Render dashboard, choose New → Web Service, connect your GitHub account and pick the repository. Fill in:

  • Language / runtime: Python
  • Build command: pip install -r requirements.txt
  • Start command: gunicorn app:app
  • Instance type: Free, while you're learning

In gunicorn app:app, the first app is the file (app.py) and the second is the Flask object inside it. You don't need to configure a port: Render sets a PORT environment variable and gunicorn binds to it automatically.

Click create, watch the build log, and after a minute or two your app is live at a .onrender.com address.


5. Add environment variables

Never commit secrets. In your service's Environment tab, add SECRET_KEY with a long random value (python -c "import secrets; print(secrets.token_hex(32))" generates one). Your code already reads it with os.environ.get. Database URLs and API keys go here too.


6. Redeploys happen on push

By default Render redeploys whenever you push to the connected branch. Make a change, commit, push, and watch the new version build. If a build fails, the previous version keeps running.


What the free tier means in practice

  • It sleeps. Free web services spin down after a period without traffic, and the first request afterwards can take up to a minute while it wakes. Fine for learning; not for a client's site.
  • The disk is temporary. Files written at runtime - including a SQLite database - disappear on every redeploy and restart. Use a hosted database such as Neon or Supabase (both have free tiers) and read its URL from an environment variable.

Fixing common errors

  • gunicorn: command not found or ModuleNotFoundError - the package is missing from requirements.txt. Install it locally, re-run pip freeze > requirements.txt, commit and push.
  • Failed to find attribute 'app' - your start command doesn't match your file or variable name. If your file is main.py with application = Flask(__name__), the command is gunicorn main:application.
  • Works locally, 500 error on Render - check the service's Logs tab. The usual cause is a missing environment variable or a file path that only exists on your machine.
  • Build installs Windows-only packages - if pip freeze captured something like pywin32, delete that line from requirements.txt.

Where to go next

Add a database: create a free Postgres database on Neon, store its connection string in a DATABASE_URL environment variable, and connect with SQLAlchemy or psycopg. Or put a frontend in front of your API with our Vue + Flask + SQLite guide.

All guides Flask primer