2026-08-16
· Dylan YuSQLite vs PostgreSQL : comment choisir la bonne base de données pour votre prochain projet
SQLite et PostgreSQL résolvent des problèmes différents, mais la plupart des conseils en ligne présentent l'un comme universellement meilleur. Voici un cadre de décision pratique basé sur ce que tu construis vraiment — concurrence, échelle, déploiement, et quand tu pourrais avoir besoin des deux.
Voici une question que j'ai vue mal répondue plus de fois que je ne peux compter : "Est-ce que je devrais utiliser SQLite ou PostgreSQL ?"
La réponse typique, c'est une variante de "SQLite c'est pour les prototypes, PostgreSQL c'est pour la production." C'est pas seulement simpliste — c'est carrément trompeur. Ça pousse les gens à monter un serveur Postgres pour un outil CLI mono-utilisateur (overkill), ou à livrer SQLite comme base de données principale pour un SaaS multi-writers (un problème en attente d'arriver).
La réponse honnête, c'est qu'ils sont optimisés pour des choses fondamentalement différentes, et le bon choix dépend des spécificités de ta charge de travail — des choses que la plupart des articles de comparaison ne demandent jamais. Allons-y.
La différence fondamentale (que la plupart des comparaisons zappent)
SQLite est une bibliothèque. Tu la lies dans ton processus applicatif, et elle lit et écrit un fichier sur disque. Pas de serveur, pas de réseau, pas de handshake d'authentification. Ton app et ta base de données vivent dans le même processus.
PostgreSQL est un serveur. Il tourne comme un daemon séparé, gère sa propre mémoire et son pool de connexions, et accepte des requêtes via un protocole réseau. Ton application s'y connecte en tant que client.
Cette seule différence d'architecture explique presque toutes les autres différences que les gens débattent :
- Concurrence — Postgres gère des centaines de connexions simultanées avec MVCC. SQLite sérialise les écritures via un verrou global unique (même en mode WAL).
- Déploiement — SQLite, c'est
npm install better-sqlite3et c'est réglé. Postgres, c'est un serveur que tu dois faire tourner, surveiller, sauvegarder et garder en vie. - Échelle — Postgres est conçu pour des téraoctets sur plusieurs disques. SQLite est conçu pour des gigaoctets sur une seule machine.
- Latence — Les requêtes SQLite prennent des microsecondes, parce qu'il n'y a pas d'aller-retour réseau. Les requêtes Postgres prennent des millisecondes, parce qu'il y a toujours un saut réseau (même en localhost).
Aucune de ces différences ne rend l'un "meilleur." Elles rendent l'un approprié à une charge de travail spécifique.
Quand SQLite est le bon choix
1. Les applications mono-processus
Si ton app tourne en un seul processus — un outil CLI, une app desktop, une app mobile, un gestionnaire de webhook sur un seul serveur — SQLite est presque toujours le bon défaut. Il n'y a aucun avantage à avoir un serveur de base de données séparé quand il n'y a qu'un seul client.
Les cas où je prends SQLite sans réfléchir :
- Une app desktop qui a besoin de stockage local (BaseVolt lui-même utilise SQLite pour sa config)
- Un outil CLI qui garde un état entre deux exécutions
- Une app mobile (SQLite est déjà embarqué dans iOS et Android)
- Un prototype ou MVP où tu ne connais pas encore ton schéma
- Un dashboard d'analytics à forte lecture basé sur un fichier
.dbpré-calculé
2. Les charges embarquées et edge
La propriété "pas de serveur" de SQLite devient un superpouvoir à l'edge. Cloudflare D1, c'est littéralement SQLite qui tourne sur le réseau edge de Cloudflare. Turso et libSQL sont des forks de SQLite optimisés pour les lectures distribuées. Si tu construis quelque chose qui tourne près des utilisateurs — un worker sur un CDN edge, un device IoT, un système embarqué — SQLite est la seule option sensée. Postgres ne tourne pas sur un Raspberry Pi Zero de façon que tu aies envie de maintenir.
3. Les charges à forte lecture avec peu de contention en écriture
Voici un fait qui surprend les gens : SQLite en mode WAL peut gérer des milliers de lecteurs simultanés sans contention. Les lecteurs ne bloquent pas les writers, et les writers ne bloquent pas les lecteurs. La limitation, c'est spécifiquement les écritures simultanées — un seul writer à la fois.
Si ta charge de travail est à 99 % de lecture (un CMS, un catalogue de produits, un store de config, un dashboard d'analytics sur des données pré-calculées), SQLite ira plus loin que tu ne le penses. Le mème "SQLite ne passe pas à l'échelle" concerne surtout les apps multi-utilisateurs à forte écriture, pas celles à forte lecture.
4. Quand tu ne veux pas opérer une base de données
Ça, c'est sous-estimé. Faire tourner Postgres en production, ça veut dire :
- Configurer le connection pooling (PgBouncer ou le pooler intégré)
- Configurer
shared_buffers,work_mem,max_connections,wal_level - Mettre en place des sauvegardes automatisées et tester les restores
- Surveiller le lag de réplication, le vacuum bloat, la contention de verrous
- Upgrader les versions majeures avec
pg_upgradeou la réplication logique
Si tu es un développeur solo ou une petite équipe sans DBA dédié, chacun de ces points est une chose qui peut casser à 3h du matin. SQLite n'a aucun de ces problèmes. La sauvegarde, c'est littéralement cp database.db database.db.bak.
Quand PostgreSQL est le bon choix
1. Les charges multi-processus ou multi-serveurs
Au moment où tu as deux serveurs applicatifs qui doivent lire et écrire les mêmes données, SQLite est hors jeu. Tu peux mettre un fichier SQLite sur un partage réseau, mais tu ne devrais pas — le verrouillage de fichiers sur NFS/SMB est un piège qui finira par corrompre ta base de données.
Postgres est conçu exactement pour ça. Plusieurs serveurs applicatifs se connectent à une seule instance Postgres, et Postgres gère la concurrence correctement. Si tu fais tourner plus d'un réplica de ton application, il te faut une base de données côté serveur.
2. Les charges à forte concurrence d'écriture
Si tu as des dizaines de writers simultanés — un SaaS avec des utilisateurs actifs, un pipeline de logs, une ingestion d'analytics en temps réel — le verrou de writer unique de SQLite devient le goulot d'étranglement. Même en mode WAL, les writers font la queue. Postgres gère ça avec MVCC : plusieurs writers peuvent modifier des lignes différentes simultanément, et les conflits sont résolus au commit.
Règle de base : si "des écritures simultanées depuis des processus différents" est une caractéristique centrale de ta charge de travail, il te faut Postgres (ou MySQL, ou un autre SGBD côté serveur).
3. Les fonctionnalités SQL avancées dont tu as vraiment besoin
Postgres a des fonctionnalités que SQLite n'a pas, et certaines comptent :
- Window functions — SQLite les a maintenant, mais l'implémentation de Postgres est plus complète
- Vues matérialisées — Postgres les a nativement ; SQLite non
- Recherche plein texte — les deux ont FTS, mais
tsvector/tsqueryde Postgres est plus puissant - JSON/JSONB — les deux supportent JSON, mais JSONB de Postgres avec les index GIN est dans une autre ligue
- PostGIS — si tu as besoin de requêtes géospatiales, PostGIS est le standard de l'industrie
- Réplication logique, partitionnement, LISTEN/NOTIFY — des fonctionnalités côté serveur sans équivalent SQLite
L'expression clé ci-dessus, c'est "dont tu as vraiment besoin." La plupart des apps n'utilisent pas la plupart de ça. Mais si tu construis une application géospatiale, ou que tu as besoin de push en temps réel via LISTEN/NOTIFY, ou que tu requêtes du JSON imbriqué à grande échelle, Postgres est la réponse.
4. L'intégrité stricte des données au niveau de la base
SQLite est célèbre pour sa permissivité par défaut. Il utilise le typage dynamique — tu peux insérer une chaîne dans une colonne d'entiers et SQLite la stockera sans broncher. L'application des clés étrangères est désactivée par défaut (tu dois faire PRAGMA foreign_keys = ON à chaque connexion). Postgres est strict par défaut : les incompatibilités de type lèvent des erreurs, les clés étrangères sont appliquées, les contraintes ne sont pas négociables.
Si tu travailles en équipe et que tu veux que la base de données applique l'intégrité plutôt que de te reposer sur le code applicatif, la rigueur de Postgres est une fonctionnalité, pas un bug.
Le tableau de comparaison (avec des compromis honnêtes)
| Dimension | SQLite | PostgreSQL |
|---|---|---|
| Architecture | Bibliothèque embarquée | Client-serveur |
| Temps de configuration | Secondes (un fichier) | Minutes à heures (config serveur) |
| Lecteurs simultanés | Milliers (mode WAL) | Milliers |
| Writers simultanés | 1 (sérialisé) | Centaines (MVCC) |
| Taille max pratique | ~1To par fichier | Téraoctets+ |
| Latence réseau | Aucune (en processus) | 0,1-2ms même en localhost |
| Sauvegarde | Copier le fichier | pg_dump / archivage WAL / snapshots |
| Charge opérationnelle | Quasi nulle | Significative |
| Coût | Gratuit | Gratuit (auto-hébergé) ou $$ (managé) |
| Typage strict | Optionnel (dynamique par défaut) | Appliqué |
| Support JSON | Extension JSON1 | JSONB avec indexation GIN |
| Recherche plein texte | FTS5 | tsvector avec ranking |
| Géospatial | Limité | PostGIS (meilleur de sa catégorie) |
| Réplication | Pas intégrée (litestream etc.) | Streaming intégré + logique |
| Idéal pour | Mono-processus, edge, forte lecture | Multi-serveurs, forte écriture, complexe |
Un cadre de décision pratique
Au lieu d'un organigramme que tu vas zapper, voici les quatre questions qui déterminent vraiment la réponse.
1. Combien de processus vont écrire dans cette base de données en même temps ?
- Un → SQLite suffit
- Plus d'un → Postgres
2. La base de données va-t-elle vivre sur plus d'une machine ?
- Non, une seule machine → SQLite suffit
- Oui, plusieurs serveurs / répliques → Postgres
3. As-tu besoin de fonctionnalités avancées exclusives à Postgres (PostGIS, vues matérialisées, JSONB à grande échelle, réplication logique) ?
- Non → SQLite suffit
- Oui → Postgres
4. La capacité de ton équipe à opérer un serveur de base de données est-elle une contrainte ?
- Oui, on n'a pas de DBA ni de temps → SQLite (ou Postgres managé)
- Non, on peut faire tourner Postgres → Postgres
Si tu as répondu "SQLite suffit" à trois questions ou plus, utilise SQLite. Si tu as répondu "Postgres" à deux questions ou plus, utilise Postgres. Les cas limites sont plus rares qu'internet ne le laisse penser.
La réalité : beaucoup d'équipes utilisent les deux
Voici ce que personne ne te dit : le choix n'est pas toujours soit l'un soit l'autre.
Un pattern de production que j'ai vu dans les équipes bien gérées :
- PostgreSQL comme base de données opérationnelle principale (multi-serveurs, forte écriture, la source de vérité)
- SQLite comme cache local, réplique edge ou snapshot d'analytics sur des machines individuelles
Cloudflare D1 (SQLite à l'edge) couplé à un Postgres primaire est une architecture légitime pour des apps distribuées globalement. Turso + Postgres, c'est la même idée. Tu écris dans Postgres, tu répliques vers des instances SQLite proches des utilisateurs, et tu lis localement à latence zéro.
La friction dans cette configuration, ce ne sont pas les bases de données — c'est le tooling. La plupart des panneaux d'administration sont conçus pour l'un ou l'autre. Tu finis avec DBeaver pour Postgres et DB Browser pour SQLite, avec des workflows complètement différents pour chacun.
C'est en partie pour ça qu'on a construit BaseVolt pour gérer les deux. Pointe-le vers un fichier .db pour SQLite, ou donne-lui une connection string Postgres, et tu obtiens la même interface d'administration — vues grille, kanban boards, dashboards, configuration de relations — quelle que soit la base à laquelle tu es connecté. Pour les équipes qui font tourner les deux, ça veut dire un outil au lieu de deux. (Il y a une démo live sur demo.basevolt.app si tu veux voir ça avant d'installer.)
Les erreurs courantes que j'ai vues
Utiliser SQLite pour un SaaS multi-writers parce que "c'est plus simple." C'est plus simple — jusqu'à ce que ton deuxième utilisateur écrive en même temps que le premier et que tu te prennes SQLITE_BUSY. J'ai vu ça en production. Utilise Postgres.
Monter un Postgres pour un outil CLI mono-utilisateur. Tu as maintenant un serveur de base de données à sauvegarder, surveiller et upgrader, pour une app utilisée par une seule personne. Utilise SQLite.
Écarter SQLite parce que "ça ne passe pas à l'échelle." Ça passe à l'échelle jusqu'à des centaines de Go et des milliers de lecteurs simultanés. Ce que ça ne fait pas, c'est les écritures simultanées depuis plusieurs processus. Si ce n'est pas ta charge de travail, SQLite va plus loin que tu ne le penses.
Considérer les valeurs par défaut de Postgres comme prêtes pour la production. Elles ne le sont pas. max_connections = 100 sans pooling va casser sous n'importe quelle charge réelle. Si tu fais tourner Postgres, renseigne-toi sur PgBouncer, shared_buffers et wal_compression — ou utilise un service managé (Neon, Supabase, RDS) qui gère ça pour toi.
En résumé
SQLite et PostgreSQL ne sont pas concurrents. Ce sont des outils pour des tâches différentes.
- SQLite quand la base de données et l'app vivent ensemble : apps desktop, apps mobiles, fonctions edge, outils CLI, charges mono-serveur à forte lecture, prototypes.
- PostgreSQL quand la base de données sert plusieurs clients : web apps avec plusieurs serveurs, charges à forte concurrence d'écriture, apps qui ont besoin de fonctionnalités SQL avancées, tout ce où l'intégrité stricte au niveau de la base compte.
Le mauvais choix, c'est de décider en fonction de ce qui est "plus puissant." Choisis en fonction de ce que ta charge de travail fait réellement. La plupart des apps n'ont pas besoin d'un serveur de base de données. Certaines apps ne peuvent pas fonctionner sans. Savoir lesquelles, c'est ça la vraie compétence.
Si tu travailles avec l'un (ou les deux), BaseVolt te donne un panneau d'administration local-first pour SQLite et PostgreSQL sans envoyer tes données nulle part. Pas de compte, pas de cloud, fonctionne hors ligne.
Tu construis quelque chose avec SQLite ou Postgres ? Je suis curieux de savoir sur quoi tu travailles — retrouvez-moi sur X.