GoraphDB Documentation

The high-performance, embeddable graph database for Go. Built for speed, simplicity, and scale.

Introduction#

GoraphDB is an embeddable graph database written in pure Go. It runs in-process with your application, eliminating network overhead and simplifying deployment. Built on top of bbolt (B+tree key-value store), it provides a robust foundation for graph data with full ACID transaction support.

Key features include:

  • Zero dependencies: specific compiled binary or simple library import.
  • Cypher support: Read/Write Cypher querying capability.
  • High Performance: Memory-mapped storage, caching, and concurrent query execution.
  • Replication: Built-in Raft consensus for single-leader high availability.

Installation#

Install GoraphDB as a library in your Go project:

bash
go get github.com/mstrYoda/goraphdb

Quick Start#

Here is a complete example showing how to open a database, add data, and query it.

go
package main

import (
    "fmt"
    "log"
    "context"

    graphdb "github.com/mstrYoda/goraphdb"
)

func main() {
    // Open (or create) a database.
    db, err := graphdb.Open("./my.db", graphdb.DefaultOptions())
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // Add nodes with arbitrary properties.
    alice, _ := db.AddNode(graphdb.Props{"name": "Alice", "age": 30})
    bob, _ := db.AddNode(graphdb.Props{"name": "Bob", "age": 25})

    // Add a directed labeled edge.
    db.AddEdge(alice, bob, "follows", graphdb.Props{"since": "2024"})

    // Cypher query.
    ctx := context.Background()
    res, _ := db.Cypher(ctx, `MATCH (a {name: "Alice"})-[:follows]->(b) RETURN b.name`)
    
    for _, row := range res.Rows {
        fmt.Println(row["b.name"]) // Bob
    }
}

Graph Data Model#

GoraphDB implements the Labeled Property Graph model. This means:

  • Nodes: The entities in the graph (e.g., Person, Movie). They can have labels and properties.
  • Edges: Directed relationships between nodes (e.g., FOLLOWS, WROTE). They have a type and can also have properties.
  • Properties: Key-value pairs stored on both nodes and edges.

Architecture#

GoraphDB is built as a layered system on top of a B+tree storage engine.

┌──────────────────────────────────────────────────────────────┐ │ Management UI │ │ React + TypeScript + Tailwind · cytoscape.js · CodeMirror │ ├──────────────────────────────────────────────────────────────┤ │ HTTP / JSON API │ │ /api/cypher · /api/nodes · /api/edges · /api/indexes │ ├──────────────────────────────────────────────────────────────┤ │ Replication Layer │ │ WAL · gRPC Log Shipping · Applier · Raft Election │ ├──────────────────────────────────────────────────────────────┤ │ Public API │ │ Node/Edge CRUD · Labels · Transactions (Begin/Commit) │ ├──────────────────────────────────────────────────────────────┤ │ Cypher Engine │ │ Lexer → Parser → AST → Executor (index-aware) │ ├──────────────────────────────────────────────────────────────┤ │ Shard Manager │ │ Hash-based routing · Cross-shard edge handling │ └──────────────────────────────────────────────────────────────┘

Transactions & ACID#

GoraphDB supports multi-statement atomic transactions with read-your-writes semantics. It uses MVCC (Multi-Version Concurrency Control) to allow lock-free readers to run concurrently with a single writer.

go
// Start a transaction
tx, err := db.Begin()

// Perform operations
alice, _ := tx.AddNode(graphdb.Props{"name": "Alice"})
bob, _ := tx.AddNode(graphdb.Props{"name": "Bob"})
tx.AddEdge(alice, bob, "follows", nil)

// Visible only inside this transaction until commit
node, _ := tx.GetNode(alice) 

// Commit all changes atomically
err = tx.Commit()
// or
err = tx.Rollback()

Cypher Query Language#

GoraphDB supports a broad subset of the Cypher query language, including `MATCH`, `CREATE`, `MERGE`, `SET`, `DELETE`, and `RETURN`.

Read Queries

go
// Match by property (uses index if available)
res, _ := db.Cypher(ctx, `MATCH (n {name: "Alice"}) RETURN n`)

// Pattern matching
res, _ = db.Cypher(ctx, `MATCH (a)-[:follows]->(b) RETURN b.name`)

// Variable length paths
res, _ = db.Cypher(ctx, `MATCH (a)-[:follows*1..3]->(b) RETURN b`)

Write Queries

