Database Technology
Nectr uses PostgreSQL with async SQLAlchemy for all relational data.- Driver:
asyncpg(pure-async PostgreSQL driver) - ORM: SQLAlchemy 2.0 (async session API)
- Migrations: Alembic
- Connection Pool: Managed by SQLAlchemy
Table Overview
Users
Table:usersModel:
app/models/user.py
Stores GitHub OAuth users who have logged into Nectr.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | Integer | Primary Key | Auto-increment user ID |
github_id | Integer | Unique, Not Null, Indexed | GitHub user ID (from OAuth) |
github_username | String | Not Null | GitHub username (e.g., alice) |
github_access_token | String | Not Null | Encrypted GitHub OAuth token |
email | String | Nullable | User’s public GitHub email |
avatar_url | String | Nullable | GitHub avatar URL |
name | String | Nullable | User’s display name |
created_at | DateTime(timezone=True) | Default now() | When user first logged in |
updated_at | DateTime(timezone=True) | Default now(), On Update | Last profile update |
Token Encryption:
github_access_token is encrypted using Fernet (AES-128-CBC) before storing. The encryption key is SECRET_KEY from environment variables.Model Definition
Model Definition
Installations
Table:installationsModel:
app/models/installation.py
Tracks connected repositories (repos that have webhook installed).
| Column | Type | Constraints | Description |
|---|---|---|---|
id | Integer | Primary Key | Auto-increment ID |
user_id | Integer | Foreign Key (users.id), Indexed | Owner of this installation |
repo_full_name | String | Not Null, Indexed | Repo name (e.g., owner/repo) |
github_repo_id | Integer | Nullable | GitHub repo ID |
webhook_id | Integer | Nullable | GitHub webhook ID |
webhook_secret | String | Nullable | Per-repo HMAC secret |
installation_id | Integer | Nullable | GitHub App installation ID (future) |
is_active | Boolean | Not Null, Default True | Whether webhook is active |
installed_at | DateTime(timezone=True) | Default now() | When repo was connected |
Per-Repo Webhook Secrets: Each installation has its own
webhook_secret for HMAC-SHA256 signature verification. This is more secure than a global secret.Model Definition
Model Definition
Events
Table:eventsModel:
app/models/event.py
Records incoming webhook events from GitHub.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | Integer | Primary Key | Auto-increment event ID |
event_type | String(50) | Not Null | GitHub event type (e.g., pull_request) |
source | String(50) | Not Null | Event source (always github) |
payload | Text | Not Null | JSON-serialized webhook payload |
status | String(20) | Not Null | pending → completed or failed |
created_at | DateTime | Default now() | When event was received |
processed_at | DateTime | Nullable | When background processing finished |
Model Definition
Model Definition
Status Flow
Status Flow
pending- Event received, not yet processedcompleted- Background task finished successfullyfailed- Background task encountered an error
Workflow Runs
Table:workflow_runsModel:
app/models/workflow.py
Tracks execution of background workflows (PR reviews, error triage, etc.).
| Column | Type | Constraints | Description |
|---|---|---|---|
id | Integer | Primary Key | Auto-increment ID |
event_id | Integer | Foreign Key (events.id), Not Null | Parent event |
workflow_type | String(50) | Not Null | Workflow type (e.g., pr_review) |
status | String(20) | Default running | running → completed or failed |
result | Text | Nullable | JSON-serialized workflow result |
error | Text | Nullable | Error message if failed |
started_at | DateTime | Default now() | When workflow started |
completed_at | DateTime | Nullable | When workflow finished |
Model Definition
Model Definition
Workflow Types
Workflow Types
pr_review- AI-powered PR reviewerror_triage- Sentry error classification (future)ticket_sync- Linear ticket updates (future)
Result JSON Example
Result JSON Example
OAuth States
Table:oauth_statesModel:
app/models/oauth_state.py
Stores CSRF state tokens for GitHub OAuth flow.
| Column | Type | Constraints | Description |
|---|---|---|---|
id | Integer | Primary Key | Auto-increment ID |
state | String | Unique, Not Null, Indexed | Random state token |
user_id | Integer | Foreign Key (users.id), Nullable | User who initiated OAuth (nullable for new users) |
created_at | DateTime(timezone=True) | Default now() | When state was created |
expires_at | DateTime(timezone=True) | Not Null | State expiry (5 minutes) |
used | Boolean | Default False | Whether state was consumed |
CSRF Protection: State tokens prevent CSRF attacks by ensuring the OAuth callback is for a session we initiated. States expire after 5 minutes and can only be used once.
Database Initialization
File:app/core/database.py
Async Engine & Session
Async Engine & Session
Migrations (Alembic)
Directory:alembic/versions/
Nectr uses Alembic for schema migrations.
Migration Flow
Migration Flow
-
Generate migration:
-
Apply migration:
-
Automatic on startup:
Example Migration
Example Migration
Connection Pooling
SQLAlchemy manages a connection pool to handle concurrent requests:- Pool size: 10 connections
- Max overflow: 20 connections (30 total)
- Pool recycle: 1 hour (prevents stale connections)
- Pool timeout: 30 seconds
Railway (hosting provider) free tier supports up to 50 concurrent connections. The pool configuration keeps us well under that limit.
Query Patterns
Fetch User by GitHub ID
Fetch User by GitHub ID
Create Installation
Create Installation
Fetch Recent Workflow Runs
Fetch Recent Workflow Runs
Data Retention
Currently, Nectr stores all events and workflow runs indefinitely. Future roadmap includes:- Archive old events (> 90 days) to cold storage
- Delete failed events (> 30 days)
- Compress payloads for storage efficiency
Next Steps
Neo4j Graph
Learn about the knowledge graph schema
Backend Architecture
Explore FastAPI routes and middleware