# Hyperdrive: distributed file storage over Hyperswarm with versioning and peer-to-peer replication

> Hyperdrive is a distributed file system from Holepunch that stores files under path-based keys, replicates in real time over Hyperswarm, and tracks every write as a versioned entry. It requires Corestore and is built on Hyperbee and Hyperblobs, which are listed as production dependencies.

**holepunchto/hyperdrive** — Hyperdrive is a secure, real time distributed file system

- Repository: https://github.com/holepunchto/hyperdrive
- Stars: 2,023 · Forks: 137
- Language: JavaScript
- License: Apache-2.0
- Published: 2026-10-11 · Updated: 2026-10-11 · Language: en
- Canonical page: https://hysenlabs.com/projects/holepunchto-hyperdrive

## Distributed file storage with a path-based API: what Hyperdrive stores and who needs it

Hyperdrive stores files under path keys and replicates them across peers in real time. Write operations are asynchronous: put() writes a buffer to a path, get() retrieves it, and del() removes it. All reads and writes go through a JavaScript API; there is no mount point and no POSIX interface.

A drive is identified by a public key. Any peer that knows a drive's public key and connects through Hyperswarm can replicate its contents without a central server. drive.discoveryKey is the hash of that public key and is the recommended topic to use when advertising the drive over Hyperswarm. drive.version counts the total number of modifications, making it usable as a version identifier for change detection.

Hyperdrive is part of the Holepunch building-block stack. Full API documentation is at docs.pears.com, not in the README, which covers only the core methods.

## Hyperbee for file structure and Hyperblobs for content: the 2-Hypercore storage model

Internally, Hyperdrive uses 2 Hypercores. The file structure (path-to-entry mapping) lives in a Hyperbee B-tree, accessible through the drive.db property. A separate Hypercore holds the blobs associated with each entry; its public key is the drive.contentKey property.

Each entry returned by drive.entry() carries a blob field with 4 numeric offsets: blockOffset, blockLength, byteOffset and byteLength. Those offsets identify the blob's position in the Hyperblobs instance. The entry also includes executable and linkname fields for file type and symlink targets, and a metadata field that is null unless explicitly set.

drive.supportsMetadata is documented as always true. drive.writable is true when the caller can write or delete data in that drive. drive.readable becomes false after drive.close() is called. drive.id is the z-base-32 encoding of the public key, the string identifier for the drive.

## Installing Hyperdrive and writing a first file: put, get and the Corestore setup

Install the package with npm:

```sh
npm install hyperdrive
```

Corestore is in hyperdrive's development dependencies, not its production dependencies. Install it separately before running the usage example. Create a store and a drive:

```js
const Hyperdrive = require('hyperdrive')
const Corestore = require('corestore')

const store = new Corestore('./storage')
const drive = new Hyperdrive(store)

await drive.put('/blob.txt', Buffer.from('example'))
await drive.put('/images/logo.png', Buffer.from('..'))
await drive.put('/images/old-logo.png', Buffer.from('..'))

const buffer = await drive.get('/blob.txt')
console.log(buffer) // => <Buffer ..> "example"

const entry = await drive.entry('/blob.txt')
console.log(entry) // => { seq, key, value: { executable, linkname, blob, metadata } }

await drive.del('/images/old-logo.png')
```

drive.put(path, buffer) creates a file at the given path. drive.get(path) returns the buffer or null if no blob exists at that path. drive.entry(path) returns the full entry object with the blob offsets and metadata, or null when the path does not exist. drive.del(path) removes the file from the drive.

## drive.clear() keeps the file structure reference but removes the blob: exists() and get() disagree

drive.clear(path) removes the blob from storage to free up space while leaving the file structure reference in place. The API documentation for drive.get(path) states that it returns null if no blob exists. After drive.clear(path), the blob is gone, so drive.get(path) returns null for that path. At the same time, drive.exists(path) checks whether the entry at the path exists, and the entry is kept by drive.clear(), so drive.exists(path) returns true. A path can exist in the drive structure while its content is unavailable, because clear() and del() are different operations.

drive.del(path) removes both the blob and the file structure entry, so drive.exists(path) returns false after a del. drive.clearAll() extends the clear pattern to all blobs at once: all blob storage is freed but every file structure entry is kept.

drive.truncate(version) rolls the drive back to a previous version, removing both the file structure references and the blobs added after that point. drive.purge() is the most destructive call: it wipes both the db and blobs cores from storage entirely.

## Atomic batch mutations, drive.mirror() and the list, readdir and entries streams

drive.batch() returns a batch object with the same interface as Hyperdrive. Mutations applied to the batch are not committed until batch.flush() is called, which writes them to the underlying drive atomically. Operations that must be consistent across multiple paths go through a batch.

