Library / SDK
holepunchto/hyperswarm avatar
holepunchto/hyperswarm

hyperswarm: Topic-Based Peer Discovery and Noise Connections

A distributed networking stack for connecting peers.

1,339 stars117 forksJavaScriptMIT

At a glance

What is it?
hyperswarm is a JavaScript networking layer for finding peers by a shared 32-byte topic and exchanging data over Noise-encrypted streams. It suits applications that need peer discovery without implementing a DHT directly, but it does not define application protocols or persistence.
Who is it for?
Adopt hyperswarm when the application already uses JavaScript and needs topic-based discovery, reconnect behavior, and encrypted peer streams through hyperdht. Do not choose it as a complete application transport, persistence layer, or general-purpose firewall.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 31 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The Peer-Networking Gap hyperswarm Addresses

hyperswarm solves a specific part of peer-to-peer applications: locating other participants associated with the same 32-byte topic, connecting to them, and maintaining discovery. It is aimed at JavaScript developers who need this connection layer for another protocol or application. The package does not present itself as a storage engine, RPC framework, message schema, or complete distributed application runtime. Applications remain responsible for deciding what peers exchange and how they interpret it.

The central identifier is a topic represented by a 32-byte Buffer. Peers that join the same topic can discover each other through the underlying DHT. This model is narrower than general Internet host discovery because callers must already agree on the topic value and the rules used to derive it. A human-readable label by itself is not enough for the documented API.

hyperswarm also supports direct connections through `joinPeer(noisePublicKey)`. That path is useful when an application already knows a peer's 32-byte Noise public key and does not need topic lookup. Discovery attempts and direct connections both have lifecycle methods for starting and stopping future connection activity.

DHT Discovery, Client Roles, and Server Roles

The repository identifies `hyperdht` as the DHT implementation and exposes the instance as `swarm.dht` for lower-level control. A default `HyperDht` instance is created when the caller does not supply one through the `dht` option. That dependency is important: hyperswarm supplies the high-level peer API, while DHT querying, announcements, and related network operations belong to `hyperdht`.

A topic can be joined in three practical configurations through the `server`, `client`, and `limit` options. In server mode, the swarm announces its keypair to the DHT and accepts incoming client connections. In client mode, it queries for announced servers and eagerly connects to them. Both options default to `true`, so calling `join(topic)` without options makes the peer both discoverable and actively discovery-enabled for that topic.

The distinction affects the connection metadata. An incoming server connection is not associated with a particular topic because the server learns that a peer connected without receiving topic-specific information through that event. A client connection is associated with the topic, represented by `info.topics` in the `connection` event. This asymmetry matters to application code that routes requests or authorizes actions by topic.

The `limit` option caps the maximum number of peers connected through a topic discovery operation and defaults to `Infinity`. That default favors reach, but an application needs its own connection budget if many participants can discover the same topic. The constructor also provides `maxPeers`, while `firewall` can synchronously reject a remote public key. Without a firewall callback, the documented default allows all connections.

Noise Streams and Connection State

Each new peer produces a `connection` event with a Duplex `socket` and a `peerInfo` object. The documentation identifies the socket as end-to-end Noise-encrypted. Hyperswarm does not replace the stream with a request-response interface, so sending application messages means writing to the socket and parsing the resulting stream according to the application's protocol.

The class exposes several state surfaces. `swarm.connections` is a set of active client and server connections, `swarm.peers` maps connected peers by Noise public key hex string to `PeerInfo` objects, and `swarm.connecting` reports the number of connections in progress. An `update` event is emitted when internal values change. The README says this can include changes to `swarm.connecting` and `swarm.connections`, making the event relevant to an interface that displays network state.

Peer lifecycle is not tied to a single topic. Calling `await swarm.leave(topic)` stops announcing or searching for that topic, but it does not close existing connections. Likewise, `swarm.leavePeer(noisePublicKey)` stops attempts to establish a direct connection but leaves an existing direct connection open. This separation is useful when discovery can stop while data transfer continues, but it requires explicit connection management rather than assuming that leaving a topic tears down its network resources.

A `ban` event reports a banned peer and an error such as a firewall rejection. The excerpt does not document the full banning and unbanning API, so applications should not assume more event and policy controls than the listed surface provides.

Installing hyperswarm and Joining a Discovery Topic

The README gives `npm install hyperswarm` as the installation step. The package identifies itself as `hyperswarm` in `package.json`, uses CommonJS in the documented example, and declares an MIT license. A new JavaScript project can install it with the following command.

bash
npm install hyperswarm

The documented usage requires constructing a swarm, attaching a connection handler, and joining with a topic that is exactly 32 bytes. The README provides this example.

js
const Hyperswarm = require('hyperswarm')

const swarm = new Hyperswarm()

swarm1.on('connection', (conn) => {
  conn.write('this is a server connection')
  conn.end()
})

const discoveryKey = Buffer.alloc(32).fill('hello world')

swarm2.join(discoveryKey, { server: true, client: true })

