Overview
Scribe Backend uses PostgreSQL as its primary database, typically hosted on Supabase. The application connects via Supabase’s transaction pooler (port 6543) for optimal performance and connection management.Scribe uses SQLAlchemy 2.0 with Alembic for database migrations. All schema changes are version-controlled and reproducible.
Database Architecture
Connection Strategy
- Transaction Pooler (Port 6543): Supabase’s Supavisor handles connection pooling server-side
- NullPool: No client-side pooling — fresh connections per request, immediately closed
- SSL Required: All connections enforce
sslmode=require
Step 1: Set Up Supabase Project
Create Supabase project
- Go to supabase.com
- Click New Project
- Choose a region close to your users
- Set a strong database password
Get connection details
Navigate to Settings → Database in your Supabase dashboard.Copy the Transaction Pooler connection string:
Step 2: Verify Database Connection
Test the connection before running migrations:Alternative: Test with psql
If connection fails, verify your IP is allowed in Supabase’s database settings or disable IP restrictions for development.
Step 3: Run Database Migrations
Alembic manages database schema changes through versioned migration files.Apply Migrations
Check Current Migration Version
View Migration History
Database Schema
Users Table
Emails Table
Queue Items Table
Connection Pooling Explained
Why NullPool?
Scribe uses SQLAlchemy’s NullPool strategy:- No Stale Connections: Fresh connection per request, immediately discarded
- Optimal for Transaction Pooler: Supavisor handles pooling server-side
- Memory Efficient: No idle connections consuming resources
- Works on Raspberry Pi: Minimal memory footprint
Transaction pooler (port 6543) is designed for stateless, short-lived connections. NullPool is the perfect match.
Connection Timeouts
Scribe configures two types of timeouts:Connect Timeout (30 seconds)
Statement Timeout (30 seconds)
Creating Migrations
When you modify database models, create a new migration:models/*.py) with the current database schema and generates a migration file in alembic/versions/.
Review Generated Migration
Apply Migration
Rollback Migration
Database Utilities
Health Check
The/health endpoint checks database connectivity:
Get Database Info
Production Considerations
SSL/TLS Enforcement
All Supabase connections require SSL:Connection Pooler Choice
| Pooler Type | Port | Use Case |
|---|---|---|
| Transaction | 6543 | Stateless apps, serverless, auto-scaling (Scribe) |
| Session | 5432 | Long-running transactions, advisory locks |
Scribe uses transaction pooler (6543) for optimal performance with its stateless pipeline design.
Common Database Operations
Backup Database
Supabase provides automatic backups, but you can also manually export:Restore Database
Reset Database (Development Only)
Troubleshooting
Connection timeout errors
Connection timeout errors
Error:
OperationalError: could not connect to serverSolutions:- Check database host and port in
.env - Verify IP whitelist in Supabase dashboard
- Increase
DB_CONNECT_TIMEOUTfor slow networks:
SSL/TLS errors
SSL/TLS errors
Error:
SSL connection has been closed unexpectedlySolution: Ensure sslmode=require is in the connection string. Scribe handles this automatically via settings.database_url.Migration conflicts
Migration conflicts
Error:
Target database is not up to dateSolution:Port 6543 vs 5432 confusion
Port 6543 vs 5432 confusion
Issue: Using wrong port for connection typeSolution:
- Transaction pooler: Use port 6543 (recommended)
- Session pooler: Use port 5432
- Direct connection: Use port 5432 (not recommended)
Stale connection errors
Stale connection errors
Error:
server closed the connection unexpectedlyCause: Using QueuePool with transaction poolerSolution: Verify poolclass=NullPool in database/base.py. This is the default configuration.Next Steps
- Run the application locally → Running Locally Guide
- Deploy to production → Deployment Guide
