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.
Ably is a mature realtime platform with rich delivery semantics. NoLag shares the same pub/sub foundation and presence model, so moving across is mostly a matter of renaming a few concepts. This guide maps Ably onto NoLag and shows the same flow in both.
Why teams move
NoLag keeps the realtime pub/sub and presence you rely on, and changes who runs it:
- Open source, on your own infrastructure. The kraken broker is Apache-2.0 and runs as a single container, so there is no vendor lock-in and no per-message bill. The trade is real: Ably operates its service for you, and with NoLag you operate kraken yourself.
- Blueprint SDKs for chat, notifications, dashboards, tracking, and more.
Concept map
| Ably | NoLag |
|---|---|
| API key / token auth | Actor access tokens |
| Channel | Room + topic |
channel.subscribe('event', cb) | room.on('topic', cb) |
channel.publish('event', data) | room.emit('topic', data) |
channel.presence | Presence (per room) |
| History | Your own store (NoLag is a messaging layer, not a database) |
Before: Ably
import * as Ably from 'ably'
const ably = new Ably.Realtime('API_KEY')
const channel = ably.channels.get('chat')
channel.subscribe('message', (msg) => {
console.log('Received:', msg.data)
})
channel.publish('message', { text: 'Hello!' })
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 subscribes...
const receiver = NoLag('receiver_access_token', { url: KRAKEN_URL })
const inbox = receiver.setApp(APP_SLUG).setRoom('general')
inbox.on('message', (data) => {
console.log('Received:', data)
})
// Subscribe in the connect handler: it runs after every reconnect too
receiver.on('connect', () => inbox.subscribe('message'))
await receiver.connect()
// ...and another publishes. Publishers never receive their own messages,
// so a single client that subscribes and emits will not log "Received".
const sender = NoLag('sender_access_token', { url: KRAKEN_URL })
await sender.connect()
sender.setApp(APP_SLUG).setRoom('general').emit('message', { text: 'Hello!' })
One behavioural difference from Ably is worth flagging before you port a test suite: an Ably client sees its own publishes, a NoLag actor never does. Append the sent message to your UI locally, and use a second actor in tests that expect to receive.
Presence and history
Ably presence maps to NoLag presence, tracked per room with join and leave events and a live member list. A client sets its presence on the room with room.setPresence(data) and listens for presence:join, presence:leave and presence:update on the client.
History is the one Ably feature that does not have a counterpart. NoLag is a messaging layer, not a database: nothing published while a client was disconnected is replayed when it comes back, and a fresh subscription receives no history. If you use Ably history to fill gaps after a disconnect or to render the last N messages on load, keep those messages in your own store and read it on connect. Subscribe in the connect handler, as in the sample above: it runs after every successful reconnect, and a self-hosted broker does not reliably restore subscriptions on its own.
Delivery guarantees
Ably is known for its delivery semantics. NoLag accepts quality-of-service levels 0, 1, and 2 per message, chosen on each emit. Be precise about what they cover: the level governs the hop between kraken and an MQTT broker when you run kraken against one, kraken's built-in broker does not use it, and the WebSocket leg between your client and kraken has a simpler contract. A publish can be acknowledged (pass a callback to emit and it resolves on the broker's published ack), nothing is resent for you, and there is no exactly-once guarantee end to end. Put an idempotency key in the payload of anything that must not be applied twice.
Authentication
Ably authenticates with API keys and tokens, often carrying capabilities in the token itself. NoLag centres permissions on the actor: every credential resolves to a typed actor (such as user, device, service or session), and its read and write access lives server-side as per-topic ACL rather than in each token. For browser clients running against @nolag/core, your backend mints a short-lived JWT (client token) signed with a project signing key, so long-lived credentials never leave your servers.
Next steps
- Start with the 5-minute quick start.
- Read the deeper NoLag vs Ably comparison.
- Explore the high-level SDKs if you would rather not rebuild chat or dashboards by hand.