Aller au contenu
Data Engineering

De Firebase à PostgreSQL : Comment nous avons réduit nos coûts cloud de 80%

Retour d'expérience sur une migration complexe de Firebase vers PostgreSQL qui a transformé notre architecture data et réduit notre facture cloud de 80%.

30 mars 2026
9 min
Detailed image of a server rack with glowing lights in a modern data center.

L'email du contrôleur de gestion est arrivé un lundi matin. Objet : "Alerte facture Firebase". Le montant dépassait les 12 000 euros pour le mois précédent. Pour une application qui comptait certes plusieurs milliers d'utilisateurs actifs, mais qui restait loin des volumes d'un géant du web, quelque chose clochait. En creusant les logs de facturation, le constat était sans appel : les lectures Firestore explosaient, les fonctions Cloud tournaient en boucle sur des requêtes inefficaces, et chaque nouvelle feature aggravait la situation.

Cette alerte a marqué le début d'une migration de six mois pour migrer de Firebase vers PostgreSQL, hébergé sur Supabase. Aujourd'hui, notre facture mensuelle tourne autour de 2 400 euros, pour des performances sensiblement meilleures et une architecture qui nous donne enfin le contrôle. Cette économie de 80% n'est pas tombée du ciel. Elle est le fruit d'une planification minutieuse, de choix techniques assumés et de quelques erreurs qu'on aurait préféré éviter. Réduire les coûts infrastructure sans compromettre la qualité reste l'un des défis majeurs des équipes tech.

Pourquoi Firebase finit par coûter cher

Firebase séduit au démarrage. On lance un MVP en quelques jours, les SDK sont bien pensés, la synchronisation temps réel fonctionne d'emblée. Le problème survient quand l'application grandit et que les patterns d'utilisation se complexifient. Firestore facture au nombre de lectures et d'écritures. Une requête qui ramène 100 documents compte pour 100 lectures. Si on rafraîchit une liste toutes les minutes pour 500 utilisateurs simultanés, on explose rapidement les quotas gratuits.

Dans notre cas, trois anti-patterns creusaient la facture. D'abord, les listeners temps réel mal configurés. Beaucoup de composants React écoutaient des collections entières alors qu'ils n'affichaient que quelques éléments. Ensuite, l'absence d'agrégation côté serveur. Firestore ne propose pas de GROUP BY ni de SUM natifs, ce qui nous forçait à charger des milliers de documents côté client pour calculer des totaux. Enfin, les index secondaires mal maîtrisés généraient des lectures en cascade pour des requêtes pourtant simples.

On a tenté d'optimiser. On a refactorisé les listeners, mis en cache certaines données, réduit la fréquence des rafraîchissements. Résultat : on est passés de 12 000 à 9 000 euros par mois. Insuffisant. Le vrai problème n'était pas technique mais structurel. Firestore est conçu pour des cas d'usage précis. Dès qu'on sort du cadre, on paie le prix fort. PostgreSQL, lui, offre une flexibilité qui correspondait mieux à notre trajectoire produit et constituait une Firebase alternative crédible.

Planifier une migration database sans couper le robinet

Migrer une base de données en production relève de l'exercice d'équilibriste. On ne peut pas se permettre de downtime prolongé, ni de perdre des données, ni de casser les features existantes. La première étape consistait à cartographier précisément ce qu'on migrait. On a audité l'ensemble des collections Firestore, identifié les volumes, les patterns de lecture-écriture, les dépendances entre entités. Cet audit a révélé des surprises : certaines collections stockaient des données obsolètes depuis des mois, d'autres contenaient des doublons masqués par l'absence de contraintes d'unicité.

On a opté pour une stratégie de migration progressive en trois phases. Phase un : duplication des écritures. On a commencé par les entités les moins critiques, comme les logs d'audit et les préférences utilisateur. Chaque nouvelle écriture allait simultanément dans Firestore et PostgreSQL. Cette double écriture permettait de tester le schéma relationnel en conditions réelles sans risque. Phase deux : basculement des lectures par feature. Une fois la duplication stabilisée pendant deux semaines, on a migré les lectures feature par feature, en commençant par celles qui généraient le moins de trafic. Un feature flag permettait de revenir en arrière en quelques secondes en cas de problème.

Phase trois : migration des données historiques et décommissionnement. Cette étape s'est révélée la plus chronophage. On a écrit des scripts de migration qui transformaient les documents Firestore en lignes PostgreSQL, en reconstruisant au passage les relations entre entités. Firestore stocke tout en JSON imbriqué. PostgreSQL attend des tables normalisées avec des foreign keys. La transformation nécessitait de prendre des décisions sur la structure finale : dénormaliser certaines données pour la performance, normaliser d'autres pour la cohérence. On a passé trois semaines à affiner ces scripts avant de lancer la migration complète sur un week-end à faible trafic.

