Compare PostgreSQL and SQLite for Django projects. Learn when to use each, how to switch, and best practices for production databases.
Choosing the right database for your Django project is a critical decision. SQLite ships with Python and is great for development, but PostgreSQL is the production standard. This guide compares both and shows you how to set up PostgreSQL with Django.
| Feature | SQLite | PostgreSQL |
|---|---|---|
| Setup | Zero config (built into Python) | Requires installation and setup |
| Concurrency | Single writer at a time | Full concurrent read/write |
| Performance | Fast for small data (<100K rows) | Scales to billions of rows |
| Data Types | Limited (text, integer, real, blob) | Rich (arrays, JSON, UUID, ranges, etc.) |
| Full-text Search | Basic | Built-in, powerful, multi-language |
| Backup | Copy the file | pg_dump, streaming replication |
| Best For | Development, prototyping, small apps | Production, multi-user, large data |
# Ubuntu/Debian
sudo apt update
sudo apt install postgresql postgresql-contrib
# macOS (Homebrew)
brew install postgresql@16
brew services start postgresql@16
# Check it's running
sudo systemctl status postgresql
# Switch to postgres user
sudo -u postgres psql
-- Create user and database
CREATE USER myproject_user WITH PASSWORD 'secure_password_here';
CREATE DATABASE myproject_db OWNER myproject_user;
-- Grant permissions
ALTER ROLE myproject_user SET client_encoding TO 'utf8';
ALTER ROLE myproject_user SET default_transaction_isolation TO 'read committed';
ALTER ROLE myproject_user SET timezone TO 'UTC';
\q -- Exit psql
pip install psycopg2-binary
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myproject_db',
'USER': 'myproject_user',
'PASSWORD': 'secure_password_here',
'HOST': 'localhost',
'PORT': '5432',
}
}
# Then run migrations
# python manage.py migrate
os.environ.get('DB_PASSWORD') or a .env file with python-decouple.
# models.py - PostgreSQL-specific fields
from django.contrib.postgres.fields import ArrayField
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
# Array field - store list of strings
tags = ArrayField(
models.CharField(max_length=50),
default=list, blank=True
)
# JSON field (works on all DBs in Django 4+)
metadata = models.JSONField(default=dict, blank=True)
# Querying arrays
Product.objects.filter(tags__contains=['sale'])
Product.objects.filter(tags__overlap=['new', 'featured'])
# Full-text search
from django.contrib.postgres.search import SearchVector
Product.objects.annotate(
search=SearchVector('name', 'description')
).filter(search='django framework')
# Backup
pg_dump -U myproject_user myproject_db > backup.sql
# Backup (compressed)
pg_dump -U myproject_user -Fc myproject_db > backup.dump
# Restore
psql -U myproject_user myproject_db < backup.sql
# Automated daily backup (crontab)
0 3 * * * pg_dump -U myuser mydb | gzip > /backups/db_$(date +\%Y\%m\%d).sql.gz