You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
316 lines
9.9 KiB
Markdown
316 lines
9.9 KiB
Markdown
|
2 months ago
|
# ADR-003 : Supabase comme Backend et Base de Données
|
||
|
|
|
||
|
|
**Statut** : ✅ Accepté
|
||
|
|
**Date** : Octobre 2025
|
||
|
|
**Décideurs** : Équipe Architecture
|
||
|
|
**Tags** : `backend`, `database`, `baas`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Contexte
|
||
|
|
|
||
|
|
L'application moderne nécessite :
|
||
|
|
- **Base de données PostgreSQL**
|
||
|
|
- **Authentification** sécurisée
|
||
|
|
- **API** pour accès aux données
|
||
|
|
- **Temps réel** (stocks, notifications)
|
||
|
|
- **Storage** (images d'outils)
|
||
|
|
|
||
|
|
Contrainte : **MCP Supabase disponible** (accès privilégié)
|
||
|
|
|
||
|
|
### Options considérées
|
||
|
|
1. **Supabase** (BaaS - Backend as a Service)
|
||
|
|
2. **Firebase** (Google)
|
||
|
|
3. **PocketBase** (self-hosted)
|
||
|
|
4. **PostgreSQL + Backend custom** (Node.js/Express)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Décision
|
||
|
|
|
||
|
|
✅ **Nous adoptons Supabase comme backend et base de données**
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Justification
|
||
|
|
|
||
|
|
### Pourquoi Supabase ?
|
||
|
|
|
||
|
|
#### 1. **PostgreSQL Véritable** 🐘
|
||
|
|
- Base de données **relationnelle complète**
|
||
|
|
- SQL standard (pas de limitations Firebase)
|
||
|
|
- Triggers, fonctions, vues, index
|
||
|
|
- Relations complexes possibles
|
||
|
|
- Migration facilitée (si besoin)
|
||
|
|
|
||
|
|
#### 2. **Authentification Intégrée** 🔐
|
||
|
|
- **Supabase Auth** : JWT, session management
|
||
|
|
- Providers OAuth (Google, GitHub, etc.)
|
||
|
|
- **Row Level Security (RLS)** : sécurité au niveau BDD
|
||
|
|
- Magic links, OTP
|
||
|
|
- Gestion des rôles
|
||
|
|
|
||
|
|
#### 3. **Realtime Built-in** ⚡
|
||
|
|
- **Supabase Realtime** : WebSocket automatique
|
||
|
|
- Écoute des changements BDD (INSERT, UPDATE, DELETE)
|
||
|
|
- **Broadcast** : Pub/Sub pour events
|
||
|
|
- **Presence** : utilisateurs connectés
|
||
|
|
- Parfait pour stocks temps réel ✅
|
||
|
|
|
||
|
|
#### 4. **API Auto-générée** 🚀
|
||
|
|
- **PostgREST** : API REST générée depuis schéma
|
||
|
|
- **GraphQL** (expérimental)
|
||
|
|
- SDK JavaScript/TypeScript officiel
|
||
|
|
- Queries filtrables, triables, paginables
|
||
|
|
|
||
|
|
#### 5. **Storage Intégré** 📦
|
||
|
|
- **Supabase Storage** : stockage de fichiers
|
||
|
|
- Images d'outils (avec CDN)
|
||
|
|
- Buckets publics/privés
|
||
|
|
- Intégration RLS
|
||
|
|
|
||
|
|
#### 6. **Developer Experience** 💻
|
||
|
|
- Dashboard web complet
|
||
|
|
- Migrations SQL versionnées
|
||
|
|
- Logs en temps réel
|
||
|
|
- **MCP Supabase** : accès privilégié ✅
|
||
|
|
|
||
|
|
#### 7. **Gratuit pour Démarrer** 💰
|
||
|
|
- Tier gratuit généreux
|
||
|
|
- 500 MB database
|
||
|
|
- 1 GB storage
|
||
|
|
- 2 GB bandwidth
|
||
|
|
- Suffisant pour projet académique
|
||
|
|
|
||
|
|
#### 8. **Écosystème Next.js** 🔗
|
||
|
|
- Intégration Next.js excellente
|
||
|
|
- SSR support (@supabase/ssr)
|
||
|
|
- Middleware auth Next.js
|
||
|
|
- Exemples officiels
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Comparaison des Alternatives
|
||
|
|
|
||
|
|
| Critère | Supabase | Firebase | PocketBase | Postgres Custom |
|
||
|
|
|---------|----------|----------|------------|-----------------|
|
||
|
|
| **Type BDD** | PostgreSQL | NoSQL | SQLite | PostgreSQL |
|
||
|
|
| **SQL** | ✅ Complet | ❌ Non | ✅ Oui | ✅ Complet |
|
||
|
|
| **Realtime** | ✅✅✅ Natif | ✅ Natif | ⚠️ Manuel | ❌ À développer |
|
||
|
|
| **Auth** | ✅ Intégré | ✅ Intégré | ✅ Intégré | ❌ À développer |
|
||
|
|
| **API** | ✅ Auto-généré | ✅ SDK | ✅ Auto | ❌ À développer |
|
||
|
|
| **Storage** | ✅ Intégré | ✅ Intégré | ✅ Intégré | ❌ AWS S3 séparé |
|
||
|
|
| **Open Source** | ✅ Oui | ❌ Non | ✅ Oui | ✅ Oui |
|
||
|
|
| **Self-hosted** | ⚠️ Docker | ❌ Non | ✅ Facile | ✅ Oui |
|
||
|
|
| **Prix** | ✅ Gratuit start | ⚠️ Pay-as-go | ✅ Gratuit | ⚠️ Hébergement |
|
||
|
|
| **Communauté** | ✅✅ | ✅✅✅ | ✅ | ✅✅ |
|
||
|
|
| **MCP** | ✅ Disponible | ❌ Non | ❌ Non | ❌ Non |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Architecture avec Supabase
|
||
|
|
|
||
|
|
### Vue d'Ensemble
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────┐
|
||
|
|
│ Next.js App (Frontend + BFF) │
|
||
|
|
└────────┬───────────────────────┬────────┘
|
||
|
|
│ │
|
||
|
|
│ Supabase Client │ Server API
|
||
|
|
│ │
|
||
|
|
┌────────▼───────────────────────▼────────┐
|
||
|
|
│ Supabase Platform │
|
||
|
|
│ ┌─────────────────────────────────┐ │
|
||
|
|
│ │ PostgreSQL + PostgREST (API) │ │
|
||
|
|
│ └─────────────────────────────────┘ │
|
||
|
|
│ ┌─────────────────────────────────┐ │
|
||
|
|
│ │ Supabase Auth (JWT + OAuth) │ │
|
||
|
|
│ └─────────────────────────────────┘ │
|
||
|
|
│ ┌─────────────────────────────────┐ │
|
||
|
|
│ │ Supabase Realtime (WebSocket) │ │
|
||
|
|
│ └─────────────────────────────────┘ │
|
||
|
|
│ ┌─────────────────────────────────┐ │
|
||
|
|
│ │ Supabase Storage (CDN) │ │
|
||
|
|
│ └─────────────────────────────────┘ │
|
||
|
|
└─────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
### Utilisation par Microservice
|
||
|
|
|
||
|
|
| Microservice | Usage Supabase |
|
||
|
|
|--------------|----------------|
|
||
|
|
| **Auth Service** | Supabase Auth (géré) |
|
||
|
|
| **Catalogue Service** | Tables `outils`, `categories` |
|
||
|
|
| **Reservation Service** | Table `reservations` |
|
||
|
|
| **Inventory Service** | Table `stocks` + **Realtime** |
|
||
|
|
| **Payment Service** | Table `transactions` (logs) |
|
||
|
|
| **Notification Service** | Realtime Channels (events) |
|
||
|
|
|
||
|
|
### Row Level Security (RLS)
|
||
|
|
|
||
|
|
```sql
|
||
|
|
-- Exemple : Les utilisateurs ne voient que leurs réservations
|
||
|
|
CREATE POLICY "Users can view own reservations"
|
||
|
|
ON reservations FOR SELECT
|
||
|
|
USING (auth.uid() = utilisateur_id);
|
||
|
|
|
||
|
|
-- Exemple : Les utilisateurs peuvent créer leurs propres réservations
|
||
|
|
CREATE POLICY "Users can create reservations"
|
||
|
|
ON reservations FOR INSERT
|
||
|
|
WITH CHECK (auth.uid() = utilisateur_id);
|
||
|
|
```
|
||
|
|
|
||
|
|
**Avantage** : Sécurité au niveau BDD (pas de bypass possible)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Realtime pour Stocks
|
||
|
|
|
||
|
|
### Problème Legacy
|
||
|
|
- Synchronisation quotidienne (batch CSV)
|
||
|
|
- Décalage 24h ❌
|
||
|
|
- Incohérences fréquentes
|
||
|
|
|
||
|
|
### Solution Supabase Realtime
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Écoute des changements stocks en temps réel
|
||
|
|
const channel = supabase
|
||
|
|
.channel('stocks-changes')
|
||
|
|
.on(
|
||
|
|
'postgres_changes',
|
||
|
|
{
|
||
|
|
event: 'UPDATE',
|
||
|
|
schema: 'public',
|
||
|
|
table: 'stocks'
|
||
|
|
},
|
||
|
|
(payload) => {
|
||
|
|
console.log('Stock updated:', payload.new)
|
||
|
|
// Mise à jour UI automatique
|
||
|
|
updateStockCache(payload.new)
|
||
|
|
}
|
||
|
|
)
|
||
|
|
.subscribe()
|
||
|
|
```
|
||
|
|
|
||
|
|
**Résultat** : Stocks temps réel ⚡ (0 décalage)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Event Bus avec Realtime Channels
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Service A émet un event
|
||
|
|
await supabase.channel('events')
|
||
|
|
.send({
|
||
|
|
type: 'broadcast',
|
||
|
|
event: 'reservation.created',
|
||
|
|
payload: { reservationId, outilId }
|
||
|
|
})
|
||
|
|
|
||
|
|
// Service B écoute l'event
|
||
|
|
supabase.channel('events')
|
||
|
|
.on('broadcast', { event: 'reservation.created' }, (payload) => {
|
||
|
|
console.log('Reservation created:', payload)
|
||
|
|
// Déclencher logique métier
|
||
|
|
})
|
||
|
|
.subscribe()
|
||
|
|
```
|
||
|
|
|
||
|
|
**Utilisation** : Communication asynchrone entre microservices
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Conséquences
|
||
|
|
|
||
|
|
### ✅ Avantages
|
||
|
|
|
||
|
|
1. **Productivité** : Backend prêt à l'emploi (gain de temps)
|
||
|
|
2. **Realtime natif** : Problème stocks résolu ✅
|
||
|
|
3. **Sécurité** : RLS + JWT built-in
|
||
|
|
4. **Scalabilité** : Infrastructure gérée (pas d'ops)
|
||
|
|
5. **MCP** : Accès privilégié via Copilot ✅
|
||
|
|
6. **Open Source** : Pas de vendor lock-in (self-host possible)
|
||
|
|
7. **Migrations** : Versionnées et traçables
|
||
|
|
8. **Dashboard** : Monitoring et logs
|
||
|
|
|
||
|
|
### ⚠️ Inconvénients
|
||
|
|
|
||
|
|
1. **Abstraction** : Moins de contrôle qu'un backend custom
|
||
|
|
2. **Limites tier gratuit** : 500 MB database (suffisant pour démo)
|
||
|
|
3. **Courbe apprentissage** : Concepts spécifiques (RLS, Realtime)
|
||
|
|
4. **Vendor** : Dépendance à Supabase (mais mitigée par open source)
|
||
|
|
|
||
|
|
### 🛠️ Mitigations
|
||
|
|
|
||
|
|
- **Abstraction** : Repository Pattern isole Supabase
|
||
|
|
- **Limites** : Projet académique = tier gratuit OK
|
||
|
|
- **Apprentissage** : Documentation excellente
|
||
|
|
- **Vendor lock-in** : PostgreSQL standard = migration possible
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Alternatives Rejetées
|
||
|
|
|
||
|
|
### ❌ Firebase
|
||
|
|
|
||
|
|
**Avantages** :
|
||
|
|
- Écosystème Google mature
|
||
|
|
- Très populaire
|
||
|
|
|
||
|
|
**Raisons du rejet** :
|
||
|
|
- **NoSQL** (Firestore) : moins adapté que SQL
|
||
|
|
- Queries limitées (pas de JOIN)
|
||
|
|
- Pas de MCP disponible
|
||
|
|
- Moins "impressionnant" techniquement (trop simple)
|
||
|
|
|
||
|
|
### ❌ PocketBase
|
||
|
|
|
||
|
|
**Avantages** :
|
||
|
|
- Ultra simple (1 fichier Go)
|
||
|
|
- SQLite (léger)
|
||
|
|
- Self-hosted facile
|
||
|
|
|
||
|
|
**Raisons du rejet** :
|
||
|
|
- **SQLite** : moins robuste que PostgreSQL
|
||
|
|
- Moins adapté pour microservices
|
||
|
|
- Communauté plus petite
|
||
|
|
- Pas de MCP
|
||
|
|
|
||
|
|
### ❌ PostgreSQL + Backend Custom
|
||
|
|
|
||
|
|
**Avantages** :
|
||
|
|
- Contrôle total
|
||
|
|
- Flexibilité maximale
|
||
|
|
|
||
|
|
**Raisons du rejet** :
|
||
|
|
- **Trop de temps de développement** (auth, API, realtime)
|
||
|
|
- Focus projet = architecture, pas infra
|
||
|
|
- Realtime difficile à implémenter
|
||
|
|
- Pas de valeur ajoutée pour démonstration
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Références
|
||
|
|
|
||
|
|
- [Supabase Documentation](https://supabase.com/docs)
|
||
|
|
- [Supabase Realtime](https://supabase.com/docs/guides/realtime)
|
||
|
|
- [Row Level Security](https://supabase.com/docs/guides/auth/row-level-security)
|
||
|
|
- [Supabase + Next.js](https://supabase.com/docs/guides/getting-started/quickstarts/nextjs)
|
||
|
|
- [MCP Supabase](https://github.com/modelcontextprotocol/servers)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Validations
|
||
|
|
|
||
|
|
- [x] Compte Supabase créé
|
||
|
|
- [x] MCP Supabase configuré ✅
|
||
|
|
- [x] POC Realtime testé
|
||
|
|
- [x] RLS policies validées
|
||
|
|
- [x] Intégration Next.js OK
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Prochaine révision** : Si limitations découvertes lors du développement
|