ADR 0003: PostgreSQL as Primary Database
Status: Accepted
Date: 2025-01-25
Track: Software
Context
KoproGo requires a database that supports:
ACID transactions for financial operations (double-entry accounting, payments)
Complex queries (ownership history, financial reports, aggregations)
JSON/JSONB for flexible schema evolution (user preferences, metadata)
Foreign keys & constraints to enforce referential integrity
Multi-tenancy with organization-level data isolation
Mature Rust ecosystem (compile-time query verification)
We evaluated PostgreSQL 15, MySQL 8.0, ScyllaDB, and MongoDB.
Decision
We chose PostgreSQL 15 as the primary database.
Reasons:
✅ Rock-solid ACID guarantees (critical for financial data)
✅ Rich constraint system: CHECK, UNIQUE, FK, custom domains
✅ JSON/JSONB support: Flexible schema for evolving features
✅ Powerful query capabilities: CTEs, window functions, aggregates
✅ Excellent Rust integration: sqlx with compile-time query verification
✅ Mature ecosystem: Proven at scale (Instagram, GitHub, Discord)
✅ Open-source: No vendor lock-in, AGPL-compatible
✅ Cost-effective: Runs efficiently on modest hardware (€33/month OVH VPS)
sqlx integration:
// Compile-time query verification
let building = sqlx::query_as!(
Building,
"SELECT * FROM buildings WHERE id = $1",
id
)
.fetch_one(&pool)
.await?;
Queries are validated against actual database schema at compile time, catching typos and schema mismatches early.
Consequences
Positive:
✅ Strong data integrity: CHECK constraints enforce business rules (quote-part ≤ 100%)
✅ Compile-time query safety: sqlx macros catch SQL errors before deployment
✅ Rich querying: Complex financial reports without ORMs
✅ Proven reliability: MVCC handles concurrency without application-level locking
✅ Future-proof: Supports partitioning, replication, sharding if needed
Negative:
⚠️ Vertical scaling limits: Single-server for MVP (acceptable for 5k copropriétés)
⚠️ No native multi-region: Requires replication setup (not needed until Phase 3)
⚠️ Complex migrations: Schema changes require careful migration strategy
Performance (October 2025 load tests):
Connection pool: 10 connections
Query latency P99: < 50ms
Throughput: 287 req/s (single instance, bottleneck is business logic not DB)
Alternatives Considered
MySQL 8.0:
✅ Similar features, wide adoption
❌ Weaker constraint system (no CHECK until 8.0)
❌ Less robust JSON support
Verdict: PostgreSQL’s constraints and JSON support preferred
ScyllaDB (planned for Phase 2):
✅ Horizontal scalability, low latency
❌ No transactions across partitions
❌ Eventual consistency (not acceptable for accounting)
Verdict: Future addition for hot-path reads (metrics, logs), not primary DB
MongoDB:
✅ Flexible schema, easy development
❌ Weaker ACID guarantees (even with transactions)
❌ No foreign keys (enforced application-side)
Verdict: Rejected due to financial data requirements
Schema Design Highlights
Multi-tenancy:
Every table has
organization_idcolumnRow-Level Security (RLS) enforces isolation (planned for Phase 2)
Key constraints:
-- Quote-part validation
CHECK (ownership_percentage > 0 AND ownership_percentage <= 1)
-- PCMN code format
CHECK (code ~ '^\d{2,6}$')
-- VAT rates
CHECK (vat_rate IN (0.06, 0.12, 0.21))
-- Temporal validity
CHECK (end_date IS NULL OR end_date > start_date)
Migration strategy:
sqlx migrations (
backend/migrations/)Semantic versioning (20250127000000_description.sql)
Reversible migrations via
down.sql(where possible)CI/CD validation before merge
Configuration
Connection string (backend/.env):
DATABASE_URL=postgresql://koprogo:koprogo123@localhost:5432/koprogo_db
Production settings:
SSL mode:
requireConnection pool: 10 connections
Statement timeout: 30s
Idle timeout: 10 minutes
Next Steps
✅ Implement core schema (Buildings, Units, Owners) (Done)
✅ Add PCMN accounting tables (Done, Issue #79)
⏳ Implement Row-Level Security for multi-tenancy (Phase 2)
⏳ Evaluate read replicas for horizontal scaling (Phase 3)
⏳ Consider adding ScyllaDB for hot-path reads (metrics, audit logs)
References
PostgreSQL 15 Documentation: https://www.postgresql.org/docs/15/
sqlx GitHub: https://github.com/launchbadge/sqlx
KoproGo migrations:
backend/migrations/