System design details and architectural decisions
- System Design
- Database Strategy Pattern
- Development vs Production
- Retry Logic
- Vector Search Design
- Design Principles
- Extension Path
- Why This Architecture
ChatVector uses a layered architecture:
API Layer → Service Layer → Database Abstraction → PostgreSQL (pgvector)
The system is designed for:
- Production parity
- Clean separation of concerns
- Resilience against transient failures
- Extensibility
An abstract base class defines the contract:
DatabaseService
Two implementations:
SQLAlchemyService(development)SupabaseService(production)
Selected via environment-aware factory in:
app/db/__init__.py
This ensures:
- No direct DB coupling in business logic
- Environment-specific behavior isolated
- Easy extension for future backends
| Environment | Database | Implementation |
|---|---|---|
| Development | PostgreSQL (local Docker) | SQLAlchemyService |
| Production | Supabase (PostgreSQL) | SupabaseService |
SQLite was intentionally removed to ensure:
- Production parity
- Consistent vector behavior
- Identical query semantics
All database operations are wrapped with retry logic.
Purpose:
- Handle transient connection failures
- Protect against Supabase network hiccups
- Improve production resilience
Retries are applied at the service layer, not the API layer, to maintain separation of concerns.
- PostgreSQL with
pgvector - Embedding dimension:
3072(Gemini-compatible) ivfflatindexing supported- Cosine similarity search
Schema overview:
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
file_name TEXT,
created_at TIMESTAMP DEFAULT NOW(),
status VARCHAR(50) DEFAULT 'processing'
);
CREATE TABLE document_chunks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
document_id UUID REFERENCES documents(id),
chunk_text TEXT,
embedding vector(3072),
created_at TIMESTAMP DEFAULT NOW()
);Local development mirrors production database behavior.
Environment selection happens at the factory layer.
No direct DB calls outside app.db.
All database operations are async.
Transient failures are handled automatically.
Future improvements may include:
- Multi-tenant support
- Background task queue
- Embedding provider abstraction
- Observability and metrics
- Caching layer
- Read replicas
The current abstraction layer supports these extensions without major refactors.
This project demonstrates:
- Clean service abstraction
- Production-ready database design
- Resilient error handling
- Contributor-friendly extensibility
- Clear separation between operational and architectural concerns