Les pièges qui nous ont ralentis

Le premier piège, on l'a découvert dès la phase de duplication. Firestore est schemaless, PostgreSQL exige des types stricts. Plusieurs collections contenaient des champs dont le type variait d'un document à l'autre. Un champ "amount" stockait tantôt un number, tantôt une string, parfois null, parfois absent. Il a fallu nettoyer ces incohérences manuellement avant toute migration. On a écrit des scripts de validation qui parcouraient les collections pour identifier ces cas limites. Résultat : 8% de nos documents nécessitaient une intervention manuelle.

Deuxième piège : la gestion des transactions. Firestore propose des transactions, mais leur portée est limitée. On utilisait beaucoup de batch writes pour contourner ces limites, ce qui créait des états intermédiaires incohérents en cas d'erreur. PostgreSQL permet des transactions ACID robustes, mais encore faut-il les implémenter correctement. On a sous-estimé le travail de refactoring côté application. Certaines opérations métier nécessitaient désormais des BEGIN/COMMIT explicites, avec une gestion fine des rollbacks. On a passé deux sprints à revoir la logique transactionnelle de notre codebase.

Troisième piège : les performances PostgreSQL production. On s'attendait à ce que PostgreSQL soit plus rapide. C'était vrai pour les agrégations et les jointures complexes, moins évident pour les lectures simples. Firestore indexe automatiquement tous les champs. PostgreSQL demande de créer les index manuellement. Au début, certaines requêtes prenaient 3 secondes au lieu de 300ms. L'analyse EXPLAIN ANALYZE est devenue notre meilleure amie. On a identifié les scans séquentiels coûteux, créé les index manquants, ajusté certains schémas pour éviter les jointures inutiles. Aujourd'hui, les performances dépassent largement celles de Firestore, mais ça n'a pas été immédiat.

Dernier piège, souvent négligé : la courbe d'apprentissage. Notre équipe maîtrisait bien Firestore et ses SDK. PostgreSQL nécessitait de réapprendre les bonnes pratiques SQL, de comprendre les subtilités du query planner, de gérer les migrations de schéma avec des outils comme Prisma ou TypeORM. On a investi dans de la formation, organisé des sessions de pair programming pour monter en compétence collectivement. Cette friction humaine ralentit toute migration technique, il faut l'anticiper dans le planning.

Ce que la migration a changé au-delà du budget

L'économie de 80% était l'objectif initial. Elle s'est concrétisée, mais les bénéfices collatéraux ont dépassé nos attentes. D'abord, on a retrouvé du contrôle sur nos données. PostgreSQL permet d'exécuter des requêtes analytiques complexes directement en base, sans charger des milliers de documents côté client. On a pu supprimer plusieurs microservices de calcul qui tournaient en permanence pour compenser les limitations de Firestore. Résultat : une architecture simplifiée, plus facile à maintenir.

Ensuite, la qualité des données s'est nettement améliorée. Les contraintes PostgreSQL (foreign keys, unique constraints, check constraints) ont forcé l'équipe à formaliser le modèle de données. Fini les champs incohérents ou les références cassées. Les migrations de schéma, bien que plus contraignantes, garantissent désormais que la structure évolue de manière contrôlée et documentée. On a moins de bugs liés à des données mal formées. Cette rigueur dans la modélisation des données rejoint les principes qu'on applique pour garantir une source de vérité unique dans nos projets data.

Côté développement, la productivité a d'abord baissé pendant la transition, puis fortement augmenté. Les développeurs passent moins de temps à contourner les limites de Firestore. Les requêtes SQL sont plus expressives que les query builders Firestore. On a pu implémenter des features qui auraient été cauchemardesque avec Firestore : rapports avec agrégations complexes, recherche full-text performante via des extensions PostgreSQL, gestion de permissions granulaires avec Row-Level Security sur Supabase.

Enfin, la migration a révélé des problèmes de conception qu'on ignorait. Certaines collections Firestore servaient de cache mémoire déguisé. D'autres mélangeaient données transactionnelles et données analytiques. En redessinant le schéma relationnel, on a été forcés de clarifier la responsabilité de chaque table, de séparer proprement les contextes métier. Cette remise à plat a posé des bases plus saines pour les évolutions futures.

Recommandations pour réussir votre migration

