Skip to content

Crystal Graph Engine

Crystal is a lightweight, extendable, lightning-fast graph engine written in Go.

It is a property graph database designed for investigation and intelligence mapping (in the spirit of Maltego) and for narrative design (in the spirit of Articy Draft). The core engine has zero external dependencies and ships as a single binary.

Licensed under Apache 2.0 with Commons Clause.

Three ways to run it

Crystal exposes the same storage engine through three interfaces — a REST server, a CLI client, and an embeddable Go library.

Authentication is on by default

Crystal refuses to start with authentication enabled and no tokens configured. This is deliberate: the alternative is a graph database listening on 0.0.0.0 that anyone with network reach can read, rewrite or delete. Generate a token first, or set auth.enabled: false explicitly.

Docker

export CRYSTAL_AUTH_TOKEN=$(openssl rand -hex 32)
docker compose up -d

The API is then available at http://localhost:7540.

From source

go build -o crystal ./cmd/crystal
export CRYSTAL_AUTH_TOKEN=$(openssl rand -hex 32)
./crystal --data-dir ./data --port 7540

CLI

go build -o crystal-cli ./cmd/crystal-cli
export CRYSTAL_URL=http://localhost:7540
export CRYSTAL_TOKEN=$CRYSTAL_AUTH_TOKEN

crystal-cli vertex create Person name=Alice age:=30
crystal-cli vertex create Server ip=10.0.0.1
crystal-cli edge create $ALICE_ID $SERVER_ID accessed port:=443
crystal-cli bfs $ALICE_ID --depth 3
crystal-cli export graph.json

As a library

import "crystal/pkg/crystal"

db, err := crystal.Open(crystal.Options{
    StorageType: "disk",
    DataDir:     "./mydata",
})
defer db.Close()

ctx := context.Background()

person, _ := db.AddVertex(ctx, "Person", crystal.Properties{"name": "Alice"})
server, _ := db.AddVertex(ctx, "Server", crystal.Properties{"ip": "10.0.0.1"})
db.AddEdge(ctx, person.ID, server.ID, "accessed", crystal.Properties{"port": 443})

Every operation that can do unbounded work takes a context.Context, so a cancelled request stops the work it started instead of running to completion for a caller that has gone away.

Know before you deploy

Crystal is RAM-resident: the whole graph lives in memory, and disk provides durability rather than capacity. There is no paging and no lazy loading, so the maximum dataset is bounded by RAM, not by disk.

Measured at the benchmark's property density, that is 745 bytes per vertex and 626 bytes per edge, plus roughly 2× for garbage-collector headroom — about 1M vertices / 10M edges on a 16 GB host.

This is a deliberate decision with recorded reasoning and revisit conditions: see ADR 0001 — Storage model.

To scale past one machine, shard by graph and add read replicas — see Cluster Mode.

Documentation