Documentation

HTTP/JSON server

graphbuff-server serves a DatabaseManager over HTTP/JSON, so any language can run Cypher against graphbuff:

cargo run --release -p graphbuff-server                                  # in-memory, 127.0.0.1:7475
cargo run --release -p graphbuff-server -- --data ./data --persistent    # durable
cargo run --release -p graphbuff-server -- --bind 0.0.0.0:7475 --token s3cret
cargo run --release -p graphbuff-server -- --demo movies                 # start with the movies demo graph
Request Answer
GET /health {"status":"ok"} (never needs the token)
GET /db {"databases":[{"name","storage","default","nodes","relationships"}]}
POST /db/{name}/query runs {"query": "...", "params": {...}, "timeoutMs": 5000} against database name (params and timeoutMs optional)
POST /query the same, against the default database
POST /db/{name}/tx begins a transaction: 201 {"transaction":{"id","database","path","timeoutMs"}}
POST /db/{name}/tx/{id} runs {"query", "params", "timeoutMs"} in it; answers like a query
POST /db/{name}/tx/{id}/commit commits: {"committed":true}
DELETE /db/{name}/tx/{id} rolls back (cancelling a running statement): {"rolledBack":true}
/tx, /tx/{id}, /tx/{id}/commit the same, against the default database
POST /db/{name}/backup online backup into --backup-dir: {"backup": "name"}; admins only (details)
POST /db/{name}/restore creates the database from a backup: {"backup": "name", "overwrite": false}; admins only
POST /db/{name}/check consistency check of a persistent database: {"check":{"consistent","errors",...}}; admins only

A query returns {"columns":[...],"rows":[[...]],"stats":{"nodesCreated":1,...,"containsUpdates":true}}. A query request is its own transaction. Database commands (CREATE DATABASE, SHOW DATABASES, USE x MATCH ...) work through either query endpoint.

  • Transactions: the statements of an explicit transaction may come in separate requests, on any connection, and see each other's changes; other clients see none of them until the commit. While one is open, other writers on its database wait (including begin), readers do not. A statement that fails rolls the whole transaction back, and its error carries "rolledBack":true. A statement that does not parse, a database command, or USE of another database is rejected and the transaction stays open. A transaction that gets no request for --tx-timeout seconds (default 60) is rolled back; requests to a transaction that has ended answer 404 TransactionNotFound. Shutting the server down rolls back open transactions.

  • Timeouts: --query-timeout MS stops a query that runs longer (default: no limit); a request may ask for less with "timeoutMs". The limit also covers the wait for another writer, and the wait to begin a transaction. A query that runs out of time is rolled back and answers 408 Timeout; in a transaction the whole transaction rolls back. Rolling back a transaction (and shutting down) cancels the statement it is running, which then answers 409 Cancelled.

  • Values: JSON integers become Cypher INTEGERs and numbers with a fraction or exponent become FLOATs, in both directions (floats are always written with .0 or an exponent). NaN and infinities are returned as the strings "NaN", "Infinity", "-Infinity". Nodes, relationships and paths are objects with a "$type": {"$type":"node","id":0,"labels":["Person"],"properties":{...}}, {"$type":"relationship","id":0,"type":"KNOWS","start":0,"end":1,"properties":{...}}, {"$type":"path","nodes":[...],"relationships":[...]}.

  • Errors: {"error":{"code":"SyntaxError","message":"...","offset":9}} with status 400 (SyntaxError, SemanticError, TypeError, RuntimeError, Unsupported, BadRequest), 404 (DatabaseNotFound, TransactionNotFound), 408 (Timeout), 409 (ConstraintError, Cancelled), 401 (missing or wrong credentials), 403 (Forbidden: the user's roles do not allow the statement), 413 (body over 16 MiB, or TransactionTooLarge: a transaction past its database's size cap, rolled back), 500 (StorageError).

  • Security: the server listens on localhost by default. With --token (or the GRAPHBUFF_TOKEN environment variable) every request except /health needs Authorization: Bearer <token>; with --users FILE, clients log in as users (see Users and TLS). LOAD CSV is off unless --import-dir DIR is given; it then reads only files inside DIR.

  • Implementation (crates/server, standard library only, plus rustls with a TLS feature): one thread per connection (at most 256), HTTP/1.1 keep-alive, Content-Length or chunked bodies, Expect: 100-continue. Server::start embeds it in a Rust program.

From Java, examples/java/GraphbuffClient.java is a dependency-free client (Java 17+, java.net.http) with a runnable demo:

java examples/java/GraphbuffClient.java http://127.0.0.1:7475
var db = new GraphbuffClient("http://127.0.0.1:7475", null);   // or a token
db.query("CREATE DATABASE movies IF NOT EXISTS", null);
db.query("movies", "CREATE (:Person {name: $name, age: $age})", Map.of("name", "Ann", "age", 31));
var r = db.query("movies", "MATCH (p:Person) RETURN p.name AS name, p.age AS age", null);
String name = (String) r.get(0, "name");
long age = (Long) r.get(0, "age");          // INTEGER -> Long, FLOAT -> Double

With Jackson or Gson in the project, HttpClient plus your JSON library is all you need. Send {"query": ..., "params": ...} and read columns / rows.

Try it on your machine: one command starts the server with the movies graph. Needs Docker.

$ docker run --rm -p 127.0.0.1:7475:7475 -p 127.0.0.1:7687:7687 ghcr.io/janvencl/graphbuff --demo movies

Then follow Getting started.