Firebase Realtime Database est une base de données JSON cloud en temps réel lancée par Google en 2012 pour les applications mobiles et web. Toutes les données sont stockées dans un seul grand arbre JSON et synchronisées entre les clients connectés en temps réel via une connexion WebSocket. Selon la documentation officielle Firebase, 2025, Realtime Database peut gérer jusqu'à 200 000 connexions simultanées et prend en charge jusqu'à 1 000 écritures simultanées par seconde. La base de données ne nécessite pas d'infrastructure serveur et fournit des SDK pour iOS, Android, Web et les plates-formes serveur.
Points clés
Firebase Realtime Database est une base de données NoSQL cloud qui stocke et synchronise les données en temps réel entre tous les clients connectés. Lancée en 2012 sous le nom Firebase (avant le rachat par Google), elle est devenue la première base de données cloud en temps réel pour les développeurs mobiles. Les données sont représentées au format JSON et organisées dans un arbre hiérarchique, où chaque nœud a un chemin unique.
La valeur principale de Realtime Database est la synchronisation intégrée. Lorsqu'une application modifie des données sur un appareil, tous les autres clients connectés reçoivent instantanément la mise à jour via une connexion persistante. Cela élimine la nécessité pour le développeur d'implémenter son propre mécanisme de synchronisation, serveur WebSocket ou API REST pour le transfert de données entre clients.
La base de données fournit des SDK pour toutes les principales plates-formes : Android (Java, Kotlin), iOS (Swift, Objective-C), Web (JavaScript) et environnements serveur via Admin SDK. Selon Google, Realtime Database est utilisé dans plus de 1,5 million de projets Firebase actifs dans le monde. Malgré l'arrivée de Firestore plus moderne, Realtime Database reste un choix populaire pour les projets avec des structures de données simples.
Contrairement aux bases de données relationnelles, Realtime Database n'utilise ni tables ni lignes. Toutes les données sont un seul arbre JSON qui ressemble à des objets JavaScript imbriqués. Par exemple, pour stocker des utilisateurs et leurs messages, une hiérarchie est créée : users/userId/name et messages/messageId/text. Chaque chemin dans l'arbre est une chaîne, et les données sont accessibles directement par ce chemin.
{
"users": {
"user1": {
"name": "Ivan Petrov",
"email": "ivan@example.com"
},
"user2": {
"name": "Maria Sokolova",
"email": "maria@example.com"
}
},
"messages": {
"-Nabc123": {
"text": "Bonjour !",
"userId": "user1"
}
}
}
Une caractéristique importante est que l'imbrication profonde affecte les performances. Lorsqu'une application lit des données à un certain chemin, elle charge tous les nœuds enfants de ce chemin. Il est donc recommandé de concevoir la structure de données la plus plate possible, en évitant les imbrications de plus de 3 à 4 niveaux. Pour contourner ce problème, la dénormalisation des données est utilisée — la duplication d'informations dans différents nœuds de l'arbre.
Realtime Database et Firestore sont souvent comparés comme deux bases de données cloud en temps réel de Google. Le choix entre elles dépend des exigences spécifiques du projet : complexité des requêtes, cohérence requise et charge attendue. Comprendre les forces de chaque base de données aide à prendre la bonne décision architecturale.
Le principal avantage de Realtime Database est la faible latence de synchronisation. Comme toutes les données sont stockées dans un seul arbre JSON sans couches d'abstraction supplémentaires, la synchronisation est plus rapide que dans Firestore. Pour les applications où la vitesse de livraison des mises à jour est critique (chats, jeux en ligne, systèmes d'édition collaborative), Realtime Database peut être le choix le plus approprié.
Realtime Database est mieux adapté aux scénarios avec des structures de données simples et une fréquence de mise à jour élevée. Exemples typiques : chats, likes en temps réel, indicateurs de frappe, statuts de présence des utilisateurs. C'est également un bon choix pour les prototypes et les projets à budget limité, car la tarification est basée sur le volume de données, pas sur le nombre d'opérations.
D'autre part, pour les applications avec des requêtes complexes (filtrage par plusieurs champs, tri, agrégation), Firestore offre des capacités beaucoup plus puissantes. Realtime Database ne prend en charge que le filtrage par un paramètre et ne peut pas trier les résultats sur plusieurs champs simultanément. Si un projet prévoit des analyses de données complexes côté client, Firestore sera un choix plus pratique.
Realtime Database utilise une connexion WebSocket persistante pour la synchronisation bidirectionnelle des données. Lorsqu'un client appelle setValue ou updateChildren sur un chemin spécifique, les données sont envoyées au serveur Firebase via le canal ouvert. Le serveur applique les modifications et distribue les mises à jour à tous les clients abonnés en quelques millisecondes. Chaque connexion est identifiée par une clé de session unique.
Le mécanisme d'abonnement fonctionne via des listeners. Un développeur peut s'abonner aux modifications d'un nœud spécifique (addListenerForSingleValueEvent) ou recevoir des mises à jour continues (addValueEventListener). Chaque fois que les données changent, le callback onDataChange est déclenché avec un instantané complet des données au chemin spécifié. Cela diffère de Firestore, où seuls les documents modifiés sont reçus — dans Realtime Database, toutes les données du nœud sont toujours chargées.
Realtime Database prend en charge le mode hors ligne sur Android et iOS via le cache disque. Le SDK conserve une copie locale des données et continue de traiter les opérations d'écriture en l'absence de réseau. Lorsque la connexion est rétablie, toutes les modifications accumulées sont envoyées au serveur. La stratégie de la dernière écriture gagnante (last-write-wins) est utilisée pour la résolution des conflits, mais les développeurs peuvent implémenter une logique personnalisée via ServerValue.TIMESTAMP pour la résolution de collisions.
val database = FirebaseDatabase.getInstance()
val myRef = database.getReference("messages")
// Écriture de données
myRef.push().setValue(
hashMapOf(
"text" to "Nouveau message",
"timestamp" to ServerValue.TIMESTAMP
)
)
// Lecture avec mises à jour continues
myRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val data = snapshot.getValue()
Log.d("TAG", "Données : $data")
}
override fun onCancelled(error: DatabaseError) {
Log.w("TAG", "Erreur : ${error.message}")
}
})
Pour optimiser le trafic et les performances, il est recommandé d'utiliser des child listeners plutôt que des value listeners pour suivre les modifications de nœuds enfants spécifiques. ChildEventListener fournit des callbacks séparés pour l'ajout, la modification, la suppression et le déplacement d'éléments enfants, permettant un contrôle plus précis des mises à jour de l'interface et évitant de redessiner tous les éléments de la liste à chaque modification de données.
Realtime Database utilise un langage de règles déclaratif pour le contrôle d'accès aux données. Les règles décrivent qui peut lire et écrire des données à chaque chemin de l'arbre JSON. Elles sont vérifiées sur le serveur Firebase avant chaque requête et ne nécessitent pas de logique serveur pour l'autorisation. Les règles prennent en charge les variables, les objets intégrés et les fonctions pour une configuration d'accès flexible.
Par défaut, l'accès à la base de données est refusé pour tous les utilisateurs. Le développeur ouvre progressivement l'accès en utilisant les règles ".read" et ".write" à différents niveaux de l'arbre. Les conditions peuvent vérifier l'authentification via la variable auth, le type de requête (lecture/écriture) et les données existantes via l'objet data. De plus, les règles prennent en charge la validation des données écrites via l'objet newData.
{
"rules": {
"users": {
"$uid": {
// Seul le propriétaire peut lire ses données
".read": "$uid === auth.uid",
// Seul le propriétaire peut écrire
".write": "$uid === auth.uid",
// Validation des champs lors de l'écriture
".validate": "newData.hasChildren(['name', 'email'])"
}
},
"messages": {
// Tout utilisateur authentifié peut lire
".read": "auth !== null",
// Seul l'utilisateur authentifié peut écrire
".write": "auth !== null",
".indexOn": ["timestamp"]
}
}
}
Les règles prennent également en charge l'indexation des données via la directive ".indexOn". Sans celle-ci, les requêtes avec tri (orderByChild) seront rejetées ou exécutées de manière inefficace. Les index sont spécifiés pour chaque chemin où un tri par un champ spécifique est effectué. Les règles sont en cascade : les règles plus profondes remplacent les règles parentes, et si l'accès n'est pas défini à un certain niveau, il est considéré comme autorisé ou refusé selon la règle parente.
Realtime Database prend en charge cinq types de données : String, Number, Boolean, Map (objet) et List (tableau). La profondeur d'imbrication est limitée à 32 niveaux, et la taille maximale d'un seul nœud ne doit pas dépasser 256 Mo. Pour un travail efficace avec la base de données, il est recommandé de concevoir une structure de données plate et d'utiliser la dénormalisation pour éviter les requêtes profondes qui chargent de grandes quantités de données.
Considérons un exemple pratique d'intégration de Realtime Database dans une application Android pour les statuts d'utilisateurs (en ligne/hors ligne). L'application affichera une liste d'utilisateurs avec leur statut actuel, mis à jour en temps réel. Pour la démonstration, Firebase Authentication est utilisé pour l'identification des utilisateurs et les coroutines pour les opérations asynchrones.
Pour commencer, ajoutez la dépendance firebase-database-ktx au fichier build.gradle du module de l'application. La version de la bibliothèque est gérée via Firebase BoM pour garantir la compatibilité de tous les composants. Après avoir ajouté la dépendance, Firebase doit être initialisé dans la classe Application ou via une initialisation paresseuse dans le ViewModel.
dependencies {
implementation platform("com.google.firebase:firebase-bom:33.0.0")
implementation "com.google.firebase:firebase-database-ktx"
implementation "com.google.firebase:firebase-auth-ktx"
}
Après la configuration, un référentiel est créé pour travailler avec les utilisateurs. Chaque utilisateur est représenté par un nœud dans l'arbre /users/{uid} avec les champs name, email et status. Pour le suivi de statut, onDisconnect est utilisé — un mécanisme spécial de Firebase qui exécute automatiquement une opération d'écriture lors de l'interruption de la connexion client. Cela garantit que le statut de l'utilisateur passe à "offline" lors de la fermeture de l'application ou de la perte de réseau sans code supplémentaire côté client.
class PresenceRepository {
private val database = FirebaseDatabase.getInstance()
private val auth = FirebaseAuth.getInstance()
private val presenceRef = database
.getReference("presence")
fun trackPresence() {
val uid = auth.currentUser?.uid ?: return
val userRef = presenceRef.child(uid)
userRef.onDisconnect().setValue("offline")
userRef.setValue("online")
}
fun getPresenceStream(): Flow<Map<String, String>> =
presenceRef.snapshotFlow()
.map { snapshot ->
(snapshot.value as? Map<*, *>)
?.mapKeys { it.key.toString() }
?.mapValues { it.value.toString() }
?: emptyMap()
}
}
L'élément clé de l'exemple est onDisconnect. Ce mécanisme permet de définir une opération d'écriture qui sera exécutée sur le serveur lorsque la connexion client est interrompue. Dans ce cas, lorsque l'utilisateur se déconnecte, son statut est automatiquement défini sur "offline" sans qu'il soit nécessaire de gérer l'événement de fermeture de l'application. Si l'application plante, Firebase exécutera lui-même l'opération onDisconnect, et les autres utilisateurs verront le statut correct.
Foire aux questions
Realtime Database stocke les données dans un seul arbre JSON et offre une latence de synchronisation plus faible. Firestore utilise des collections de documents, prend en charge les requêtes complexes et la cohérence forte. Realtime Database est meilleur pour les chats simples et les statuts, Firestore est meilleur pour les applications avec des structures de données complexes et des analyses.
La taille maximale d'un seul nœud Realtime Database est de 256 Mo. La profondeur d'imbrication est limitée à 32 niveaux. Pour un projet Firebase, plusieurs instances Realtime Database peuvent être créées (jusqu'à 5 sur le plan Spark et jusqu'à 100 sur le plan Blaze), permettant de distribuer les données entre différentes instances.
Realtime Database s'intègre avec Firebase Authentication. La variable auth contenant l'uid de l'utilisateur authentifié est disponible dans les règles de sécurité. Les développeurs peuvent restreindre l'accès au niveau des nœuds individuels de l'arbre JSON en vérifiant l'uid du propriétaire des données. Les utilisateurs anonymes et non authentifiés ont auth = null.
Oui, Realtime Database prend en charge les transactions via la méthode runTransaction. Une transaction garantit l'atomicité de l'opération lecture-modification-écriture pour un seul nœud. En cas de modifications simultanées, la transaction est réessayée avec les données actuelles. C'est utile pour les compteurs, les évaluations et autres scénarios où la cohérence des données est importante.
Oui, Realtime Database prend en charge le mode hors ligne sur Android et iOS. Le SDK met en cache les données localement et continue de traiter les opérations d'écriture sans réseau. Lorsque la connexion est rétablie, toutes les modifications accumulées sont synchronisées avec le serveur. Pour activer le mode hors ligne, utilisez la méthode keepSynced(true) sur le nœud souhaité.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi