---
title: "Migrate from Firebase to NoLag"
description: How to move the realtime layer of a Firebase app to NoLag, when it makes sense, and what to keep. Includes a concept map and before-and-after code.
excerpt: "Firebase syncs data through database listeners; NoLag is explicit pub/sub. Here is how to migrate the realtime layer, and the one thing you should not try to move."
date: '2026-08-01'
readTime: 7 min read
category: Migration 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.

## 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.
- **A coordination layer for AI agents** on the same platform.

## Concept map

| Firebase | NoLag |
| --- | --- |
| Realtime Database ref / Firestore collection | Room + topic |
| `onValue` / `onSnapshot` listener | `room.on('topic', cb)` |
| `set` / `update` / `push` | `room.emit('topic', data)` |
| Security rules | Actors, access tokens, per-topic ACL |
| Presence via connection state | Presence (per room) |

## Before: Firebase Realtime Database

```js
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

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

const client = NoLag('your_access_token')
await client.connect()

const room = client.setApp('chat').setRoom('general')
room.subscribe('messages')

room.on('messages', (data) => {
  console.log('Message received:', data)
})

room.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.

## Access control

Firebase security rules become **per-topic ACL** in NoLag, tied to a typed **actor** and enforced at the broker rather than written in a rules language. A connection authenticates with an actor token, and browser clients use short-lived JWTs ([client tokens](/docs/client-tokens)) your backend signs with a project signing key.

## Next steps

- Follow the [5-minute quick start](/docs/getting-started).
- See the full [NoLag vs Firebase](/compare/firebase) comparison.
- If you are keeping a database, use NoLag alongside it for the live layer only.