The installation command is complete, but the pasted usage example references `swarm1` and `swarm2` without showing their construction. As written, it assumes those variables already exist, so a first-time reader should resolve that omission before using the example. The call to `Buffer.alloc(32).fill('hello world')` produces the required 32-byte topic. The handler writes a short message and ends that stream.

For real peer discovery, separate processes or peers must use the same 32-byte value and compatible roles. `swarm2.join(discoveryKey, { server: true, client: true })` asks that peer to announce itself and search for servers. Calling `swarm.flush()` waits for pending announcements and queued discovered peers, but the README describes it as swarm-wide and potentially slow. Normally, connection handlers receive peers as their connections open.

Direct Peers, Suspension, and Operational Boundaries

Known peers can be connected without topic discovery by passing a 32-byte Noise public key to `swarm.joinPeer(noisePublicKey)`. According to the documentation, Hyperswarm continues attempting reconnection if a direct peer connection fails. `leavePeer(noisePublicKey)` stops that process, although it does not destroy a connection that is already open.

Applications that pause with the JavaScript runtime can call `await swarm.suspend({ log: () => {} })`. This disconnects peers, suspends server listening, and stops new discovery. `await swarm.resume({ log: () => {} })` refreshes discovery, reannounces servers to the DHT, and reconnects peers. The optional `log` argument defaults to a no-op function.

These lifecycle methods are more useful than treating a suspended process as a continuously active peer, but the README does not specify how pending application data is migrated or reconciled after suspension. Because suspension disconnects peers, stream state and incomplete messages remain application concerns.

There is another boundary around discovery flushing. `swarm.flush()` waits for all pending DHT operations and connections across the swarm, not only for one topic. For a narrowly scoped test, `discovery.flushed()` is the topic-specific server announcement check. The latter applies only in server mode. These differences matter in tests and startup sequences because the swarm-wide call can wait on unrelated topic activity.

The package also supports deterministic identity through a 32-byte `seed` option. That option generates a keypair from the supplied seed, while `keyPair` allows a Noise keypair to be supplied directly. Persistence and protection of identity material are not documented here, so callers must account for those concerns in their own application.

Maintenance Signals and the Alternative of Lower-Level Networking

The repository is not archived. Its last push was on 2026-09-22, and releases v4.17.2 and v4.17.1 were published on 2026-09-22 and 2026-09-08. Those facts indicate recent project activity, but they do not establish API stability for every application. Upgrade work is easier to assess through the semantic version in `package.json`, currently 4.17.2, and through the dependency ranges listed there.

The package is distributed under the MIT license. That identifier permits reuse and modification under the license's terms, but this article does not interpret the license text or provide legal advice. The published package includes `index.js` and `lib/**.js`, while tests and development utilities remain repository concerns.

A real alternative is to use `hyperdht` directly. Hyperswarm wraps DHT discovery with topic-oriented client and server behavior, peer reconnection management, connection state, Noise streams, and higher-level events. `hyperdht` is the lower-level choice for code that needs DHT control without that abstraction. The trade-off is that moving down to `hyperdht` means taking responsibility for more connection behavior that `swarm.join`, `PeerDiscovery`, and the swarm events otherwise consolidate.

Hyperswarm is the wrong tool for an application that only needs a fixed list of hosts, because its documented focus is peer discovery by topic or direct Noise key. It is also incomplete as a protocol suite. It supplies encrypted streams but does not define message framing, request semantics, persistence, topic authorization, or data synchronization.

Editorial conclusion

Adopt hyperswarm when the application already uses JavaScript and needs topic-based discovery, reconnect behavior, and encrypted peer streams through hyperdht. Do not choose it as a complete application transport, persistence layer, or general-purpose firewall. Before adoption, verify your topic derivation, peer limits, client and server roles, shutdown path, and how existing connections behave when a topic is left.

Frequently asked questions

How do I install hyperswarm?

Run `npm install hyperswarm`. The documented example loads it with `require('hyperswarm')` and creates an instance with `new Hyperswarm()`.

What does hyperswarm use for peer discovery?

Hyperswarm uses a 32-byte topic with its `hyperdht` dependency. Server peers announce a topic to the DHT, while client peers query it and connect to discovered servers.

Does leaving a hyperswarm topic close existing peer connections?

No. `await swarm.leave(topic)` stops announcing or searching for the topic, but the documentation states that it does not close existing connections.

What does a hyperswarm connection provide?

The `connection` event provides a Duplex stream encrypted with Noise and a `peerInfo` object. Hyperswarm does not impose an application-level request or response protocol on that stream.

Can hyperswarm connect directly to a known peer?

Yes. Pass the peer's 32-byte Noise public key to `swarm.joinPeer(noisePublicKey)`. The documentation states that direct connection attempts are reestablished after failures.

Official sources

  1. holepunchto/hyperswarm on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/holepunchto-hyperswarm.svg)](https://hysenlabs.com/projects/holepunchto-hyperswarm)

Was this useful?