Libraries
Hyperswarm
Discovers peers on shared topics and establishes encrypted connections.
Verified 19 October 2026
Find another instance of your notes app and connect its replication stream.
Status in Unstoppable Stack
Discovery does not grant permission. Use application pairing and grants for access control.
How it works
A topic is a 32-byte discovery identifier. Peers looking for the same topic can find one another without your own application directory server.
The connection event supplies an encrypted byte stream. Your protocol still needs framing, validation and a decision about which remote identities may access data.
This example creates two peers and a local DHT bootstrap in one process. It exercises topic discovery without announcing anything to the public network.
Run an example
Use Node 22.17+ and npm for installation. Start in a new directory for this example so its ./data storage cannot collide with another example. Save each file below with the exact filename shown, then run the commands in order.
mkdir hyperswarm-demo
cd hyperswarm-demo
npm init -y
npm install hyperswarm@'^4.17.2' hyperdht@'^6.34.1'Save as example.mjs:
import Hyperswarm from 'hyperswarm'
import DHT from 'hyperdht'
import { randomBytes } from 'node:crypto'
const seed = DHT.bootstrapper(49777, '127.0.0.1')
await seed.ready()
const bootstrap = [{ host: '127.0.0.1', port: seed.address().port }]
const host = new Hyperswarm({ bootstrap })
const client = new Hyperswarm({ bootstrap })
const topic = randomBytes(32)
let timer
try {
host.on('connection', socket => {
socket.on('error', () => {})
socket.end('Hello topic')
})
const received = new Promise((resolve, reject) => {
timer = setTimeout(() => reject(new Error('Discovery timed out')), 10000)
client.on('connection', socket => {
let text = ''
socket.on('data', chunk => { text += chunk.toString() })
socket.on('end', () => resolve(text))
socket.on('error', reject)
})
})
// Start discovery and await the message together so failures are observed.
const discovery = (async () => {
await host.join(topic, { server: true, client: false }).flushed()
client.join(topic, { server: false, client: true })
})()
const [message] = await Promise.all([received, discovery])
console.log(message)
} finally {
clearTimeout(timer)
await Promise.all([host.destroy(), client.destroy()])
await seed.destroy()
}
Run from this example directory:
node example.mjsExpected result
Hello topic
Example verification
The code shown here ran successfully in a local check on 19 October 2026. This verifies the small example, not production readiness, public-network reachability or every platform.
API essentials
- join(topic, { server, client }): announce, discover, or do both. Await the discovery handle's flushed() when announcement must finish first.
- on('connection', socket): handle a peer stream; attach error handling and define an application protocol.
- destroy(): close swarm activity during shutdown. Leaving a topic alone does not close existing connections.
Troubleshooting and limits
- Run one networking demo at a time: the local bootstrap uses UDP port 49777. Change it if that port is occupied.
- Discovery timeout: local UDP may be blocked. The example stops waiting after ten seconds and cleans up its swarms.
- A shared topic is not authorization. Use the P2P runtime's grants and invites for permissioned app services.
- For a real multi-process app, share the topic explicitly and persist identities. This random topic is only shared in memory.