MetaLoom // Graph

A native-code backed graph database for Java, built on the Foreign Function and Memory API.

It stores nodes, relationships and attributes in compact, purpose-built binary files, optimised for SSD. The defining design constraint:

An element id decodes arithmetically into the exact file and byte offset of its record. Reading an element by id costs zero index probes and zero extra seeks.

No lookup. No probe. No seek beyond the one the read itself performs:

long byteOffset = dataStart(kind) + (long) slot(id) * stride(kind);

What it is

Durability

A write-ahead log. Every commit is fsynced before it touches a data file, so uncommitted data cannot reach disk and recovery is a single redo pass.

Query language

An openCypher subset that reads and writes, in its own module, plus a single-jar server and a React and D3 browser.

Transactions

begin / commit / rollback, plus auto-commit for single operations.

Isolation

One writer at a time; many concurrent readers. A reader gets MVCC snapshot isolation — a view fixed at one instant across many reads, while the writer keeps committing. Reads take no lock and scale to 10x at 32 threads. No concurrent writers.

Indexes

Label and property B+trees, declared composite indexes, unique constraints, and an HNSW index for nearest-neighbour search over vector properties.

Space reclamation

reclaim() punches all-free pages and breaks no ids. compact() relocates records to close holes within pages, rewrites every internal reference, and pulls the high water marks down.

Native layer

Rust via FFM. io_uring is 12.4x over a pread loop on 64 scattered reads — the one capability the JVM cannot approach.

Operations

Prometheus metrics, a slow query log, container images and a Helm chart, and an MCP server so an agent can query the graph.

What it is not

Stated plainly, because a database page that implies capabilities the system lacks is a liability.

  • No concurrent writers. Writers serialise on one lock. That is a property of the storage engine, not a configuration, and it is why the Helm chart refuses more than one replica.

  • No backup mechanism. A cold copy of a stopped store is the only correct procedure today.

  • No authentication on any port. Not the HTTP port, not the binary port, not the monitoring port.

  • No OPTIONAL MATCH, and several other openCypher constructs — each refused by name at parse time rather than silently doing something else.

  • No repair tool for a store that fails verify.

At scale

Ten million nodes and twenty million random relationships load in 11 to 25 minutes and occupy 6.1 GiB. Reopening the finished store takes 1 ms; nodeLabel runs at 4.2M/s over it and neighbours at 1.1M/s.

The load figure is a range because it was measured four times with the same command and the edge phase varied 2.5x across the runs while the resulting store stayed identical to the byte. The benchmarks page has every run and what is known about the spread.

Where to go next

Architecture

Ids, segments, records, and how the address function works

Query language

The openCypher subset, and what is deliberately not in it

Browser

The built-in Cypher editor and graph view

API and wire protocol

The embedded Java API and the binary streaming port

Operations

Sizing, tuning, configuration, the slow query log, security posture

Metrics

The Prometheus catalogue and the alert rules it implies

MCP server

Letting an AI client query the graph

Deployment

Container images and the Helm chart

Benchmarks

Measured numbers, with their caveats