SQL vs NoSQL : lequel choisir pour votre projet ?
PostgreSQL ou MongoDB ? Redis ou Cassandra ? La réponse n'est pas une préférence — c'est une question de modèle de données, de patterns d'accès et de garanties de cohérence.
"Utilisez MongoDB pour sa flexibilité." "PostgreSQL est plus sérieux." "Redis pour la vitesse." Ces opinions circulent partout — souvent sans aucun contexte sur le problème qu'elles sont censées résoudre.
SQL et NoSQL ne sont pas une question de goût. Ce sont deux approches fondamentalement différentes de la gestion des données, chacune avec des avantages concrets sur des cas d'usage précis. La vraie question n'est pas "lequel est meilleur" — c'est "lequel correspond à mon modèle de données".
Le modèle relationnel (SQL)
Les bases SQL — PostgreSQL, MySQL, SQLite, SQL Server — organisent les données en tables avec des colonnes typées et des relations explicites entre tables.
-- Schéma explicite, types stricts
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
total NUMERIC(10,2) NOT NULL,
status VARCHAR(20) CHECK (status IN ('pending', 'paid', 'shipped'))
);
-- Jointure — récupérer les commandes avec les infos utilisateur
SELECT u.email, o.total, o.status
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'pending';Le schéma est une contrainte — et une protection. Un email qui ne respecte pas UNIQUE NOT NULL n'entre pas en base. Un user_id qui ne référence pas un utilisateur existant est rejeté. La base garantit l'intégrité des données.
ACID : les quatre garanties SQL
Atomicité — une transaction réussit entièrement ou échoue entièrement. Pas d'état intermédiaire. Un virement bancaire qui débite sans créditer est impossible.
Cohérence — chaque transaction amène la base d'un état valide à un autre état valide. Les contraintes (NOT NULL, UNIQUE, FOREIGN KEY) sont toujours respectées.
Isolation — les transactions concurrentes ne se voient pas mutuellement avant validation. Deux utilisateurs qui modifient la même ligne en même temps ne se corrompent pas.
Durabilité — une fois commitée, une transaction survit même à un crash serveur. Les données sont sur disque.
ACID n'est pas gratuit. Cette sécurité coûte en performance — verrous, journaux de transactions, synchronisation disque. C'est le compromis que les bases SQL font explicitement.
Le monde NoSQL
NoSQL est un terme parapluie pour tout ce qui n'est pas relationnel. Quatre grandes familles, quatre cas d'usage distincts.
Bases document (MongoDB, CouchDB, Firestore)
// Un document MongoDB — pas de schéma fixe
{
"_id": ObjectId("..."),
"email": "william@iducation.fr",
"profile": {
"name": "William",
"avatar": "https://..."
},
"preferences": {
"theme": "dark",
"notifications": ["email", "push"]
},
"tags": ["dev", "devops"],
"created_at": ISODate("2026-06-18")
}Les données d'un utilisateur sont dans un seul document. Pas de jointure nécessaire — tout ce dont vous avez besoin est là. Lecture ultra-rapide pour ce pattern d'accès.
Le revers : si vous devez lister tous les utilisateurs avec theme: "dark", vous scannez tous les documents (sauf index). Et si un utilisateur peut avoir plusieurs adresses, vous les imbriquez dans le document — mais les requêtes sur des données imbriquées sont moins naturelles.
Bases clé-valeur (Redis, DynamoDB, etcd)
# Redis — opérations O(1)
SET session:abc123 '{"userId": 42, "role": "admin"}' EX 3600
GET session:abc123
# Incrémenter un compteur atomiquement
INCR page_views:article:docker-intro
# Ajouter à un ensemble trié
ZADD leaderboard 1500 "william"
ZRANK leaderboard "william"Structure la plus simple : une clé pointe vers une valeur. Pas de requête complexe possible — vous devez connaître la clé. En contrepartie : latence sub-milliseconde, débit massif.
Redis est souvent utilisé en complément d'une base SQL : cache des requêtes lentes, sessions utilisateur, rate limiting, pub/sub, files d'attente. Redis expliqué simplement détaille chacun de ces patterns avec du code concret.
Bases colonne (Cassandra, HBase, ScyllaDB)
Optimisées pour les écritures massives et les requêtes sur des plages temporelles. Cassandra peut ingérer des millions d'événements par seconde sur plusieurs datacenters.
-- CQL (Cassandra Query Language — ressemble à SQL mais fonctionne différemment)
CREATE TABLE events (
device_id UUID,
timestamp TIMESTAMP,
event_type TEXT,
payload MAP<TEXT, TEXT>,
PRIMARY KEY (device_id, timestamp)
) WITH CLUSTERING ORDER BY (timestamp DESC);
-- Requête efficace — lit le partition pour device_id + range timestamp
SELECT * FROM events
WHERE device_id = ? AND timestamp > ? AND timestamp < ?;Le modèle de données doit être conçu autour des requêtes, pas des entités. Cassandra n'a pas de jointures, pas de transactions multi-partitions. Mais pour de la télémétrie IoT, des logs d'événements, des time series à haute vélocité : rien ne tient la comparaison.
Bases graphe (Neo4j, Amazon Neptune)
// Cypher (Neo4j) — relations comme citoyens de première classe
MATCH (william:Person {name: "William"})
-[:FOLLOWS]->(friend:Person)
-[:LIKES]->(article:Article)
WHERE NOT (william)-[:READ]->(article)
RETURN article.title, COUNT(*) AS score
ORDER BY score DESC
LIMIT 10Quand les relations entre données sont le sujet principal, les bases graphe évitent les jointures récursives coûteuses en SQL. Réseaux sociaux, moteurs de recommandation, détection de fraude (trouver des connexions entre comptes suspects), graphes de dépendances.
Théorème CAP : pourquoi vous ne pouvez pas tout avoir
Eric Brewer (2000) : un système distribué ne peut garantir que deux des trois propriétés suivantes simultanément.
Consistency
(tous les nœuds
voient les mêmes données)
/\
/ \
/ \
/ CA \
/--------\
/ CP \
/------AP----\
/______________\
Availability Partition tolerance
(toujours disponible) (résiste aux coupures réseau)CP (Consistency + Partition tolerance) — en cas de coupure réseau, le système refuse les requêtes plutôt que de retourner des données potentiellement obsolètes. HBase, Zookeeper, etcd.
AP (Availability + Partition tolerance) — en cas de coupure, le système continue à répondre mais peut retourner des données temporairement incohérentes. Cassandra, DynamoDB, CouchDB. Eventual consistency : les données convergent vers la cohérence une fois la coupure résolue.
CA (Consistency + Availability) — n'existe pas vraiment en distribué (une coupure réseau est inévitable). Les SGBDR traditionnels sur une seule machine s'approchent de CA.
Ce n'est pas un choix moral — c'est une contrainte physique. Cassandra choisit AP délibérément pour son cas d'usage (données distribuées mondialement). PostgreSQL choisit CA car il tourne typiquement sur un seul nœud ou avec une réplication synchrone.
ACID vs BASE
Les bases NoSQL document et colonne adoptent souvent BASE en contrepartie de la scalabilité :
- Basically Available — le système répond, même partiellement
- Soft state — l'état peut changer même sans input (réplication en cours)
- Eventually consistent — les données convergent vers la cohérence
"Eventual consistency" n'est pas une faiblesse — c'est un choix. Pour un fil d'actualité Twitter, afficher un tweet avec 1 000 likes au lieu de 1 001 pendant 100ms est acceptable. Pour un solde bancaire, ce n'est pas le cas.
Comparaison directe
| Critère | SQL (PostgreSQL) | Document (MongoDB) | Clé-valeur (Redis) | Colonne (Cassandra) |
|---|---|---|---|---|
| Modèle | Tables + relations | Documents JSON | Paires clé/valeur | Colonnes larges |
| Schéma | Strict, migré | Flexible, optionnel | Aucun | Semi-structuré |
| Jointures | Oui, natives | Limitées ($lookup) | Non | Non |
| Transactions | ACID complètes | Depuis 4.0 (limité) | Transactions simples | Non (par partition) |
| Scalabilité | Verticale + réplication | Horizontale (sharding) | Horizontale | Horizontale native |
| Cas d'usage | Données relationnelles, transactionnel | Documents variés, CMS, catalogue | Cache, sessions, compteurs | Time series, événements |
| Maturité | 50 ans | 15 ans | 17 ans | 15 ans |
Quand choisir SQL
Vos données sont relationnelles. Utilisateurs, commandes, produits, paiements — tout s'imbrique et se référence. SQL est conçu pour ça.
Vous avez besoin de transactions ACID. Finance, e-commerce, réservations — une cohérence stricte est non-négociable.
Votre schéma est stable. Si la structure de vos données change rarement, le schéma fixe est un avantage, pas une contrainte.
Vous faites des requêtes ad hoc. SQL permet de poser des questions que vous n'aviez pas anticipées. NoSQL vous force à modéliser en avance les requêtes que vous ferez.
Équipe qui connaît SQL. SQL est un standard de 50 ans. Votre équipe le connaît probablement déjà.
PostgreSQL couvre 95% des besoins des applications web — index, jointures, JSONB (données semi-structurées dans une colonne), transactions, full-text search. Avant de passer à NoSQL, vérifiez que vous avez vraiment atteint une limite de PostgreSQL.
Quand choisir NoSQL
Vos données sont des documents naturels. Un article de blog avec ses métadonnées, ses tags, ses images — tout dans un document MongoDB est plus naturel que 5 tables SQL.
Volume et vélocité extrêmes. 1 million d'événements IoT par seconde : Cassandra ou InfluxDB. Un cache avec 10 millions d'accès/seconde : Redis. PostgreSQL ne fera pas ce travail proprement.
Schéma très variable. Chaque utilisateur a des attributs différents, et ça change souvent. MongoDB permet d'ajouter des champs sans migration.
Scalabilité horizontale native. Cassandra distribue les données sur des dizaines de nœuds sans coordination centrale — impossible à répliquer proprement en SQL sans sharding complexe.
La réalité : souvent les deux
La plupart des applications sérieuses utilisent plusieurs bases de données, chacune pour ce qu'elle fait mieux.
Architecture typique :
PostgreSQL ─── Données transactionnelles (users, orders, payments)
Redis ─── Sessions, cache, rate limiting, file de tâches
Elasticsearch ─ Search full-text sur catalogue produits
InfluxDB ─── Métriques et séries temporelles (monitoring)Ce n'est pas de la sur-ingénierie si chaque couche résout un problème réel. C'en est si vous ajoutez MongoDB "pour la flexibilité" alors que PostgreSQL + JSONB aurait suffi.
Décision rapide
Mes données ont des relations fortes (users ↔ orders ↔ products) ?
→ SQL (PostgreSQL)
J'ai besoin de transactions multi-entités ? (virement, réservation)
→ SQL obligatoire
Mes données sont des documents indépendants avec structure variable ?
→ Document (MongoDB)
J'ai besoin de cache, sessions, compteurs à très haute vitesse ?
→ Redis
J'ingère des événements/métriques à très haute fréquence ?
→ Cassandra, InfluxDB, TimescaleDB
Mes données SONT des relations (réseau social, graphe de dépendances) ?
→ Neo4j, Amazon NeptunePostgreSQL a ajouté JSONB (JSON binaire indexable) précisément parce que la frontière SQL/NoSQL est floue. Vous pouvez stocker des données semi-structurées dans PostgreSQL et les interroger comme du JSON — avec les garanties ACID en prime. C'est souvent le meilleur des deux mondes avant d'avoir un vrai besoin de scalabilité horizontale.
Le choix de base de données est difficile à défaire. Migrer de SQL vers NoSQL (ou l'inverse) sur une application en production est un projet de plusieurs mois. Choisissez bien dès le départ — pas en suivant la hype, mais en modélisant votre domaine.
Pour une API REST ou GraphQL, le choix de base de données influence directement la forme de vos endpoints et la complexité de vos resolvers — c'est une décision architecturale, pas juste technique.