Firebase Realtime Database Integration for Chat in Mobile Application
Firebase Realtime Database gives WebSocket connection out of box, realtime synchronization and simple SDK — honest pluses for prototype or small chat. But on load growth or structure complication specific problems start, which are solved with correct data structure from day one.
Data Structure — Key Decision
Most expensive mistake integrating Firebase Realtime Database for chat — flat structure with nested messages in chat object. When conversation has 10,000 messages, each childEventListener on root chat node pulls entire tree. On Android this manifests in OutOfMemoryError, on iOS — noticeable lag when opening old chat.
Correct structure:
/chats/{chatId}/
metadata: { title, lastMessage, updatedAt }
members: { userId1: true, userId2: true }
/messages/{chatId}/{messageId}/
text, senderId, timestamp, status
/userChats/{userId}/{chatId}: true
Separating chat metadata and messages allows subscribing to user's chat list (/userChats/{userId}) without loading entire history. Messages load separately with pagination via limitToLast(50).
Pagination and Real-time Updates
Combining initial load via limitToLast and live subscription to new messages — not trivial task. Standard approach:
- Load last 50 messages via
orderByChild("timestamp").limitToLast(50). - Remember
timestampof oldest message from set. - Live subscription to new messages after current time:
startAt(currentTimestamp). - For history load up:
endAt(oldestTimestamp).limitToLast(50)— new one-time request.
Android SDK:
val query = database.child("messages").child(chatId)
.orderByChild("timestamp")
.startAt(System.currentTimeMillis().toDouble())
query.addChildEventListener(object : ChildEventListener {
override fun onChildAdded(snapshot: DataSnapshot, previousChildName: String?) {
val message = snapshot.getValue(Message::class.java) ?: return
// add to list
}
// ...
})
Security Rules
Firebase Security Rules — mandatory part often done last. Without proper rules base is open. Minimal set for chat:
{
"rules": {
"messages": {
"$chatId": {
".read": "auth != null && root.child('chats').child($chatId).child('members').child(auth.uid).exists()",
".write": "auth != null && root.child('chats').child($chatId).child('members').child(auth.uid).exists()"
}
}
}
}
Test rules — via Firebase Rules Playground before production deploy.
Limitations and When to Choose Firestore
Realtime Database loses to Firestore on query capabilities: no composite indexes, no where with multiple fields. If need message sorting by multiple criteria, text search or complex filtering — Firestore preferable. For simple 1-to-1 chat or group without complex logic Realtime Database works fine.
What's Included
Design data schema for your chat type, implement SDK integration (Android/iOS/Flutter), configure pagination and live updates, write Security Rules, setup offline persistence (enabled by default but requires fine-tuning keepSynced).
Timeline: 3–6 days for full-featured chat with history, online-statuses and read-statuses.







