← Back to blog
MIGRATION GUIDE7 min read

Migrate from Firebase to NoLag

HB
Henco Burger
August 1, 2026

This post was written for NoLag Cloud, the hosted service, which was retired in October 2026. To run NoLag yourself, start with the self-hosting guide.

Firebase Realtime Database and Firestore give you realtime by syncing stored documents and firing client listeners when the data changes. NoLag takes a different approach: explicit publish and subscribe over topics. That difference matters for migration, so let us be clear up front about what to move and what to keep.

What to migrate, and what not to

NoLag is a messaging layer, not a database. If you use Firebase purely as a realtime signal, presence, or message bus, NoLag replaces that cleanly and gives you more control over delivery. If you use Firebase as your system of record, keep a database. Migrate the realtime and pub/sub usage to NoLag, and let your data live wherever suits you. Many teams end up with NoLag for the live layer and a database of their choice behind it.

This also answers the question every Firebase team asks first: "what does a client see when it reconnects?" In Firebase, the current document. In NoLag, only what is published from then on: nothing from the gap is replayed, and a fresh subscription gets no history. The database you keep is where "current state" lives, and the client reads it on connect. Do your subscribing in the connect handler too, as in the sample below: it runs after every successful reconnect, and a self-hosted broker does not reliably restore subscriptions on its own.

Why teams move the realtime layer

  • Explicit pub/sub instead of modelling every realtime feature as a change on a stored document.
  • Database-agnostic: add realtime to any stack rather than standardising on Firestore.
  • Blueprint SDKs for chat, notifications, dashboards, and tracking.
  • Open source, on your own infrastructure. The kraken broker is Apache-2.0 and runs as a single container. Firebase is a managed Google service; with NoLag you run the broker yourself, and nothing ties you to a vendor.

Concept map

FirebaseNoLag
Realtime Database ref / Firestore collectionRoom + topic
onValue / onSnapshot listenerroom.on('topic', cb)
set / update / pushroom.emit('topic', data)
Security rulesActors, access tokens, per-topic ACL
Presence via connection statePresence (per room)

Before: Firebase Realtime Database

import { getDatabase, ref, onValue, push } from 'firebase/database'

const db = getDatabase()
const messagesRef = ref(db, 'chat/general/messages')

onValue(messagesRef, (snapshot) => {
  console.log('Data changed:', snapshot.val())
})

push(messagesRef, { text: 'Hello!', sender: 'user-123' })

After: NoLag

import { NoLag } from '@nolag/js-sdk'

// KRAKEN_URL is your broker, for example ws://localhost:8080/ws.
// The `chat` app and its `general` room are granted to both tokens in your
// auth config (kraken's auth.json or a @nolag/core project document).
const APP_SLUG = 'chat'

// One actor listens...
const receiver = NoLag('receiver_access_token', { url: KRAKEN_URL })
const inbox = receiver.setApp(APP_SLUG).setRoom('general')
inbox.on('messages', (data) => {
  console.log('Message received:', data)
})
// Subscribe in the connect handler: it runs after every reconnect too
receiver.on('connect', () => inbox.subscribe('messages'))
await receiver.connect()

// ...and another publishes. Publishers never receive their own messages,
// so the sender appends its own message to the UI locally.
const sender = NoLag('sender_access_token', { url: KRAKEN_URL })
await sender.connect()
sender.setApp(APP_SLUG).setRoom('general').emit('messages', { text: 'Hello!', sender: 'user-123' })

The key shift is from "write to a path and listen for changes" to "publish an event and subscribe to it." You send exactly the message you mean, rather than reshaping your data model so that a write triggers the right listeners. The other shift is that a Firebase listener fires for the writer too, and a NoLag publisher never receives its own message: update your local state when you send, and let the subscription carry everyone else's.

Access control

Firebase security rules become per-topic ACL in NoLag, tied to a typed actor (such as user, device, service or session) and enforced at the broker rather than written in a rules language. A connection authenticates with an actor token, and with @nolag/core browser clients use short-lived JWTs (client tokens) your backend signs with a project signing key.

Next steps