Waku's Store-and-Forward Gossip: Reliable Messaging When Peers Keep Disappearing
Waku pairs GossipSub mesh relay with a store-and-forward protocol so peers that drop offline can catch up. Here is how the pieces fit, a minimal js-waku example, and the limits to plan around.
29 Sept 2026, 23:22 UTC

If you are building a chat, notification, or coordination layer without a central server, the hard part is not sending a message — it is what happens when the recipient is offline, on flaky mobile data, or behind a NAT that just killed the connection. Waku, a family of peer-to-peer messaging protocols that grew out of the Status project, tackles this with two ideas working together: a GossipSub mesh for live propagation and a store protocol for catching up on what you missed. This post explains how those pieces fit, shows a minimal working setup, and covers where the design starts to strain.
The problem Waku is actually solving
Plain GossipSub (the pub/sub routing protocol used in libp2p) is deliberately simple: nodes subscribe to topics, form a partial mesh of peers per topic, and relay new messages to their mesh neighbors. Delivery is fast and bandwidth stays bounded because each node only forwards messages for topics it cares about. But GossipSub alone assumes reasonably stable, online peers. If your laptop sleeps for an hour or your phone drops to 2G, messages published during that window are simply gone from your perspective.
Waku layers on top of this. The relay protocol is GossipSub-based, so live traffic propagates through a topic-scoped mesh. On top of that, Waku defines a separate store protocol: nodes that opt in keep recent messages (typically time-windowed and size-capped) and answer history queries. A node that reconnects can ask a store-capable peer for messages on its topics since a timestamp, page through the results, and fill the gap. The network layer is deliberately separated from the application layer, so the same messaging semantics can run over different libp2p transports.
A minimal two-node check
The fastest way to see this behavior is with js-waku, the JavaScript implementation. The snippet below creates a light node, connects to a peer, subscribes to a content topic, and publishes. Run it in Node.js (version compatibility with the current js-waku release should be checked against the project's README — the API has changed across major versions, so treat this as a sketch to verify, not a drop-in):
import { createLightNode } from "@waku/sdk";
import { createEncoder, createDecoder } from "@waku/sdk";
const node = await createLightNode({ defaultBootstrap: true });
await node.start();
await node.waitForPeers();
const contentTopic = "/demo/1/chat/proto";
const encoder = createEncoder({ contentTopic });
const decoder = createDecoder(contentTopic);
await node.filter.subscribe([decoder], (msg) => {
console.log("received:", new TextDecoder().decode(msg.payload));
});
await node.lightPush.send(encoder, {
payload: new TextEncoder().encode("hello from node A"),
});No special permissions are needed beyond network egress. The meaningful placeholder is the content topic string — Waku content topics follow a /{app}/{version}/{name}/{encoding} convention, and both nodes must use the identical string. A practical verification: run the script on two machines (or a machine and a VPS), publish from one, and confirm the callback fires on the other. To check the store path, take the receiving node offline, publish several messages, restart it, and query a store node for the topic's recent history — the missed messages should come back if a store-capable peer was reachable and still holds them.
Why the mesh trade-off matters
Waku's relay mesh mirrors GossipSub's core compromise. Each node maintains a small set of mesh peers per topic and gossips message metadata (IHAVE/IWANT exchanges) to a wider set. That bounds bandwidth — you are not flooding the whole network — but it means propagation latency depends on mesh health. Under high churn, where peers join and leave faster than the mesh can repair, you will see delivery delays or gaps until the mesh re-forms around a topic. The store protocol is the safety net for exactly this failure mode, which is why the two are designed to be used together rather than as alternatives.
Topic-scoped relaying also has a privacy and efficiency angle: nodes only forward traffic for topics they subscribe to, so a well-chosen topic structure keeps resource-constrained nodes (phones, browsers running light nodes) from drowning in irrelevant traffic.
Limitations worth planning around
Three constraints show up quickly in real deployments:
- Message size. Large payloads congest the gossip layer. Waku deployments generally expect small messages; if you need to move big blobs, fragment at the application layer or move the bulk data out of band and gossip a reference.
- Store is best-effort. Store nodes hold bounded history and are under no obligation to keep your messages. If you need guaranteed retention, you need your own archival node, not the public network's goodwill.
- Permissionless means Sybil-exposed. Without strong peer identity, an attacker can spin up many nodes to degrade routing or censor topics. Rate limiting and protocol-level protections help, but treat this as an open design consideration, not a solved problem.
A concrete way to sanity-check your setup before shipping: run two nodes on separate networks, publish a burst of messages while one is disconnected, reconnect it, and confirm the store query returns the full burst. Then watch traffic with a packet analyzer or your node's metrics to confirm you are seeing bounded gossip rather than uncontrolled flooding. If either check fails, the issue is almost always topic-string mismatch, missing store peers, or a bootstrap connectivity problem — in that order.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.