Quick Start
Run the broker on your own machine and send a message from one client to another. Nothing here needs an account or a database: kraken ships with a token file that defines two demo actors, alice and bob.
Prerequisites
- Docker with Docker Compose, and Git
- Node.js 18 or later for the JavaScript client (or Python 3.10+, or Go 1.21+, for the other tabs)
Step 1: Start kraken
git clone --branch v0.9.0 https://github.com/NoLagApp/kraken.git
cd kraken
docker compose up -d --build
--branch v0.9.0 checks out the release these docs describe. The first build compiles kraken from source and takes a minute or two. Then check that it is up:
curl localhost:8080/health
# {"status":"ok"}
kraken now accepts WebSocket connections on ws://localhost:8080/ws. It reads its tokens from examples/auth.json, which defines two:
| Token | Actor | Permission | Topics |
|---|---|---|---|
dev-token-alice | alice | pubSub | demo/general/# |
dev-token-bob | bob | pubSub | demo/general/# |
Topics are addressed as app/room/topic, and # matches the rest of the address, so both actors may publish and subscribe to any topic in room general of app demo, such as demo/general/messages.
The demo tokens are published in the kraken repository. Replace them before the broker is reachable from anywhere but your own machine. See Static Auth File.
Step 2: Install an SDK
mkdir nolag-quickstart && cd nolag-quickstart
npm init -y
npm install @nolag/js-sdkStep 3: Subscribe as bob
Save this as subscriber.mjs:
import { NoLag } from "@nolag/js-sdk";
const bob = NoLag("dev-token-bob", { url: "ws://localhost:8080/ws" });
bob.on("error", (err) => console.error("error:", err.message));
bob.on("demo/general/messages", (data) => console.log("bob got:", data));
// Subscribe in the connect handler. It runs after every successful connect,
// including automatic reconnects, so the subscription is made again if the
// broker restarts.
bob.on("connect", () => {
bob.subscribe("demo/general/messages", (err) => {
console.log(err ? `subscribe failed: ${err.message}` : "bob is subscribed");
});
});
await bob.connect();
Run it and leave it running:
node subscriber.mjs
# bob is subscribed
NoLag is a factory function, so there is no new. The url option is required in practice: the SDKs' built-in default points at the retired NoLag Cloud broker, so every client you write passes the address of your own broker.
Step 4: Publish as alice
In a second terminal, in the same directory, save this as publisher.mjs:
import { NoLag } from "@nolag/js-sdk";
const alice = NoLag("dev-token-alice", { url: "ws://localhost:8080/ws" });
await alice.connect();
alice.emit("demo/general/messages", { text: "hello from alice" }, (err) => {
console.log(err ? `publish failed: ${err.message}` : "alice published");
alice.disconnect();
});
node publisher.mjs
# alice published
The first terminal prints:
bob got: { text: 'hello from alice' }
The emit callback fires when kraken acknowledges the publish, not when bob receives it. Subscribe and publish failures (a topic outside the token's grants, for example) arrive on that callback and on the error event; they are never thrown.
The same in Python or Go
One program that runs both actors:
import asyncio
from nolag import NoLag, NoLagOptions
URL = "ws://localhost:8080/ws"
TOPIC = "demo/general/messages"
async def main():
bob = NoLag("dev-token-bob", NoLagOptions(url=URL))
bob.on(TOPIC, lambda data, meta: print("bob got:", data))
await bob.connect()
await bob.subscribe(TOPIC)
alice = NoLag("dev-token-alice", NoLagOptions(url=URL))
await alice.connect()
await alice.emit(TOPIC, {"text": "hello from alice"})
await asyncio.sleep(1) # give the message time to arrive
alice.disconnect()
bob.disconnect()
asyncio.run(main())What just happened
- Each client opened a WebSocket to kraken and sent its token in its first frame. kraken looked the token up in
auth.jsonand cached the answer for 30 seconds. - bob subscribed to
demo/general/messages. kraken checked the topic against bob's grants,demo/general/#with permissionpubSub, and accepted it. - alice published to the same topic. kraken checked her grants and delivered the message to every connection subscribed to the topic.
A connection that is subscribed to a topic also receives its own publishes. Here alice and bob are different connections, so it does not show; pass echo: false on a publish to skip the sender's own connection. See Topics and Pub/Sub.
Reconnects: what comes back and what does not
We ran both clients against kraken v0.9.0 and restarted the broker with docker compose restart while they were connected. This is what happened:
- The JavaScript and Python clients reconnected on their own, about five seconds after the drop (their default reconnect interval).
- kraken did not restore their subscriptions. It only restores subscriptions that its auth backend lists for the actor, and the demo tokens list none. A client that subscribed once, straight after
connect(), reconnected and then received nothing, with no error. - A client that subscribes in its
connecthandler, assubscriber.mjsdoes, was subscribed again after the reconnect and received messages again. - The Go SDK sends its subscriptions again by itself after a reconnect, so the Go program above needs nothing extra.
- Messages published while a subscriber was disconnected were never delivered to it. While alice's own connection was down, her
emitcallback reportedNot connected.
In Python, make the subscription in the connect handler the same way:
bob.on("connect", lambda: asyncio.create_task(bob.subscribe(TOPIC)))
await bob.connect()
In JavaScript, use the connect event rather than reconnect: the SDK emits reconnect when it schedules a retry, before the connection is back. For more on what kraken does and does not keep across a restart, see the Production Checklist.
Troubleshooting
access_denied when connecting. The token is not in auth.json. If you edited the file, check that it is still valid JSON: kraken logs Failed to parse auth file and then accepts no tokens at all.
unknown_topic (code 42940) on a subscribe or publish. The topic is outside the token's grants. With the demo tokens, only demo/general/... topics are allowed.
Nothing arrives and nothing errors. Usually a subscription that was lost on a reconnect (see above), or a subscriber that is not connected yet when the publish happens. kraken keeps no backlog for subscribers that were not there.
The client never connects. Check that you passed url. Without it the SDK tries the retired hosted broker.
A client receives its own messages. That is kraken's default. Publish with echo: false to skip the sending connection.
Next steps
- Self-Hosting: choose between the broker on its own, your own auth service, and the full stack with
@nolag/core - Static Auth File: write your own tokens and grants
- Topics and Pub/Sub: addressing, echo, retained messages and load balancing
- JavaScript SDK: the full client API