drive.mirror(out) copies the current drive into another drive instance and returns a MirrorDrive object. Calling await mirror.done() waits for the mirror to finish. The method signature accepts options passed through to the MirrorDrive constructor.

drive.list(folder) returns a stream of all entries under paths prefixed with the given folder. The recursive option controls whether subdirectories are descended into; the ignore option accepts a string or array of names to exclude. drive.readdir(folder) returns a stream of subpaths rather than full entry objects, which is closer to a traditional directory listing. drive.entries() accepts a range argument and returns a read stream of entries, using the same options as Hyperbee's createReadStream.

## drive.ready(), symlink depth limits and the compare() return values

drive.ready() must be awaited before reading synchronous properties like drive.discoveryKey, unless a prior async call to the drive has already completed the internal setup. Calling drive.put() or drive.get() before drive.ready() is safe; those calls trigger the same initialization.

Symlinks are created with drive.symlink(path, linkname). If a blob entry exists at the target path, it is overwritten by the symlink: drive.get(key) returns null for that path, while drive.entry(key) returns the entry with the symlink information. The follow option on drive.entry() controls whether symlinks are followed automatically, with a maximum of 16 levels before the call throws an error.

drive.compare(entryA, entryB) returns 0 if the entries are the same, 1 if entryA is older than entryB, and -1 if entryB is older. A return value of 1 means entryA is the older entry, not the newer one: the sign is the opposite of what a positive return means in a typical comparison.

## When local file storage is the right choice and Hyperdrive adds unnecessary complexity

Hyperdrive is not a good fit for applications that store files only on the local machine and never need to share them with other peers. Using Node's built-in fs module for a local file store avoids the Corestore dependency, the Hyperbee and Hyperblobs layers, and the public-key identity model entirely. When there is no peer-to-peer replication requirement, those layers add setup cost without a corresponding benefit.

Applications that need only a persistent key-value store for binary data without the path-and-directory model should also evaluate alternatives like a local SQLite database or a direct Hypercore, which is a lower-level component that hyperdrive itself builds on.

Hyperdrive is licensed under Apache-2.0; the last push was on 2026-09-17 and the repository is not archived. The package.json imports section maps fs, path and events to bare-specific alternatives, which means Hyperdrive is designed to run in both the Node.js runtime and the Bare runtime used in Holepunch applications.

## Conclusion

Hyperdrive suits peer-to-peer applications that need to replicate files in real time over Hyperswarm using a versioned, content-addressed store. It is not a fit for purely local file storage, where the Corestore dependency and the absence of POSIX semantics add complexity without benefit. Before building on it, call drive.ready() before reading synchronous properties like discoveryKey, note that drive.clear(path) removes blob content while leaving the entry intact so drive.get(path) returns null while drive.exists(path) stays true, and check docs.pears.com for the full API since the README documents only the core methods.

## FAQ

### What is Hyperdrive in the Holepunch ecosystem?

Hyperdrive is a distributed file system from Holepunch that stores files under path-based keys and replicates them in real time. It is built on Hyperbee for the file structure and Hyperblobs for blob content, both of which sit on top of Hypercore. Full API documentation is at docs.pears.com.

### How do I install Hyperdrive?

Run npm install hyperdrive. Corestore is required to create a store instance but is not in hyperdrive's production dependencies, so it must be installed separately with npm install corestore.

### What does drive.clear() do in Hyperdrive?

drive.clear(path) deletes the blob from storage to free up space but keeps the file structure reference. After a clear, drive.exists(path) returns true but drive.get(path) returns null because the blob no longer exists. To remove both the blob and the entry, use drive.del(path) instead.

### How does Hyperdrive versioning work?

drive.version is a number that counts the total modifications made to the drive, used as a version identifier for change detection. drive.truncate(version) rolls the drive back to a previous version, removing both the file structure references and the blobs added after that version.

### What is drive.discoveryKey in Hyperdrive?

drive.discoveryKey is the hash of the public key of the Hypercore backing the drive. It can be used as a topic to announce and find the drive over Hyperswarm. Call drive.ready() before accessing drive.discoveryKey unless another async API call has already completed.

## Sources

- [holepunchto/hyperdrive on GitHub](https://github.com/holepunchto/hyperdrive)
- [Issues](https://github.com/holepunchto/hyperdrive/issues)
- [License: Apache-2.0](https://github.com/holepunchto/hyperdrive/blob/main/LICENSE)
- [README](https://github.com/holepunchto/hyperdrive/blob/main/README.md)
- [Releases](https://github.com/holepunchto/hyperdrive/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/holepunchto-hyperdrive
