OrbitDB: a peer-to-peer database built on IPFS and Merkle-CRDTs
Peer-to-Peer Databases for the Decentralized Web
At a glance
- What is it?
- OrbitDB is a serverless, eventually consistent database that stores data on IPFS and syncs it over Libp2p Pubsub. It fits local-first apps and multi-writer collaboration, not a drop-in replacement for a hosted SQL instance.
- Who is it for?
- Adopt OrbitDB when your application is local-first or peer-to-peer and you accept eventual consistency, a Helia instance you configure yourself, and a Node.js 22 or newer floor. Do not adopt it when you need a central query engine, server-side transactions, or a managed service.
- 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 138 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 September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What OrbitDB replaces, and for whom
OrbitDB is a serverless, distributed, peer-to-peer database. The README describes it as using IPFS as its data storage and Libp2p Pubsub to automatically sync databases with peers. There is no server process to deploy and no connection string to configure. Each participant runs a database locally and replicates with whoever else has joined the same database address.
The audience is narrow and specific. The README names p2p and decentralized apps, blockchain applications, and local-first web applications. If your application already has a backend that owns the data, OrbitDB adds replication machinery you do not need. The interesting case is when two or more parties need to write to the same dataset without one of them being the authority, and when the application should keep working while offline.
Four data models ship with it. events is an immutable append-only log with traversable history, which the README suggests for latest-N use cases or as a message queue. documents stores JSON documents indexed by a specified key, useful for search indices or version controlling documents. keyvalue is a plain key-value store. keyvalue-indexed is the same data indexed in a Level key-value database. All four are implemented on top of the OpLog, which the README describes as an immutable, cryptographically verifiable, operation-based CRDT, formalized in the Merkle-CRDTs paper.
How the OpLog and Merkle-CRDT layer actually work
The data flow has three layers. At the bottom, Helia provides the IPFS node. Libp2p, configured inside or alongside Helia, provides the transport and the pubsub channel. On top, OrbitDB keeps an OpLog per database.
An OpLog is a log of operations rather than of final states. Each write appends an operation, and the log is a Merkle DAG, so any peer can verify that a given operation belongs to the history it claims to belong to. Because the structure is a CRDT, two peers that have seen different operations can merge their logs without a coordinator deciding who wins. The README is explicit that the result is an eventually consistent database: replicas converge, but not at the moment of the write.
Database types are projections over that log. The events database exposes the log more or less directly. documents and keyvalue apply their own merge rules on top of the same operation history. That is why the README says you can extend OrbitDB with a custom data model and still inherit the properties of the underlying Merkle-CRDT. If you write a custom database, you are writing the reduction from operations to state, not a new replication protocol.
A database is identified by an address of the form /orbitdb/zdpuAkstgbTVGHQmMi5TC84auhJ8rL5qoaNEtXo2d5PHXs2To, shown in the README's usage example. Any peer that has that address can open the same database. The address is the sharing mechanism.
Installing @orbitdb/core and writing your first entry
The package is published as @orbitdb/core. The README's install line pulls in Helia as well, because OrbitDB does not bundle an IPFS node:
npm install @orbitdb/core heliapackage.json sets engines.node to >=22.0.0, so check your Node version before anything else. The package is ESM (type: module) and its main entry is src/index.js.
The README's usage example builds a Libp2p instance, wraps it in Helia, then creates the OrbitDB instance. Note the gossipsub option in that example, which the README comments is necessary to run a single peer:
import { createHelia } from 'helia'
import { createOrbitDB } from '@orbitdb/core'
import { gossipsub } from "@chainsafe/libp2p-gossipsub";
import { identify } from "@libp2p/identify";
import { createLibp2p } from 'libp2p'
const Libp2pOptions = {
services: {
pubsub: gossipsub({
// neccessary to run a single peer
allowPublishToZeroTopicPeers: true
}),
identify: identify()
}
}With that in place, opening a database and adding an entry looks like this. The README notes that open defaults to the events type, and prints the address so you can hand it to another peer:
const libp2p = await createLibp2p({ ...Libp2pOptions })
const ipfs = await createHelia({libp2p})
const orbitdb = await createOrbitDB({ ipfs })
const db = await orbitdb.open("hello")
console.log(db.address)
const hash = await db.add("world")
console.log(hash)To read the log back, the README iterates it and listens for peer updates. On a second peer, opening the same address is what starts replication:
db.events.on("update", async entry => {
console.log(entry)
const all = await db.all()
console.log(all)
})
for await (const record of db.iterator()) {
console.log(record)
}Cleanup is explicit in the README's example: await db.close(), then orbitdb.stop(), then ipfs.stop(). The README points to the @orbitdb/quickstart module for a faster path and for examples of configuring Helia for persistency and Libp2p for connecting to peers. That is where you should look next, because the snippet above uses an in-memory node.
Where OrbitDB is the wrong tool
The README calls OrbitDB eventually consistent, and that single adjective rules out a class of use cases. If two users must see the same counter value at the same instant, or if a write must fail when it violates a constraint that another concurrent write also violates, an eventually consistent CRDT is the wrong substrate. You would be building the coordination layer yourself on top of a system designed to avoid it.
Query capability is another boundary. The documents database indexes by a specified key, and keyvalue-indexed uses a Level database for indexing. There is no query planner, no joins, and no aggregation engine described in the README. Anything beyond key lookup and log traversal happens in your application code, over data you have already replicated locally.
Operationally, OrbitDB is not a managed service. You supply the Helia node, you decide its persistence configuration, and you decide which peers to connect to. The README's own usage example creates an in-memory IPFS node and says to see the quickstart module for persistency. A reader who copies that snippet into production will lose data on restart. That is not a defect in OrbitDB, but it is the most likely way to misuse it.
Finally, size. Every peer that opens a database replicates its operation log. The README describes events as useful for latest-N use cases, which hints at the pattern: if you only need the recent tail, the full log is still what gets replicated. For large datasets with many small updates, that is a cost you should measure before committing.
OrbitDB against GunDB, Peerbit and a Go implementation
The closest comparison in the JavaScript ecosystem is GunDB, which also targets decentralized, offline-capable applications. The difference in approach is the storage and identity layer. GunDB carries its own graph storage and peer discovery; OrbitDB delegates storage to IPFS through Helia and replication to Libp2p Pubsub, so your content addressing, peer identity and transport come from the libp2p stack rather than from the database. If you already run IPFS infrastructure, that is a reason to pick OrbitDB. If you do not, GunDB asks you to learn one system instead of two.
Peerbit is another decentralized database in the same space. The README does not discuss it, so a direct feature comparison is not something this article can make. What can be said from the README is that OrbitDB's design is explicitly tied to Merkle-CRDTs and to the OpLog as a shared substrate for all database types.
If JavaScript is not your runtime, the README names two other implementations. A Go implementation is developed and maintained by the Berty project at berty/go-orbit-db, and there is a Python HTTP client at orbitdb/py-orbit-db-http-client. The Python package is a client, not a full node, which matters if you expected to run a Python peer. OrbitDB's browser and Node.js support covers Linux, OS X and Windows, and the README also documents loading a distributed js file with a script tag, where OrbitDB is the global namespace.
Maintenance, the MIT licence, and what an upgrade costs
The repository is not archived, and its last push was on 2026-05-14. There are no release notes in the repository listing, so the changelog in CHANGELOG.md is the place to look for what changed between versions. The published package version in package.json is 4.0.0.
The licence is MIT, which is permissive and places few obligations on how you redistribute or host software that depends on it. This is not legal advice; read the LICENSE file in the repository if your organisation has specific requirements.
The upgrade cost is dominated by the peer dependencies rather than by OrbitDB itself. package.json pins ^9.2.5 for @ipld/dag-cbor, ^13.4.2 for multiformats, ^10.0.0 for level, and ^8.0.1 for p-queue, and its devDependencies track helia ^6.0.22 and libp2p packages at major versions that move independently. Because OrbitDB's storage is IPFS and its transport is Libp2p, a Helia or Libp2p major bump can require changes in your application even when OrbitDB's own API is unchanged. The Makefile shows the intended local loop: make test runs npm run test -- --exit, make build runs tests then npm run build, and make rebuild chains clean-dependencies and build. The build script itself runs build:docs, build:dist and build:debug, so a full build also regenerates ./docs/api.
Editorial conclusion
Adopt OrbitDB when your application is local-first or peer-to-peer and you accept eventual consistency, a Helia instance you configure yourself, and a Node.js 22 or newer floor. Do not adopt it when you need a central query engine, server-side transactions, or a managed service. Before committing, verify what your own Helia and Libp2p configuration does for persistence, and read docs/ACCESS_CONTROLLERS.md to see whether the write access model matches your threat model.
Frequently asked questions
What is the difference between a centralized and decentralized database, in OrbitDB's case?
A centralized database has one authority that orders writes and answers queries. OrbitDB has no server process: the README describes it as serverless and peer-to-peer, with IPFS as storage and Libp2p Pubsub syncing databases between peers, and it is eventually consistent rather than immediately consistent.
Is OrbitDB a blockchain database?
The README lists blockchain applications as one use case, but OrbitDB is not a chain. It is an operation-based CRDT: writes are appended to a Merkle-CRDT OpLog, and the README says all database types are implemented on top of that OpLog.
How do I install OrbitDB and open a database?
Install @orbitdb/core together with helia, create a Libp2p instance and a Helia instance, then call createOrbitDB({ ipfs }) and orbitdb.open("hello"). The README notes that open defaults to the events database type and that the resulting address can be used on another peer to open the same database.
Which Node.js version does OrbitDB require?
package.json sets engines.node to >=22.0.0, so Node.js 22 or newer is required. The package is ESM, with type set to module and src/index.js as its main entry.
Are there OrbitDB implementations in other languages?
The README names a Go implementation maintained by the Berty project at berty/go-orbit-db, and a Python HTTP client at orbitdb/py-orbit-db-http-client. The Python package is a client rather than a full node.
Official sources
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.
[](https://hysenlabs.com/projects/orbitdb-orbitdb)