Firebase Realtime Database é um banco de dados NoSQL em nuvem do Google com sincronização de alterações em tempo real através de uma conexão WebSocket persistente. Os dados são armazenados como uma única árvore JSON, e qualquer alteração em qualquer nó é instantaneamente entregue a todos os clientes conectados. De acordo com Google, 2026, o Realtime Database suporta até 200 mil conexões simultâneas a uma única instância. O serviço é oferecido com um limite gratuito de 1 GB de armazenamento e 10 GB de tráfego por mês.
Pontos Principais
Firebase Realtime Database é um dos primeiros bancos de dados em nuvem em tempo real, lançado pelo Google juntamente com o Firebase em 2012. É um banco de dados NoSQL onde os dados são armazenados como uma única árvore JSON acessível através de uma única URL. Os SDKs de cliente (Android, iOS, Web) subscrevem nós específicos da árvore via WebSocket e recebem atualizações a cada alteração de dados — sem necessidade de polling do servidor ou implementação de um mecanismo Push personalizado.
O Firebase original foi fundado em 2011 por James Tamplin e Andrew Lee, e o primeiro produto foi o próprio Realtime Database. Após a aquisição pelo Google em 2014 (segundo o TechCrunch — por um valor entre 50 e 100 milhões de dólares), o banco de dados foi integrado ao Google Cloud e recebeu uma capacidade significativamente maior. Em 2017, o Google anunciou o Firestore como uma substituição evolutiva, mas o Realtime Database continua a ser ativamente suportado e atualizado. De acordo com o Google (2026), o Realtime Database ainda é utilizado em mais de 1.5 milhões de projetos ativos.
Plano Spark (gratuito) inclui: 1 GB de armazenamento, 10 GB de dados transferidos por mês, 100 conexões simultâneas e suporte a banco de dados numa região. No plano Blaze (pay-as-you-go), é cobrado por armazenamento adicional ($1/GB), tráfego ($0.12/GB) e conexões simultâneas ($5 por cada 100 mil acima do limite). Para testes, também está disponível um modo de emulação — firebase emulators:start — que executa o Realtime Database localmente sem conexão à nuvem.
O Realtime Database não tem tabelas, coleções ou documentos — tudo é uma única árvore JSON acessível através de uma URL como https://project-name-default-rtdb.firebaseio.com/. Cada chave da árvore é ou um valor final (string, número, booleano, null) ou um nó aninhado com chaves filhas. O motor do banco de dados não suporta JOIN, subconsultas ou agregações — uma consulta devolve sempre o conteúdo de um nó com todos os seus elementos filhos.
Devido à falta de JOIN no Realtime Database, a normalização de dados é obrigatória. Em vez de uma árvore aninhada (utilizador → lista das suas publicações), os dados são divididos em listas planas com referências através de chaves. Esta é a abordagem padrão: os dados são desnormalizados para que a leitura de um nó não puxe todo o contexto. Por exemplo, a lista de mensagens de chat é armazenada separadamente dos perfis de utilizador, e cada publicação contém apenas o ID do autor, não todo o seu perfil.
| Abordagem | Exemplo de Estrutura | Problema |
|---|---|---|
| Aninhado | users/{uid}/posts/{postId}/content | Ler utilizador carrega todas as publicações |
| Plano | posts/{postId}/authorId + users/{uid}/name | Requer duas consultas |
| Desnormalizado | posts/{postId}/authorName (copiado) | Duplicação ao atualizar |
As consultas no Realtime Database são executadas usando filtros (orderByChild, orderByKey, orderByValue, limitToFirst, limitToLast, equalTo, startAt, endAt). Ao contrário do Firestore, os índices são criados manualmente através da secção Rules (.indexOn). Se um índice não for declarado, uma consulta com ordenação devolve um erro PERMISSION_DENIED. As consultas funcionam apenas num único campo — consultas compostas (filtrar por preço + ordenar por data) não são suportadas. Para filtragem complexa, os dados são frequentemente duplicados em diferentes nós com diferentes chaves de ordenação.
Escolher entre Realtime Database e Firestore é uma das decisões arquitetónicas comuns ao iniciar um projeto. O Google recomenda o Firestore para a maioria das novas aplicações, mas o Realtime Database continua a ser a melhor escolha para cenários onde a latência mínima de transferência de dados é crítica.
Primeiro cenário — jogos multijogador com sincronização de estado (xadrez, jogos de cartas, ação em tempo real). A latência do Realtime Database é de 10-30 ms contra 50-100 ms do Firestore na mesma região. Segundo cenário — chats e mensageiros com alta frequência de mensagens. O Realtime Database é faturado por volume de dados, não por número de escritas, tornando-o significativamente mais barato que o Firestore em frequências superiores a 1 mensagem por segundo. Terceiro cenário — presença de utilizadores (online/offline), onde os manipuladores onDisconnect do Realtime Database permitem definir atomicamente o estado ao perder a conexão.
De acordo com o Google (2026), aproximadamente 15% dos novos projetos Firebase escolhem conscientemente o Realtime Database — quando a equipa compreende claramente os seus requisitos de latência, estrutura de dados e orçamento. Nos restantes 85% dos casos, o Firestore é a escolha mais segura graças à melhor escalabilidade, consultas mais poderosas e replicação automática.
Ligar o Realtime Database a uma aplicação Android é feito adicionando a dependência firebase-database-ktx no build.gradle. O objeto FirebaseDatabase está disponível através de getInstance(url) — pode ligar-se a várias bases de dados dentro de um mesmo projeto Firebase. Após a inicialização, o SDK estabelece automaticamente uma conexão WebSocket com o servidor e começa a sincronização de dados.
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")
O Realtime Database utiliza o objeto DatabaseReference para todas as operações. setValue() escreve dados no nó especificado, substituindo completamente todo o seu conteúdo. push() gera automaticamente uma chave única (baseada num timestamp) para adicionar um item a uma lista — esta é a forma padrão de criar mensagens de chat, publicações e registos. updateChildren() modifica vários nós atomicamente numa única operação. addValueEventListener subscreve alterações de nó e recebe um callback em cada atualização de dados.
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) }
}
}
O mecanismo de sincronização do Realtime Database baseia-se no protocolo WebSocket (anteriormente — long-polling). O cliente envia um pedido para subscrever um nó específico, e o servidor mantém a conexão aberta. Em qualquer alteração de dados no nó subscrito, o servidor envia o JSON completo desse nó ao cliente. O SDK no cliente atualiza automaticamente o estado local e aciona os callbacks correspondentes (onDataChange).
OnDisconnect é uma funcionalidade única do Realtime Database que está ausente no Firestore. Um programador pode registar uma operação de escrita que será executada automaticamente no servidor quando a conexão do cliente for perdida. Isto é usado para estados de presença: "user123/status": "online" com onDisconnect.setValue("offline"). Se o utilizador fechar a aplicação ou perder a internet, o servidor definirá automaticamente o estado para "offline" dentro de no máximo 3 minutos (configurável na consola Firebase).
Persistence no Realtime Database é ativada com uma única linha: FirebaseDatabase.getInstance().setPersistenceEnabled(true). O SDK armazena em cache no disco o último estado de todos os nós subscritos (até 10 MiB por defeito, configurável até 100 MiB). Quando a conexão é perdida, o cliente continua a trabalhar com os dados em cache, e todas as operações de escrita são colocadas em fila. Quando a conexão é restaurada, o SDK envia todas as alterações acumuladas ao servidor na ordem correta (FIFO).
De acordo com o Google (2026), as aplicações com cache de persistência ativada têm 40% menos probabilidade de perder dados de utilizador ao perder a conexão. No entanto, se um cliente acumulou mais de 1000 operações pendentes, o servidor pode rejeitá-las todas e solicitar uma sincronização completa — este é um mecanismo de proteção contra clientes desatualizados.
As Regras de Segurança no Realtime Database são uma configuração JSON que descreve quem pode ler e escrever dados em cada nó e sob que condições. As regras são executadas no servidor do Google e são aplicadas antes de cada operação. Por defeito (em produção), recomenda-se definir as regras em modo "fechado" — apenas utilizadores autenticados têm acesso.
As regras do Realtime Database são escritas em formato JSON com as secções .read, .write, .validate, .indexOn. Ao contrário do Firestore (que usa sintaxe match), o Realtime Database usa objetos aninhados que refletem a estrutura de dados. As condições verificam auth (autenticação), data (dados existentes), newData (novos dados na escrita) e now (hora do servidor). As regras de validação (.validate) permitem verificar tipos, intervalos de valores e estrutura de dados.
{
"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"
}
}
}
}
As regras do Realtime Database são herdadas em cascata — se .read = false no nível superior, todos os nós filhos ficam indisponíveis para leitura independentemente das suas próprias regras. O Firebase fornece um simulador de regras na consola onde pode testar operações com diferentes tokens de autenticação antes da implementação. Recomenda-se testar sempre as regras no simulador — um erro numa regra pode abrir o acesso a dados privados de todos os utilizadores. De acordo com o Google (2026), 40% das fugas de dados em projetos Firebase são causadas por regras de segurança mal configuradas.
Perguntas Frequentes
Até 200 mil conexões simultâneas a uma única instância de banco de dados. Quando o limite é excedido, novas conexões são bloqueadas. Para escalar, utiliza-se a fragmentação em várias bases de dados.
Use onDisconnect — registe uma operação de escrita para "offline" ao perder a conexão. O servidor executá-la-á automaticamente quando o WebSocket for interrompido. Monitorize a conexão separadamente através de .info/connected.
Verifique .indexOn nas Regras de Segurança — sem um índice declarado, uma consulta com orderByChild devolverá PERMISSION_DENIED. Certifique-se também de que os dados são escritos no nó correto e o leitor tem permissões .read.
A Consola Firebase fornece exportação do Realtime Database para o Firestore com um único botão. A estrutura JSON é convertida em coleções e documentos. Para migrações personalizadas, use o Admin SDK.
Não, armazenar palavras-passe no Realtime Database é proibido pelas regras de segurança do Google. Use o Firebase Auth para autenticação — os hashes de palavras-passe são armazenados num armazenamento isolado que não é acessível através do SDK do Realtime Database.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também