Skip to content

feat(scale): DB scaling (read replicas + pgbouncer + partitioning + multi-tenant) #356

Description

@Yanstart

Cadrage stratégique 2026 (mai 2026) — PIVOT PRODUIT

PostgreSQL passage à l'échelle pour produit multi-tenant.
Voir `.claude/memory/VISION_ALIGNMENT.md §0.6`.

Contexte

Aujourd'hui : 1 instance PostgreSQL + PostGIS, port 5433, partagée par tous
les services backend. Pas de read replica, pas de pooler, pas de partitioning.
Acceptable PoC. Inacceptable produit multi-tenant à volume.

Volumes à anticiper (estimation produit) :

  • 50 tenants × 10k slides/tenant = 500k slides référencées
  • 50 tenants × 1k annotations/jour = 50k annotations/jour, 18M/an
  • audit_logs : 1 ligne/action × 50 tenants × 100 actions/jour = 5k/jour, 1.8M/an
  • quality_reports : 50 × 200/jour = 10k/jour, 3.6M/an

Cible

  1. Read replicas : 1 master + N replicas, routing read queries vers replicas
  2. pgbouncer : connection pooling pour réduire `max_connections` pressure
  3. Partitioning : `audit_logs`, `quality_reports`, `annotation_events` (Wave 9 feat(quality): versioning Git-like des annotations (branches, merge, diff visuel, rollback) #337) partitionnés par mois ou par tenant_id + mois
  4. Indexes ciblés : analyse `pg_stat_statements` pour identifier slow queries
  5. PostGIS spécifique : `SELECT_EXPLAIN` sur queries spatiales fréquentes, indexes GiST tunés

Approche technique proposée

  1. Read/write split : SQLAlchemy avec 2 engines (master + replica), router automatique selon `async_session.execute` vs `async_session.commit`. Routes `def` (read-heavy) → replica, routes `async` (write) → master.
  2. pgbouncer ajouté à `docker-compose.yml --profile prod` en transaction pooling mode
  3. Partitioning : migration Alembic qui convertit les tables haute-volume en partitioned tables. Stratégie : RANGE par mois.
  4. Tests de charge : k6 / locust avec scenarios produit (Wave 13 #N16) — vérifier scaling
  5. Documentation runbook : `docs/Admin/services/db-scaling.md` (failover, backup, restore, monitoring)

Acceptance criteria

  • Read/write split SQLAlchemy fonctionnel (engine master + N replicas)
  • pgbouncer en `transaction` pooling mode dans `docker-compose.yml`
  • 3 tables partitionnées par mois : audit_logs, quality_reports, annotation_events
  • Migration Alembic propre + script de re-partitionnement existant data
  • Tests : 100 req/s sustained sur GET /api/v1/annotations sans erreurs
  • Métriques Prometheus : connections actives par pool, replication lag, query duration P95
  • Multi-tenant aware : monitoring lag par tenant si schema-per-tenant
  • Documentation runbook complète (failover, backup, restore)
  • Réversibilité : peut être désactivé (env var `DB_REPLICAS_ENABLED=false`) pour dev/test simple

Dépendances

Références

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions