Deploying a Waku Relay Node with Store for Offline Message Delivery
Run a Waku Relay node with the Store plugin and verify that offline subscribers receive missed messages after reconnection.
12 Dec 2025, 23:35 UTC

Desired outcome
Run a Waku Relay node that persists messages via the Store plugin and verify that a subscriber which was offline during publication receives the missed messages when it reconnects.
Prerequisites
- Docker Engine installed and the user able to run
dockercommands (either root or a user in thedockergroup). - Basic familiarity with terminal/shell usage.
- Network access to pull images from Docker Hub (no firewall blocking
docker pull).
Focused procedure
- Pull the official Waku Go image
# Run in any terminal with docker access # No special flags needed; the image is public docker pull wakuorg/waku-go:latestThis step fetches the Relay binary bundled with the Store plugin.
- Create a persistent volume for Store data
# Creates a named volume that survives container restarts docker volume create waku-store-dataThe volume will be mounted inside the container to hold the message database.
- Start the Relay node with Store enabled
# Run the container, exposing the JSON‑RPC port (default 8545) # Adjust --store-path if you prefer a different mount point docker run -d \ --name waku-relay \ -p 8545:8545 \ -v waku-store-data:/root/.waku/store \ wakuorg/waku-go:latest \ --listen-address 0.0.0.0:8545 \ --store \ --store.path /root/.waku/storeThe node begins gossiping via libp2p GossipSub and starts storing incoming messages.
- Verify the Relay is healthy
# Check that the container is running docker ps --filter name=waku-relay # Query the admin peer count endpoint (should show >0 after a few seconds) curl -s http://localhost:8545/admin/peers | jq '.peers | length'If the peer count is zero, ensure the host can reach the public bootstrap nodes or provide custom ones via
--bootstrap. - Publish a test message
# Install waku-cli if not present (npm i -g @wakuorg/waku-cli or use the binary) waku-cli publish \ --topic /my-app/1.0/pubsub \ --payload '{"event":"hello","seq":1}' \ --rpc http://localhost:8545The command returns a transaction‑like hash; the Relay logs should show a GossipSub propagation line.
- Subscribe and confirm real‑time receipt
# In a second terminal waku-cli subscribe \ --topic /my-app/1.0/pubsub \ --rpc http://localhost:8545You should see the published JSON appear within a few seconds.
- Simulate an offline subscriber
- Stop the subscriber with Ctrl+C.
- Publish a second message while the subscriber is down:
waku-cli publish \ --topic /my-app/1.0/pubsub \ --payload '{"event":"world","seq":2}' \ --rpc http://localhost:8545 - Restart the subscriber (same command as step 7).
- Verify offline delivery from Store
Upon reconnection, the subscriber should first receive the missed message (seq 2) before any new messages. The waku‑cli output will show both payloads in order.
- Optional: Check stored message count
# Use the admin store endpoint (if enabled) curl -s http://localhost:8545/admin/store/stats | jq '.totalMessages'This returns the number of messages persisted in the volume.
Expected checks
- Container runs without exit codes;
docker logs waku-relayshows no fatal errors. - Peer count > 0 after node startup indicates successful GossipSub mesh formation.
- Publish command returns a hash and the Relay log contains a line like "GossipSub message published".
- Subscriber receives messages in real time and, after reconnection, receives any messages published while it was offline.
- Store stats (if queried) increase with each published message, confirming persistence.
Recovery options
If the Relay node stops unexpectedly:
- Restart the container with the same name and volume:
docker start waku-relay(ordocker run …again). - Verify that the Store volume still contains prior messages by checking the admin store stats.
- If the volume appears corrupted, delete it (
docker volume rm waku-store-data) and start fresh; note that all persisted history will be lost.
Limitations and practical considerations
- Store increases disk usage proportionally to message volume; implement a retention policy (e.g., delete messages older than N days) by pruning the volume or configuring the Store plugin’s
--store.max-ageflag if available. - Reliability depends on network density; in very sparse partitions messages may still be lost if the Store plugin is not running.
- Version alignment matters: ensure the waku‑cli version matches the Relay’s API version to avoid RPC mismatches.
- By default, payloads are not encrypted; apply application‑level encryption (e.g., libsodium) if confidentiality is required.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.