go
// CREATE
db.Cypher(ctx, `CREATE (n:Person {name: "Alice", age: 30})`)

// MERGE (Upsert)
db.Cypher(ctx, `MERGE (n:Person {name: "Bob"}) ON CREATE SET n.created = timestamp()`)

Replication (Raft + WAL)#

GoraphDB offers distinct Leader and Follower roles for high availability.

  • Leader: Accepts all writes, appends to the Write-Ahead Log (WAL), and replicates to followers.
  • Follower: Read-only replicas that receive WAL streams via gRPC.
go
// Initialize as Leader
db, _ := graphdb.Open("./data", graphdb.Options{
    ShardCount: 4,
    EnableWAL:  true,
    Role:       "leader",
})

// Initialize as Follower
db, _ := graphdb.Open("./data-replica", graphdb.Options{
    ShardCount: 4,
    Role:       "follower",
})

Performance Optimizations#

A number of advanced techniques are employed to ensure low-latency and high-throughput.

Bloom Filters

A probabilistic data structure used to verify edge non-existence instantly without disk I/O.

LRU Types Cache

Byte-budgeted, sharded concurrent generic LRU cache for hot nodes.

Deployment#

GoraphDB can be deployed anywhere from a local laptop to a distributed Kubernetes cluster.

Local: Docker

The easiest way to try GoraphDB is via the official Docker image.

bash
docker run -d --name goraphdb   -p 7474:7474   -v $(pwd)/data:/data   mstryoda/goraphdb:latest

Local: Go Run

Standalone Mode

Run a single node instance directly from source.

bash
go run ./cmd/graphdb-ui/ -db ./data -addr :7474

Cluster Mode (3 Nodes)

Run a 3-node local cluster with Raft replication.

bash
# Node 1 (Leader)
go run ./cmd/graphdb-ui/ -db ./data1   -node-id node1 -raft-addr 127.0.0.1:9001 -grpc-addr 127.0.0.1:9101 -http-addr 127.0.0.1:7474   -bootstrap   -peers "node1@127.0.0.1:9001@127.0.0.1:9101@127.0.0.1:7474,node2@127.0.0.1:9002@127.0.0.1:9102@127.0.0.1:7475,node3@127.0.0.1:9003@127.0.0.1:9103@127.0.0.1:7476"   -addr 127.0.0.1:7474

# Node 2 (Follower)
go run ./cmd/graphdb-ui/ -db ./data2   -node-id node2 -raft-addr 127.0.0.1:9002 -grpc-addr 127.0.0.1:9102 -http-addr 127.0.0.1:7475   -bootstrap   -peers "node1@... (same peer list) ..."   -addr 127.0.0.1:7475

# Node 3 (Follower)
go run ./cmd/graphdb-ui/ -db ./data3   -node-id node3 -raft-addr 127.0.0.1:9003 -grpc-addr 127.0.0.1:9103 -http-addr 127.0.0.1:7476   -bootstrap   -peers "node1@... (same peer list) ..."   -addr 127.0.0.1:7476

Production: K8S Operator

For production environments, use the GoraphDB Kubernetes Operator to manage clusters. It handles provisioning, scaling, and automated failover.

1. Install the CRD & Operator

bash
kubectl apply -f https://raw.githubusercontent.com/mstrYoda/goraphdb/main/k8s/operator.yaml

2. Deploy a Cluster

yaml
apiVersion: goraphdb.io/v1alpha1
kind: GraphDBCluster
metadata:
  name: my-cluster
spec:
  replicas: 3
  version: "v1.2.0"
  storage:
    size: 10Gi
    class: standard
  resources:
    requests:
      cpu: "1000m"
      memory: "2Gi"

Golang SDK Reference#

The core API is simple and idiomatic.

go
// Create Node
id, _ := db.AddNode(graphdb.Props{"name": "Alice"})

// Create Edge
edgeID, _ := db.AddEdge(nodeA, nodeB, "follows", nil)

// Traversals (BFS)
db.BFS(id, 3, graphdb.Outgoing, nil, func(r *graphdb.TraversalResult) bool {
    fmt.Println(r.Node.Props)
    return true
})

// Shortest Path
path, err := db.ShortestPath(nodeA, nodeB)

HTTP API#

GoraphDB exposes a set of HTTP endpoints for health checks and executing Cypher over the wire (if enabled).

EndpointMethodDescription
/api/cypherPOSTExecute a Cypher query
/api/healthGETHealth check and role status
/api/clusterGETCluster topology info