This guide explains how to upgrade your Flask Todo App from SQLite to PostgreSQL for production use on Render.
- Reliability: SQLite is file-based and not ideal for production web apps
- Concurrency: PostgreSQL handles multiple concurrent users better
- Scalability: Better performance as your app grows
- Data Persistence: Render's free PostgreSQL databases are more stable than file-based SQLite
- Your app is getting real users
- You need guaranteed data persistence
- You're moving beyond testing/development
- Existing Flask Todo App deployed on Render
- Access to your Render dashboard
- Your app source code updated locally
-
Log in to Render Dashboard
- Go to dashboard.render.com
-
Create New PostgreSQL Database
- Click "New +" button
- Select "PostgreSQL"
- Choose your preferred region (same as your web service recommended)
- Name your database (e.g., "flask-todo-db")
- Plan: Free tier available
- Click "Create Database"
-
Wait for Database to Initialize
- This takes a few minutes
- Once ready, you'll see the connection details
Add psycopg2 to your requirements.txt:
Flask==2.3.0
SQLAlchemy==2.0.0
psycopg2-binary==2.9.6
# ...other dependencies...
In your app.py, update the database URI to use PostgreSQL when the DATABASE_URL environment variable is present:
import os
from flask import Flask
from sqlalchemy import create_engine
app = Flask(__name__)
# Use DATABASE_URL if available (Render), otherwise use SQLite
database_url = os.getenv('DATABASE_URL')
if database_url:
# Fix the PostgreSQL URI format for SQLAlchemy
if database_url.startswith('postgres://'):
database_url = database_url.replace('postgres://', 'postgresql://', 1)
app.config['SQLALCHEMY_DATABASE_URI'] = database_url
else:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = FalseUpdate your render.yaml to include the PostgreSQL database and link it to your web service:
services:
- type: web
name: flask-todo-app
env: python
plan: free
buildCommand: pip install -r requirements.txt
startCommand: gunicorn app:app
envVars:
- key: PYTHON_VERSION
value: 3.10
- key: OAUTHLIB_INSECURE_TRANSPORT
value: "0"
- key: APP_SECRET_KEY
generateValue: true
- key: AUTH0_DOMAIN
sync: false
- key: AUTH0_CLIENT_ID
sync: false
- key: AUTH0_CLIENT_SECRET
sync: false
- key: AUTH0_CALLBACK_URL
value: https://${RENDER_EXTERNAL_HOSTNAME}/callback
- key: DATABASE_URL
fromDatabase:
name: flask-todo-db
property: connectionString
databases:
- name: flask-todo-db
databaseName: flask_todo
plan: freeWhen your app first connects to PostgreSQL, it needs to create the tables:
Update your app initialization to create tables on startup:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
# In your init_todo() function or app creation:
with app.app_context():
db.create_all()- SSH into your Render web service
- Run:
python >>> from app import app, db >>> with app.app_context(): ... db.create_all() >>> exit()
-
Commit and push your changes
git add requirements.txt app.py render.yaml git commit -m "Add PostgreSQL support" git push origin main -
Render automatically redeploys
- Check the "Logs" tab in Render dashboard
- Wait for build to complete
- Visit your app:
https://<your-app-name>.onrender.com - Create a test todo
- Refresh the page - data should persist
- Check Render PostgreSQL dashboard to confirm queries are running
If you need to go back to SQLite:
- Remove the
DATABASE_URLenvironment variable from Render - Revert your
app.pyto use SQLite only - Push to GitHub
- Render will redeploy with SQLite
- Your
DATABASE_URLmay be malformed - Ensure you're using
postgresql://notpostgres:// - Check that the connection string includes username and password
- Tables haven't been created yet
- Ensure
db.create_all()runs on app startup - Check application logs for errors
- PostgreSQL service may still be starting
- Wait a few minutes and try again
- Check that your web service can reach the database (same region recommended)
- Free tier databases may have limitations
- Consider upgrading to a paid plan for production
- Alternatively, implement regular backups
- Render PostgreSQL Documentation
- SQLAlchemy PostgreSQL Dialect
- PostgreSQL Connection Strings
- Database Migrations with Flask-Migrate
Once PostgreSQL is running reliably:
- Implement database migrations using Flask-Migrate
- Set up automated backups in Render
- Consider upgrading to a paid database plan for production use