Интеграция SDK чата Firebase Realtime Database для чата
Firebase Realtime Database даёт WebSocket-соединение из коробки, синхронизацию в реальном времени и простой SDK — это честные плюсы для прототипа или небольшого чата. Но при росте нагрузки или усложнении структуры начинаются специфические проблемы, которые решаются правильной структурой данных с первого дня.
Структура данных — ключевое решение
Самая дорогостоящая ошибка при интеграции Firebase Realtime Database для чата — плоская структура с вложенными сообщениями в объект чата. Когда в разговоре 10 000 сообщений, каждый childEventListener на корневой узел чата тянет всё дерево. На Android это выражается в OutOfMemoryError, на iOS — в заметном лаге при открытии старого чата.
Правильная структура:
/chats/{chatId}/
metadata: { title, lastMessage, updatedAt }
members: { userId1: true, userId2: true }
/messages/{chatId}/{messageId}/
text, senderId, timestamp, status
/userChats/{userId}/{chatId}: true
Разделение метаданных чата и сообщений позволяет подписываться на список чатов пользователя (/userChats/{userId}) без загрузки всей истории. Сообщения загружаются отдельно с пагинацией через limitToLast(50).
Пагинация и real-time обновления
Совмещение начальной загрузки через limitToLast и live-подписки на новые сообщения — не тривиальная задача. Стандартный подход:
- Загружаем последние 50 сообщений через
orderByChild("timestamp").limitToLast(50). - Запоминаем
timestampстарейшего сообщения из набора. - Live-подписка через
childEventListenerна новые сообщения после текущего момента:startAt(currentTimestamp). - Для загрузки истории вверх:
endAt(oldestTimestamp).limitToLast(50)— новый одноразовый запрос.
На 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
// добавляем в список
}
// ...
})
Правила безопасности
Firebase Security Rules — обязательная часть, которую часто делают последней. Без правильных rules база открыта. Минимальный набор для чата:
{
"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()"
}
}
}
}
Тестирование правил — через Firebase Rules Playground до деплоя в продакшн.
Ограничения и когда выбрать Firestore
Realtime Database проигрывает Firestore по возможностям запросов: нет составных индексов, нет where с несколькими полями. Если нужна сортировка сообщений по нескольким критериям, поиск по тексту или сложная фильтрация — Firestore предпочтительнее. Для простого чата «один-на-один» или группового без сложной логики Realtime Database вполне подходит.
Что входит в работу
Проектируем схему данных под ваш тип чата, реализуем SDK-интеграцию (Android/iOS/Flutter), настраиваем пагинацию и live-обновления, пишем Security Rules, настраиваем оффлайн-persistence (включена по умолчанию, но требует тонкой настройки keepSynced).
Срок: 3–6 дней для полноценного чата с историей, online-статусами и статусами прочтения.







