Dgraph

Dgraph is a distributed, native graph database written in Go. Released as open-source in 2017, it stores graphs in a Pregel-style sharded layout with each predicate (edge type) potentially on a different node. Dgraph speaks GraphQL as its primary query language — a deliberate choice to give frontend engineers the same query syntax used in their REST replacement layer — and a more powerful internal language called DQL (Dgraph Query Language).

Key Features:

Dgraph vs. Neo4j vs. JanusGraph:

Use Cases:

4. Architecture

Dgraph Cluster Architecture Clients GraphQL / DQL over HTTP, gRPC Zero group membership, timestamps, shard moves Alpha group 1 predicates A.. Alpha group 2 predicates ..Z Badger LSM key-value store per Alpha Each group is a Raft replica set; data is sharded by predicate, not by node id.

A Dgraph cluster has two kinds of nodes. Zero nodes manage the cluster: they assign nodes to groups, hand out transaction timestamps and unique ids, and move predicate shards between groups to balance load. Alpha nodes store data and execute queries. Alphas are organized into groups, and each group is a Raft replica set, so a three-replica group tolerates one node failure. All data for one predicate lives in one group, which means a query that traverses a single edge type touches a single group rather than fanning out across the cluster.

5. Data Model

Data Model: Triples Stored as Posting Lists <0x1> name "Ana" subject predicate object <0x1> follows <0x2> edge as a predicate posting list key: predicate + subject

Internally everything is a triple: a subject node, a predicate, and either a literal value or another node. Dgraph stores, for each predicate and subject, a posting list of objects, keyed in the Badger store. Traversing follows from a node is a single key lookup that returns all neighbours. Indexes are declared per predicate in the schema, for example term, exact, trigram, or full-text indexes on strings, and must exist before you filter or sort on that predicate.

6. Worked Example

# DQL schema and data through the HTTP API (default Alpha port 8080)
curl -s localhost:8080/alter -d '
  name: string @index(term, exact) .
  follows: [uid] @reverse .
  age: int @index(int) .'

curl -s -H "Content-Type: application/rdf" "localhost:8080/mutate?commitNow=true" -d '
{ set {
  _:ana <name> "Ana" .  _:ana <age> "34" .
  _:bo  <name> "Bo"  .  _:bo  <age> "29" .
  _:ana <follows> _:bo .
}}'
# DQL query (shown with SQL highlighting): who does Ana follow, and who follows them?
{
  q(func: eq(name, "Ana")) {
    name
    follows @filter(ge(age, 18)) {
      name
      age
      ~follows { name }
    }
  }
}

The query starts from an indexed root function, walks the follows edge, filters on an indexed integer, and uses the reverse edge enabled by @reverse. The response is nested JSON shaped exactly like the query. With a GraphQL schema loaded, the same data can be served through an auto-generated GraphQL API.

7. When to Use Dgraph

Dgraph fits applications that need horizontal scale for graph traversals and want a GraphQL API without a separate resolver layer: social graphs, recommendation and knowledge graphs, and access-control graphs. It is less suitable when the workload is mostly tabular aggregation, where a relational or columnar database is simpler, or when a team already depends on Cypher tooling and the Neo4j ecosystem. Because data is sharded by predicate, a schema with a few very hot predicates can concentrate load on one group, so schema design affects scaling more than in node-partitioned systems.

Run a small proof of concept with realistic edge counts before committing, since traversal cost depends heavily on fan-out.

8. Pitfalls