The DHT Network
How do hundreds of independent servers with no central directory find each other, agree on where data lives, and route requests efficiently? Hashiverse uses a Kademlia distributed hash table — the same family of algorithm used by BitTorrent, IPFS, and Ethereum's peer discovery layer — adapted for a social network's access patterns.
The ring
Every entity in Hashiverse — servers, users, posts, hashtags — has a 256-bit identifier derived from its Blake3 hash. These IDs live on a ring: the address space wraps around at 2256. "Distance" between two IDs is the XOR of their bit patterns, a metric that gives the ring useful routing properties.
Each server maintains connections to other servers whose IDs are close to its own in XOR distance, plus connections at exponentially increasing distances (the Kademlia k-buckets). This structure means any server can route a query to the server nearest any target ID in O(log n) hops, where n is the number of servers in the network.
Source: kademlia.rs
Where data lives
A bucket of posts is stored on the servers whose IDs are nearest to the bucket's
location_id — a hash derived from the bucket type, the base ID (user, hashtag,
or post), and the time window. This means:
- A user's posts are stored on the servers nearest that user's ID in the ring.
- A hashtag's posts are stored near the hashtag's hash ID.
- As new servers join and leave, the nearest-neighbor set shifts, and healing propagates data to the new nearest servers.
There is no master index. No server knows where everything is. Every server knows where things near it are, and how to route toward things that are far away.
Load distribution
Popular hashtags would be a bottleneck if all posts for a hashtag landed on the same handful of servers indefinitely. Hashiverse distributes this load using time-epoch-based key rotation: the location ID for a hashtag bucket shifts over time, so different epochs land on different parts of the ring — different servers. All timeline location IDs rotate on a monthly cadence; but busier timelines automatically overflow into buckets of increasing granularity.
The bucket system is hierarchical: 1-month buckets subdivide into weekly, then daily, then 6-hour, hourly, 15-minute, 5-minute, and 1-minute buckets. Timeline loading traverses this hierarchy recursively — starting coarse and drilling into finer buckets only where content exists. A timeline with sparse activity loads cheaply; a dense timeline loads efficiently because each bucket can be fetched in parallel.
Source: buckets.rs,
recursive_bucket_visitor.rs
Transport abstraction
The protocol is transport-agnostic. The TransportFactory,
TransportServer, and TransportServerHandler traits in
hashiverse-lib/src/transport/ define the interface; implementations are
swapped without touching protocol logic:
- mem_transport: In-memory channels, used in tests. Allows spinning up complete multi-server topologies in a single process with no networking overhead.
- HttpsTransport / TcpTransport: Production implementations in
hashiverse-server/src/network/transport/, with HTTPS using auto-provisioned certificates via rcgen and instant-acme (Let's Encrypt). - WasmTransport: Browser HTTP transport via gloo-net, in
wasm_transport.rs.
The integration tests exploit this heavily: a test that verifies healing behavior, DHT routing, or post propagation can run entirely in memory with deterministic timing, no ports, and no cleanup.
Test-harness orchestration
The test-harness binary starts a primary server (for bootstrap) plus a configurable number of secondary servers
in a single process using Tokio's JoinSet, all sharing the same cancellation
token for graceful shutdown. The HashiverseServer orchestrator initializes
Kademlia, spawns transport handlers, and manages peer discovery.
Source: hashiverse-integration-tests/src/bin/test_harness.rs