Si on devait recommencer, on changerait plusieurs choses. D'abord, on commencerait la migration plus tôt. On a attendu que la douleur devienne insupportable. Résultat : on a migré dans l'urgence, avec une pression budgétaire qui limitait nos marges de manœuvre. L'idéal aurait été d'anticiper dès que les patterns Firestore montraient leurs limites, avant que la dette technique ne s'accumule. Mesurer le ROI des projets tech permet justement d'anticiper ce type de décisions stratégiques.

Ensuite, on investirait davantage dans l'observabilité dès le départ. On a ajouté des métriques détaillées en cours de route, pour suivre les taux d'erreur, les latences, les incohérences entre les deux bases. Cet outillage aurait dû être prêt avant la première ligne de code de migration. Sans visibilité fine, on navigue à l'aveugle.

On accorderait aussi plus de temps au nettoyage préalable des données. Tenter de migrer des données sales vers un schéma strict est une source inépuisable de complications. Mieux vaut prendre deux semaines pour auditer et nettoyer que de passer deux mois à corriger des scripts de migration qui échouent sur des edge cases imprévus.

Côté technique, l'utilisation d'un ORM moderne (on a choisi Prisma) a été déterminante. Il gère les migrations de schéma de manière versionnée, génère du code typesafe, facilite le travail en équipe. Coupler PostgreSQL avec Supabase nous a donné accès à une stack complète (auth, storage, realtime) qui compensait les fonctionnalités Firebase qu'on abandonnait. Cette cohérence d'écosystème a simplifié la transition.

Enfin, on communiquerait mieux avec le métier. La migration a impacté le roadmap produit pendant six mois. Certaines features ont été repoussées, d'autres simplifiées pour faciliter la transition. Embarquer les product managers dans la décision, leur montrer les bénéfices à moyen terme, ça évite les frustrations et les arbitrages précipités.

Firebase reste une excellente solution pour prototyper rapidement ou pour des applications avec des patterns simples et prévisibles. Mais quand la complexité augmente, quand les volumes grimpent, quand on a besoin de contrôle fin sur les coûts et l'architecture, PostgreSQL reprend l'avantage. Cette migration nous a coûté six mois d'efforts et beaucoup d'apprentissage. Elle nous a aussi libérés d'une trajectoire budgétaire insoutenable et redonné la maîtrise de notre stack data. Chaque contexte est unique, mais si votre facture Firebase vous fait grimacer tous les mois, peut-être est-il temps d'explorer sérieusement les alternatives relationnelles.

Questions fréquentes

Pourquoi migrer de Firebase vers PostgreSQL pour réduire les coûts cloud ?

Firebase applique un modèle tarifaire à l'usage (pay-as-you-go) qui devient très coûteux à grande échelle, tandis que PostgreSQL offre un coût prévisible et maîtrisé. En migrant vers une base de données relationnelle auto-hébergée ou gérée, vous éliminez les frais d'infrastructure propriétaire Firebase et bénéficiez d'économies d'échelle significatives, généralement de 70 à 80% pour les charges élevées.

Quels sont les défis principaux lors d'une migration Firebase vers PostgreSQL ?

Les défis incluent la restructuration des données (Firebase utilise des documents NoSQL tandis que PostgreSQL est relationnel), la migration de la logique métier et des indices, ainsi que la gestion de la downtime applicative. Il faut également former l'équipe aux concepts SQL et gérer les différences architecturales comme l'absence de transactions distribuées natives dans Firebase.

Combien de temps faut-il pour migrer une application Firebase vers PostgreSQL ?

La durée dépend de la complexité de votre architecture, du volume de données et de la taille de l'équipe. Une migration d'envergure moyenne peut prendre 2 à 6 mois, incluant la préparation, la migration des données, les tests et l'optimisation des performances. Les petits projets peuvent être migrés en quelques semaines, tandis que les systèmes complexes nécessitent plusieurs mois de planification.

Quels outils utiliser pour migrer les données de Firebase vers PostgreSQL ?

Les outils courants incluent Firestore Export/Import pour exporter les données Firebase au format JSON, puis des outils comme pgAdmin, DBeaver ou des scripts Python personnalisés pour charger les données dans PostgreSQL. Vous pouvez aussi utiliser des services de migration managés comme AWS Database Migration Service si vos données transient par AWS.

Comment garantir la continuité de service lors d'une migration Firebase vers PostgreSQL ?

Implémentez une stratégie de migration progressive en mode dual-write (écriture simultanée dans Firebase et PostgreSQL), testez rigoureusement en environnement de staging, et planifiez une fenêtre de basculement pendant les heures creuses. Versionnez votre code pour faciliter les rollbacks rapides en cas de problème, et maintenez la synchronisation des données jusqu'à la bascule complète.

Vous avez un projet data ?

Nous serions ravis de discuter de vos besoins en visualisation et analytics.

Nous contacter