---
title: "A 1.8-billion-relationship graph in 12 GB of memory: Semurg answers in 1.41 s, Neo4j and FalkorDB did not finish"
slug: a-graph-bigger-than-memory
date: 2026-10-20
author: Semurg
section: engineering
tags: [benchmarks, graph, neo4j, falkordb, bigger-than-memory, performance]
summary: SNAP's com-Friendster graph, 1.8 billion relationships, with every engine held to 12 GB of memory. Semurg answered the 4-hop query in 1.41 s and walked to 131,072 hops; Neo4j gave no answer and FalkorDB ran out of memory.
status: published
evidence:
  - bench:graph/exceeds_t2/server/neo4j@r11.118
  - bench:graph/exceeds_t2/server/falkordb@r11.118
  - bench:graph/exceeds_t4_h2/server/neo4j@r11.118
  - bench:graph/exceeds_t4_h4/server/neo4j@r11.118
  - bench:graph/exceeds_t4_h8/server/neo4j@r11.118
  - bench:graph/exceeds_t4_h16/server/neo4j@r11.118
  - bench:graph/exceeds_t4_h512/server/neo4j@r11.118
  - bench:graph/exceeds_t4_h131072/server/neo4j@r11.118
---
Most graph benchmarks use a graph that fits in memory. Real graphs outgrow it: a social network, a fraud graph, a knowledge graph
built from years of documents. Past that point the first question is not how fast a database answers, but whether it answers at
all. So we gave every engine the same graph, far larger than the memory it was allowed, and asked it the same questions we ask of
the graphs that fit.

## The result

The graph is SNAP's com-Friendster: 65.6 million people and 1.8 billion relationships, with every engine held to 12 GB of
memory[^1]. As a server, Semurg answered a 4-hop question about one person's network in 1.41 s, the median of repeated queries[^1].
Neo4j, given the same 12 GB, loaded the graph but had not answered that first 4-hop query when its time ran out after 2,345 s[^1].
FalkorDB, which keeps its whole graph in memory, ran out of its 12 GB while loading, before any question could be asked[^2].

The [benchmark page](/benchmark) shows each of these as Semurg's figure beside the other engine's outcome in words. There is no
"times faster" on these rows: an engine that does not finish has no time to divide by.

## Walking deeper

The same run walks outward from one person, one query per depth, from 2 hops all the way to 131,072 hops[^8]. Semurg answered
every depth. 2 hops took 8.45 ms[^3], 4 hops 1.69 s[^4] and 8 hops 5.85 s[^5]. From there the time barely moves: 6.67 s at
16 hops[^6], 6.70 s at 512 hops[^7] and 6.69 s at 131,072 hops[^8]. Friendster is a small world: within the first few steps a walk
reaches nearly everyone it can, so walking further adds almost nothing. Each depth is one query timed on its own, which is why the
4-hop walk and the 4-hop median above differ[^1][^4].

> Diagram walk-depth: Semurg's time for one walk at each depth on the bigger-than-memory graph: the bars grow from two hops to eight, then stay level all the way to the deepest walk.
>
> - Two hops: 0.008 s [^3]
> - Four hops: 1.694 s [^4]
> - Eight hops: 5.855 s [^5]
> - Sixteen hops: 6.666 s [^6]
> - Deepest walk: 6.692 s [^8]

Neither Neo4j nor FalkorDB has a walk result: neither got past the first question[^1][^2].

## How it was run

- **The same input for everyone:** the graph file exactly as SNAP publishes it, staged once on the server; each engine loads it
  with its own recommended bulk-load method.
- **Every engine held to the same memory:** each runs in Docker with every thread of the machine and both data disks, and a 12 GB
  memory limit that applies to Semurg too[^1].
- **A fixed time budget per engine:** an engine that has not answered when its time runs out is recorded as not finishing, with
  the reason, and the page says so in words instead of leaving a gap.

## What is not here yet

- ArcadeDB did not get a fair turn in this run: our kit counted a data-conversion step of its own against ArcadeDB's time. The
  mistake is fixed in the kit published with r11.119, and ArcadeDB is measured on the next bigger-than-memory run.
- ArangoDB and SurrealDB have no server result in this run; both are measured on the next one.
- The in-application column is not shown for this graph: Semurg's own in-application run was not measured this time, so there is
  nothing yet to set the other engines' outcomes beside.
- Load times for this graph go on the page with the next run.

## Check it yourself

The kit that ran this test is published with every release. Every figure, its spread and each engine's outcome, in its own words,
is on the [benchmark page](/benchmark), beside the in-memory results for the graphs that fit.
