Firebase Realtime Database è un database NoSQL cloud di Google con sincronizzazione delle modifiche in tempo reale attraverso una connessione WebSocket persistente. I dati sono memorizzati come un singolo albero JSON e qualsiasi modifica a qualsiasi nodo viene istantaneamente consegnata a tutti i client connessi. Secondo Google, 2026, Realtime Database supporta fino a 200 mila connessioni simultanee a una singola istanza. Il servizio è offerto con un limite gratuito di 1 GB di archiviazione e 10 GB di traffico al mese.
Punti Chiave
Firebase Realtime Database è uno dei primi database cloud in tempo reale, lanciato da Google insieme a Firebase nel 2012. È un database NoSQL in cui i dati sono memorizzati come un singolo albero JSON accessibile tramite un singolo URL. Gli SDK client (Android, iOS, Web) si iscrivono a nodi specifici dell'albero tramite WebSocket e ricevono aggiornamenti a ogni modifica dei dati — senza polling del server e senza implementare un meccanismo Push personalizzato.
Firebase originale è stata fondata nel 2011 da James Tamplin e Andrew Lee, e il primo prodotto è stato proprio Realtime Database. Dopo l'acquisizione da parte di Google nel 2014 (secondo TechCrunch — per un importo tra 50 e 100 milioni di dollari), il database è stato integrato in Google Cloud e ha ricevuto una capacità notevolmente superiore. Nel 2017, Google ha annunciato Firestore come sostituto evolutivo, ma Realtime Database continua a essere attivamente supportato e aggiornato. Secondo Google (2026), Realtime Database è ancora utilizzato in più di 1,5 milioni di progetti attivi.
Piano Spark (gratuito) include: 1 GB di archiviazione, 10 GB di dati scaricati al mese, 100 connessioni simultanee e supporto del database in una regione. Sul piano Blaze (pay-as-you-go), viene addebitato un costo per archiviazione aggiuntiva ($1/GB), traffico ($0.12/GB) e connessioni simultanee ($5 per ogni 100 mila oltre il limite). Per i test, è disponibile anche una modalità di emulazione — firebase emulators:start — che esegue Realtime Database localmente senza connessione al cloud.
Realtime Database non ha tabelle, raccolte o documenti — tutto è un singolo albero JSON accessibile tramite un URL come https://project-name-default-rtdb.firebaseio.com/. Ogni chiave dell'albero è o un valore finale (stringa, numero, booleano, null) o un nodo annidato con chiavi figlie. Il motore del database non supporta JOIN, sottoquery o aggregazioni — una query restituisce sempre il contenuto di un nodo con tutti i suoi elementi figli.
A causa della mancanza di JOIN in Realtime Database, la normalizzazione dei dati è obbligatoria. Invece di un albero annidato (utente → elenco dei suoi post), i dati vengono suddivisi in elenchi piatti con riferimenti tramite chiavi. Questo è l'approccio standard: i dati vengono denormalizzati in modo che la lettura di un nodo non trascini l'intero contesto. Ad esempio, l'elenco dei messaggi di chat viene memorizzato separatamente dai profili utente e ogni post contiene solo l'ID dell'autore, non l'intero profilo.
| Approccio | Esempio di Struttura | Problema |
|---|---|---|
| Annidato | users/{uid}/posts/{postId}/content | Leggere l'utente carica tutti i post |
| Piatto | posts/{postId}/authorId + users/{uid}/name | Richiede due query |
| Denormalizzato | posts/{postId}/authorName (copiato) | Duplicazione all'aggiornamento |
Le query in Realtime Database vengono eseguite utilizzando filtri (orderByChild, orderByKey, orderByValue, limitToFirst, limitToLast, equalTo, startAt, endAt). A differenza di Firestore, gli indici vengono creati manualmente tramite la sezione Rules (.indexOn). Se un indice non è dichiarato, una query con ordinamento restituisce un errore PERMISSION_DENIED. Le query funzionano solo su un singolo campo — le query composte (filtrare per prezzo + ordinare per data) non sono supportate. Per filtraggi complessi, i dati vengono spesso duplicati in nodi diversi con chiavi di ordinamento diverse.
Scegliere tra Realtime Database e Firestore è una delle decisioni architetturali comuni all'avvio di un progetto. Google raccomanda Firestore per la maggior parte delle nuove applicazioni, ma Realtime Database rimane la scelta migliore per scenari in cui la latenza minima di trasferimento dati è critica.
Primo scenario — giochi multiplayer con sincronizzazione dello stato (scacchi, giochi di carte, azione in tempo reale). La latenza di Realtime Database è di 10-30 ms contro 50-100 ms di Firestore nella stessa regione. Secondo scenario — chat e messaggistica con alta frequenza di messaggi. Realtime Database viene fatturato in base al volume di dati, non al numero di scritture, rendendolo significativamente più economico di Firestore a frequenze superiori a 1 messaggio al secondo. Terzo scenario — presenza degli utenti (online/offline), dove i gestori onDisconnect di Realtime Database consentono di impostare atomicamente lo stato in caso di perdita di connessione.
Secondo Google (2026), circa il 15% dei nuovi progetti Firebase sceglie consapevolmente Realtime Database — quando il team comprende chiaramente i propri requisiti di latenza, struttura dei dati e budget. Nel restante 85% dei casi, Firestore è la scelta più sicura grazie alla migliore scalabilità, query più potenti e replica automatica.
Connettere Realtime Database a un'applicazione Android si effettua aggiungendo la dipendenza firebase-database-ktx in build.gradle. L'oggetto FirebaseDatabase è disponibile tramite getInstance(url) — puoi connetterti a più database all'interno di un singolo progetto Firebase. Dopo l'inizializzazione, l'SDK stabilisce automaticamente una connessione WebSocket con il server e avvia la sincronizzazione dei dati.
dependencies {
implementation(platform("com.google.firebase:firebase-bom:33.1.0"))
implementation("com.google.firebase:firebase-database-ktx")
}
// Initialization with custom URL
val database = FirebaseDatabase.getInstance(
"https://my-project-default-rtdb.firebaseio.com/"
)
val ref = database.getReference("chats")
Realtime Database utilizza l'oggetto DatabaseReference per tutte le operazioni. setValue() scrive i dati nel nodo specificato, sostituendo completamente tutto il suo contenuto. push() genera automaticamente una chiave univoca (basata su un timestamp) per aggiungere un elemento a un elenco — questo è il metodo standard per creare messaggi di chat, post e record. updateChildren() modifica più nodi atomicamente in un'unica operazione. addValueEventListener si iscrive alle modifiche dei nodi e riceve un callback a ogni aggiornamento dei dati.
data class Message(
val author: String = "",
val text: String = "",
val timestamp: Long = ServerValue.TIMESTAMP
)
class ChatRepository(private val ref: DatabaseReference) {
fun sendMessage(author: String, text: String) {
val msg = Message(author = author, text = text)
ref.child("messages").push().setValue(msg)
}
fun observeMessages(): Flow<List<Message>> = callbackFlow {
val listener = ref.child("messages")
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val messages = snapshot.children.mapNotNull { it.getValue(Message::class.java) }
trySend(messages)
}
override fun onCancelled(error: DatabaseError) {}
})
awaitClose { ref.removeEventListener(listener) }
}
}
Il meccanismo di sincronizzazione di Realtime Database si basa sul protocollo WebSocket (precedentemente — long-polling). Il client invia una richiesta per iscriversi a un nodo specifico e il server mantiene la connessione aperta. A ogni modifica dei dati nel nodo sottoscritto, il server invia il JSON completo di quel nodo al client. L'SDK sul client aggiorna automaticamente lo stato locale e attiva i callback corrispondenti (onDataChange).
OnDisconnect è una funzionalità unica di Realtime Database assente in Firestore. Uno sviluppatore può registrare un'operazione di scrittura che verrà eseguita automaticamente sul server quando la connessione del client viene persa. Questo viene utilizzato per gli stati di presenza: “user123/status”: “online” con onDisconnect.setValue(“offline”). Se l'utente chiude l'app o perde Internet, il server imposterà automaticamente lo stato su “offline” entro un massimo di 3 minuti (configurabile nella console Firebase).
Persistence in Realtime Database viene attivato con una singola riga: FirebaseDatabase.getInstance().setPersistenceEnabled(true). L'SDK memorizza nella cache su disco l'ultimo stato di tutti i nodi sottoscritti (fino a 10 MiB per impostazione predefinita, configurabile fino a 100 MiB). Quando la connessione viene persa, il client continua a lavorare con i dati nella cache e tutte le operazioni di scrittura vengono messe in coda. Quando la connessione viene ripristinata, l'SDK invia tutte le modifiche accumulate al server nell'ordine corretto (FIFO).
Secondo Google (2026), le applicazioni con cache di persistenza attivata perdono dati utente con una probabilità inferiore del 40% in caso di perdita di connessione. Tuttavia, se un client ha accumulato più di 1000 operazioni in sospeso, il server potrebbe rifiutarle tutte e richiedere una sincronizzazione completa — questo è un meccanismo di protezione contro i client obsoleti.
Le Regole di Sicurezza in Realtime Database sono una configurazione JSON che descrive chi può leggere e scrivere dati in ogni nodo e a quali condizioni. Le regole vengono eseguite sul server di Google e vengono applicate prima di ogni operazione. Per impostazione predefinita (in produzione), si consiglia di impostare le regole in modalità “chiuso” — solo gli utenti autenticati hanno accesso.
Le regole di Realtime Database sono scritte in formato JSON con le sezioni .read, .write, .validate, .indexOn. A differenza di Firestore (che usa la sintassi match), Realtime Database utilizza oggetti annidati che riflettono la struttura dei dati. Le condizioni verificano auth (autenticazione), data (dati esistenti), newData (nuovi dati in scrittura) e now (orario del server). Le regole di validazione (.validate) consentono di verificare tipi, intervalli di valori e struttura dei dati.
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid === $uid",
".write": "auth.uid === $uid",
".validate": "newData.hasChildren(['name', 'email'])"
}
},
"messages": {
".indexOn": ["timestamp"],
"$msgId": {
".read": true,
".write": "auth.uid !== null",
".validate": "newData.child('text').isString() && newData.child('text').val().length <= 500"
}
}
}
}
Le regole di Realtime Database vengono ereditate a cascata — se .read = false al livello superiore, tutti i nodi figli non sono disponibili per la lettura indipendentemente dalle proprie regole. Firebase fornisce un simulatore di regole nella console dove è possibile testare le operazioni con diversi token di autenticazione prima del deployment. Si consiglia di testare sempre le regole nel simulatore — un errore in una regola può aprire l'accesso ai dati privati di tutti gli utenti. Secondo Google (2026), il 40% delle fughe di dati nei progetti Firebase è causato da regole di sicurezza configurate in modo errato.
Domande Frequenti
Fino a 200 mila connessioni simultanee a una singola istanza del database. Quando il limite viene superato, le nuove connessioni vengono bloccate. Per scalare, viene utilizzato lo sharding su più database.
Usa onDisconnect — registra un'operazione di scrittura per “offline” in caso di perdita di connessione. Il server la eseguirà automaticamente quando il WebSocket viene interrotto. Monitora la connessione separatamente tramite .info/connected.
Controlla .indexOn nelle Regole di Sicurezza — senza un indice dichiarato, una query con orderByChild restituirà PERMISSION_DENIED. Assicurati anche che i dati siano scritti nel nodo corretto e che il lettore abbia i permessi .read.
La console Firebase fornisce l'esportazione da Realtime Database a Firestore con un solo pulsante. La struttura JSON viene convertita in raccolte e documenti. Per migrazioni personalizzate, usa l'SDK Admin.
No, memorizzare password in Realtime Database è vietato dalle regole di sicurezza di Google. Usa Firebase Auth per l'autenticazione — gli hash delle password sono conservati in un archivio isolato non accessibile tramite l'SDK di Realtime Database.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche