Overview
Nectr uses two databases:- PostgreSQL — User accounts, repo connections, webhook events, PR review history
- Neo4j — Knowledge graph (files, PRs, developers, issues, and their relationships)
PostgreSQL Setup
Option 1: Supabase (Recommended)
Supabase provides a free PostgreSQL database with connection pooling.Create Supabase project
- Go to supabase.com and sign up
- Click New Project
- Choose an organization (or create one)
- Set:
- Name:
nectr-db - Database Password: Generate a strong password
- Region: Choose one close to your deployment
- Name:
- Click Create new project (takes 2-3 minutes)
Get connection string
- Navigate to Project Settings → Database
- Scroll to Connection Pooling section
- Select Session mode
- Copy the Connection string
Format for SQLAlchemy
Convert the Supabase connection string to SQLAlchemy async format:Supabase format:SQLAlchemy format (add Set this as
+asyncpg):DATABASE_URL in your .env file.Option 2: Railway PostgreSQL
Railway provides a managed PostgreSQL addon.Add PostgreSQL to Railway project
- Open your Railway project
- Click New → Database → PostgreSQL
- Railway will automatically provision the database
Get DATABASE_URL
Railway automatically sets
DATABASE_URL in your environment.To view it:- Click on the PostgreSQL service
- Go to Variables tab
- Copy the
DATABASE_URLvalue
Option 3: Local PostgreSQL
For local development only.Database Schema
Nectr uses Alembic for migrations. The schema is created automatically on startup.Tables
usersid(primary key)github_id(unique, indexed)github_usernamegithub_access_token(encrypted with Fernet)created_at,updated_at
id(primary key)user_id(foreign key → users)repo_full_name(e.g.,owner/repo)installation_id(GitHub App installation ID)github_repo_id(GitHub repository ID)webhook_idwebhook_secret(unique per repo)is_activecreated_at
id(primary key)event_type(e.g.,pull_request,issues)payload(JSON)status(pending,completed,failed)deduplication_hash(prevents duplicate event processing)created_at,processed_at
id(primary key)event_id(foreign key → events)workflow_type(e.g.,pr_review)status(running,completed,failed)result(JSON, includes AI summary and verdict)errorcreated_at,completed_at
id(primary key)state(unique, indexed)created_at- Cleaned up after OAuth flow completes
Migrations
Migrations are inalembic/versions/:
- e83f4b0f5bf4 — Initial schema (users, installations, oauth_states)
- a1b2c3d4e5f6 — Add
installation_idandgithub_repo_idto installations
Neo4j Setup
Create Neo4j Aura Instance
Neo4j Aura provides a free tier with 200k nodes and 400k relationships.Sign up for Neo4j Aura
Go to neo4j.com/cloud/aura and create an account.
Create free instance
- Click Create database
- Select Free tier
- Choose a region (same as your backend deployment)
- Click Create
- Wait 2-3 minutes for provisioning
Save credentials
You’ll receive:
- URI:
neo4j+s://xxxxx.databases.neo4j.io - Username:
neo4j - Password:
generated-password
.env:Whitelist IPs
Neo4j Aura requires IP whitelisting:
- In Neo4j console, go to instance → Security → Allowed IPs
- For development: Add
0.0.0.0/0(allow all) - For production: Add Railway/Vercel IPs (requires paid plan for static IPs)
Neo4j Schema
Nectr creates constraints and indexes automatically on startup (seeapp/core/neo4j_schema.py).
Node Types
Repositoryfull_name(unique) — e.g.,owner/reposcanned_at— timestamp of last file tree scan
repo+path(node key) — unique per repoextension— file extension
repo+number(node key) — unique per repotitleverdict— AI verdict (APPROVE,REQUEST_CHANGES, etc.)created_at
login(unique) — GitHub username
repo+number(node key) — unique per repotitlestate—openorclosed
Relationships
(Repository)-[:CONTAINS]->(File)(PullRequest)-[:TOUCHES]->(File)— PR modified this file(PullRequest)-[:AUTHORED_BY]->(Developer)(Developer)-[:CONTRIBUTED_TO]->(Repository)(PullRequest)-[:CLOSES]->(Issue)— PR closes this issue
Constraints
Created automatically on startup:Graph Building
Initial Repo Scan
When you connect a repo, Nectr:- Creates
(Repository)node - Recursively fetches file tree from GitHub
- Creates
(File)node for each file - Creates
(Repository)-[:CONTAINS]->(File)relationships
app/services/graph_builder.py:build_repo_graph().
PR Indexing
After reviewing a PR, Nectr:- Creates
(PullRequest)node - Creates
(Developer)node (if new) - Creates relationships:
(PullRequest)-[:TOUCHES]->(File)for each changed file(PullRequest)-[:AUTHORED_BY]->(Developer)(Developer)-[:CONTRIBUTED_TO]->(Repository)(PullRequest)-[:CLOSES]->(Issue)for linked issues
app/services/graph_builder.py:index_pr().
Auto-Scan on Startup
Nectr automatically scans repos not yet indexed in Neo4j on startup:- Waits 5 seconds after server starts
- Fetches all active installations from PostgreSQL
- Checks each repo in Neo4j
- Scans repos not yet indexed
app/main.py:30-86 (_scan_unindexed_repos function).
Connection Pooling
PostgreSQL
Supabase handles connection pooling automatically (Session mode, port 5432). SQLAlchemy pool settings (seeapp/core/database.py):
Neo4j
Neo4j driver manages connection pooling internally. No configuration needed. Seeapp/core/neo4j_client.py for driver initialization.
Backup and Restore
PostgreSQL (Supabase)
Backup:Neo4j Aura
Neo4j Aura provides automatic backups:- Free tier: Backups every 24 hours, retained for 3 days
- Pro tier: Backups every 6 hours, retained for 7 days
Monitoring
PostgreSQL
Supabase Dashboard:- Database size and usage
- Active connections
- Query performance
- Table sizes
Neo4j
Neo4j Aura Console:- Node and relationship counts
- Query performance
- Storage usage
Troubleshooting
PostgreSQL: Connection refused
PostgreSQL: Connection refused
- Check
DATABASE_URLformat:postgresql+asyncpg://... - Verify host, port, username, password
- For Supabase: use Session mode (port 5432)
- Test connection:
psql "postgresql://..."
PostgreSQL: Too many connections
PostgreSQL: Too many connections
- Reduce SQLAlchemy
pool_size+max_overflowinapp/core/database.py - Use Supabase connection pooling (recommended)
- Check for connection leaks (ensure
async withcontext managers)
Neo4j: Connection timeout
Neo4j: Connection timeout
- Verify
NEO4J_URIusesneo4j+s://(notbolt://) - Check Neo4j Aura instance is running
- Verify IP is whitelisted in Neo4j console
- Test connection in Neo4j Browser
Neo4j: Authentication failed
Neo4j: Authentication failed
- Verify
NEO4J_USERNAMEandNEO4J_PASSWORDin.env - Check credentials in Neo4j Aura console
- Password is case-sensitive
Alembic: Migration fails
Alembic: Migration fails
- Check Alembic logs in backend startup
- Manually run:
alembic upgrade head - Verify
DATABASE_URLis correct - Check for schema conflicts (drop tables and re-run)
Neo4j: Constraint creation fails
Neo4j: Constraint creation fails
- Check Neo4j version (needs 5.0+)
- Older versions don’t support
IF NOT EXISTSsyntax - Manually create constraints in Neo4j Browser
Next Steps
Neo4j Schema
Complete Neo4j schema reference
Architecture
Understand Nectr’s data flow
Local Development
Set up local databases
Deployment
Deploy with production databases