Skip to main content
A key-value store for multi-dimensional documents, built on CRDTs, with an efficient synchronization protocol. iroh-docs provides a protocol handler for the iroh networking stack, enabling storage and synchronization of documents over peer-to-peer connections.

When would I use this?

You would use iroh-docs when you need a distributed key-value store that can handle concurrent updates from multiple peers, ensuring eventual consistency without conflicts. This is particularly useful for collaborative applications, distributed configuration management, and any scenario where data needs to be shared and synchronized across multiple devices or users.

Installation

cargo add iroh-docs

Example

use iroh::{protocol::Router, Endpoint};
use iroh_blobs::{BlobsProtocol, store::mem::MemStore, ALPN as BLOBS_ALPN};
use iroh_docs::{protocol::Docs, ALPN as DOCS_ALPN};
use iroh_gossip::{net::Gossip, ALPN as GOSSIP_ALPN};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // create an iroh endpoint that includes the standard discovery mechanisms
    // we've built at number0
    let endpoint = Endpoint::builder().bind().await?;

    // build the gossip protocol
    let gossip = Gossip::builder().spawn(endpoint.clone());

    // build the docs protocol
    // use Docs::persistent to use local storage
    let docs = Docs::memory()
        .spawn(endpoint.clone(), (*blobs).clone(), gossip.clone())
        .await?;

    // create a router builder, we will add the
    // protocols to this builder and then spawn
    // the router
    let builder = Router::builder(endpoint.clone());

    // setup router
    let _router = builder
        .accept(GOSSIP_ALPN, gossip)
        .accept(DOCS_ALPN, docs)
        .spawn();

    // do fun stuff with docs!
    Ok(())
}

How it works

The crate operates on Replicas. A replica contains an unlimited number of Entries. Each entry is identified by a key, its author, and the replica’s namespace. Its value is the 32-byte BLAKE3 hash of the entry’s content data, the size of this content data, and a timestamp. The content data itself is not stored or transferred through a replica. Range-based set reconciliation is a simple approach to efficiently compute the union of two sets over a network, based on recursively partitioning the sets and comparing fingerprints of the partitions to probabilistically detect whether a partition requires further work. The crate exposes a generic storage interface with in-memory and persistent file-based implementations. The latter makes use of [redb], an embedded key-value store, and persists the whole store with all replicas to a single file.