---
title: "Loading a 117.2-million-relationship graph: Semurg 6.0 to 70.3 times faster than FalkorDB, ArcadeDB and SurrealDB"
slug: loading-a-117-million-relationship-graph
date: 2026-10-20
author: Semurg
section: engineering
tags: [benchmarks, graph, falkordb, arcadedb, surrealdb, ingest, performance]
summary: Every engine loaded the same 117.2 million relationships repeatedly, on one server, and we publish the median. Semurg loads the graph 6.0 to 70.3 times faster than FalkorDB, ArcadeDB and SurrealDB.
status: published
evidence:
  - bench:graph/t1/server/falkordb@r11.118
  - bench:graph/t1/server/arcadedb@r11.118
  - bench:graph/t1/server/surrealdb@r11.118
  - bench:graph/t2/server/arcadedb@r11.118
---
The first thing anyone does with a graph database is put a graph into it. A benchmark that only times queries leaves out the step
that decides whether a team can reload its data every night or has to plan a weekend around it. Until now our graph results showed
"Results pending" for every load: each engine had been loaded once, and one load is not a measurement. In our latest run every engine
loaded the same graph repeatedly, from the same file, on the same server, and the benchmark page publishes the median.

## The result

The graph is SNAP's com-Orkut social network: 117.2 million relationships between 3.07 million people[^4]. As a server, Semurg
loaded it in 23.6 s[^1]. FalkorDB took 140.7 s[^1], ArcadeDB 290.1 s[^2] and SurrealDB 1,656.8 s[^3], which is 6.0, 12.3 and 70.3 times
as long as Semurg[^1][^2][^3].

> Diagram load-server: Time to load the whole social graph, as a server: Semurg's bar is the shortest, FalkorDB's and ArcadeDB's are several times longer, and SurrealDB's runs far to the right.
>
> - Semurg: 23.569 s [^1]
> - FalkorDB: 140.676 s [^1]
> - ArcadeDB: 290.117 s [^2]
> - SurrealDB: 1,656.756 s [^3]

## How the load was timed

- **The same input for everyone:** the graph file exactly as SNAP publishes it, staged once on the server; each engine read it with
  its own recommended bulk-load method, sized by its own tooling.
- **Every engine maxed:** each ran in Docker with every thread of the machine and both data disks, one engine at a time.
- **A load is the whole load:** the clock runs from an empty store until the engine says the whole graph is in, and the load is
  then checked by asking the same 4-hop question every engine must answer identically[^4].
- **Repeated, then the median:** each load starts again from an empty store; the page shows the median and the spread.

## What is not here yet

- Neo4j's and ArangoDB's load times are measured but not shown: for those two, our kit's timed load still includes a step of our own,
  so the figure would not be the engine's alone. They appear when the kit times their load by itself.
- FalkorDBLite's results are held for this run because of a counting mistake in our own kit, fixed in the kit published with this
  release; it is re-measured on the next run.
- The in-application load column is held for every engine in this run: Semurg's own load in that column went through its network
  connection, so it was not an in-application load.

## Bigger than memory next

This graph fits in memory. The next run loads SNAP's com-Friendster, a social graph far larger than the memory each engine is given,
where a load has to stream from disk without running out of room. Its results go on the [benchmark page](/benchmark) and into a post
of their own.

## Run it yourself

One command on a Linux machine with Docker runs the same graph, the same engines and the same checks:
`curl -fsSL https://one.semurg.io/bench | sudo bash -s -- --graph`. Every load, query and walk, with its spread and every held row's
reason, is on the [benchmark page](/benchmark).
