You can explore the full results, methodology, and per-database breakdowns at .
Database benchmarks are notoriously easy to game, and difficult to get right. Different hardware, different durability settings, different client libraries, a workload that happens to suit one engine's indexing strategy - any of those will tilt the numbers. So we did three things:
We also went out of our way to give every database a fair shot. Rather than running each engine on its out-of-the-box defaults, we used optimised configurations across the board - the same kind of tuning a production team would apply before going live. That meant raising connection and worker pool limits to match the 128-client load, sizing buffer pools, page caches, and shared memory to take advantage of the available 128 GiB of RAM, enabling parallel query execution and prepared-statement caching where supported, setting WAL and checkpoint intervals to values recommended by each project's own performance guides, and turning on the indexes and storage engines (InnoDB, WiredTiger, RocksDB-backed stores, etc.) that each database's documentation recommends for OLTP workloads. The goal was to make sure no engine was held back by a conservative default - if a database underperforms here, it isn't because we left it on its laptop-friendly starter config.
Workloads run with 128 clients issuing 48 concurrent queries each, against datasets of a single table with 5 - 15 million rows of mixed-type records (strings, integers, floats, UUIDs, datetimes, booleans, large text fields, geospatial data, and nested objects and arrays).
We owe a word on durability. The previous round of benchmark results ran with fsync disabled for every engine - leaving each database's writes in the OS page cache rather than flushed to disk. Every database in the comparison ran with the same setting, so nothing was being "fudged" relative to the other engines, but we didn't make the setting explicit, and the headline numbers ended up describing a workload that most production deployments would not likely run.
This round is different. Every database in these benchmarks runs with full disk durability enabled - fsync on, WAL flushed on every commit, no buffered writes hiding behind the page cache. The configuration files for each engine are checked into the so anyone can audit them. The numbers above are what each engine sustains when every committed transaction is on disk before the client gets an acknowledgement. That's slower than the cache-friendly numbers you'll find in some marketing posts, ours included, but it's the only honest way to compare databases that are going to outlive a power outage.
The biggest story is internal. Across three major releases, we've fundamentally rebuilt the query, parser, and storage layers:
| Workload | SurrealDB 1.x | SurrealDB 2.x | SurrealDB 3.x |
|---|---|---|---|
| Mixed CRUD (50% write) | 78k ops/s | 107k ops/s | 141k ops/s |
| Full-table scans | 0.06 ops/s | 0.09 ops/s | 11 ops/s (164×) |
| Indexed lookups | 32 ops/s | 44 ops/s | 104 ops/s (3.2×) |
Between SurrealDB 2.x and 3.x alone:
The scan number is not a typo. The SurrealDB 3.x query planner and storage engine eliminates the per-row decoding overhead that dominated earlier versions, which is why a workload that used to take minutes now completes in seconds.
SurrealDB is a durable, transactional, multi-model database, so the comparisons that matter most are against the primary databases people actually evaluate it against - Postgres for relational, MongoDB for document, Neo4j for graph. Here's how the same workload looks across those three categories, run on the same hardware with each engine on a tuned production-grade configuration.
CRUD throughput (ops/s) and bulk-read metrics:
| Workload | SurrealDB | Postgres | MySQL |
|---|---|---|---|
| Create | 122k | 83k | 22k |
| Read | 254k | 327k | 195k |
| Update | 106k | 81k | 22k |
| Delete | 156k | 86k | 22k |
| Write throughput (C+U+D mean) | 128k | 84k | 22k |
| count(*) on 5M rows | 12 | 8 | 42 |
SurrealDB is faster than Postgres on every write operation - roughly 1.5× faster creates, 1.3× faster updates, and 1.8× faster deletes - while Postgres still edges ahead on raw single-record reads. Against MySQL the gap widens dramatically: SurrealDB is 5 - 7× faster on writes.
Averaged across creates, updates, and deletes, SurrealDB delivers ~1.5× the write throughput of Postgres - the headline number the benchmarks page leads the Relational category with - and beats Postgres by ~1.5× on full-table counts. Postgres' query planner is 30 years old and still ahead on indexed predicate filtering; we're not pretending otherwise, and we're working on closing that gap in 3.1.
CRUD throughput (ops/s) and bulk-read metrics:
| Workload | SurrealDB | MongoDB | ArangoDB |
|---|---|---|---|
| Create | 122k | 183k | 1.0k |
| Read | 254k | 200k | 255k |
| Update | 106k | 160k | 0.9k |
| Delete | 156k | 200k | 1.0k |
| Filter scan (unindexed, ops/s) | 8.3 | 3.0 | 8.5 |
This is the closest race. MongoDB still leads on single-record writes, while SurrealDB is ~1.3× faster on reads - and the picture flips on heavier workloads. On predicate filter scans against unindexed tables - the headline figure the benchmarks page uses for the Document category - SurrealDB is roughly 2.7× faster than MongoDB, with consistently lower mean and p99 latency. Against ArangoDB's document engine, SurrealDB is between 100× and 150× faster on writes.
CRUD throughput (ops/s) and bulk-read metrics:
| Workload | SurrealDB | Neo4j | ArangoDB |
|---|---|---|---|
| Create | 122k | 42k | 1.0k |
| Read | 254k | 174k | 255k |
| Update | 106k | 50k | 0.9k |
| Delete | 156k | 44k | 1.0k |
| Filter scan (indexed, mean ops/s) | 421 | 12 | - |
SurrealDB outperforms Neo4j across every CRUD operation - roughly 2 - 3.5× faster on writes and 1.5× faster on reads - while running the same graph traversals through the same engine that handles documents and tables.
The gap on filtered scans is even more dramatic. Across indexed predicate filter queries - the headline metric the benchmarks page uses for the Graph category - SurrealDB is roughly 35× faster than Neo4j. No separate database, no separate query language, no separate operational story.
For raw key-value throughput, we also ran SurrealDB's in-memory engine (with append-only persistence) against Redis and KeyDB:
| Operation | SurrealDB | Redis | KeyDB |
|---|---|---|---|
| Create | 300.8k | 85.8k | 79.5k |
| Read | 288.1k | 367.9k | 348.6k |
| Update | 300.6k | 89.0k | 85.2k |
| Delete | 279.3k | 100.6k | 100.0k |
That's roughly 3× faster than Redis on writes, updates, and deletes, while offering durable, snapshot-isolated transactions and a full query language Redis doesn't have. Redis still wins on large 1,000-record batch operations and edges ahead on single-record reads.
SurrealDB's embedded engine runs the same SurrealQL on the same disk format as the server.
| Workload | SurrealDB embedded | SQLite |
|---|---|---|
| Create | 110k | 1.3k |
| Read | 138k | 154k |
| Update | 145k | 1.3k |
| Delete | 101k | 1.3k |
| Filter scan (unindexed, ops/s) | 39 | 6 |
| Filter scan (indexed, mean ops/s) | 7.5k | 2.3k |
Against SQLite, SurrealDB is roughly 85× faster on creates, 110× faster on updates, and 75× faster on deletes, with single-record reads in the same ballpark. On predicate filter scans against unindexed tables it's around 6.5× faster than SQLite, and on indexed filter scans, around 3× faster.
The full breakdowns - including p50, p95, and p99 latencies, batch sizes from 100 to 1,000 rows, indexed and non-indexed predicate filters, and full-text search - are on the .
The numbers above are an honest snapshot, not a finish line. There are still workloads where Redis, MongoDB, and Postgres beat us - large batch operations vs. Redis, single-record writes vs. Mongo, indexed predicate filtering vs. Postgres - and we know exactly where each gap comes from. Closing those gaps is the central focus of the SurrealDB 3.1 cycle.
What we're actively working on:
The goal isn't "fastest at one thing." It's to be fastest, or competitive, across every workload that matters, while keeping the one property no specialist engine can match: a single query language - SurrealQL - that handles relational, document, graph, key-value, time-series, vector, and full-text search data in the same database, with the same transactional guarantees, on the same disk format - and the same engine, whether you're running it embedded inside an application, on a single server, at the edge close to your users, or distributed across hundreds of nodes for horizontal scale. We don't think you should have to choose between Postgres, Mongo, Neo4j, and Redis - or between a database that runs on a developer laptop and one that runs across a global fleet. We think a single database should run all four shapes of workload at production speed, anywhere it needs to live, and the SurrealDB 3.x numbers above are the strongest evidence yet that it can.
There's a reason we keep pushing on this combination of data models, and it's not historical accident. Agent memory is multi-model by nature. A useful AI agent needs structured facts about the world (relational), semi-structured context and tool outputs (document), entity and event relationships (graph), embeddings for semantic recall (vector), keyword and BM25 retrieval over its corpus (full-text search), episodic and temporal context (time-series), and fast session and cache state (key-value) - and it needs all of that in a single transactionally consistent store, because the moment those shapes live in separate databases, you've built a glue-code problem that breaks every time the schema changes or the model is updated.
Agents also need that memory close to where they run. An agent reasoning inside a browser, a phone, an in-vehicle system, or a per-tenant edge worker can't afford a round trip to a central database for every retrieval. The fact that SurrealDB runs as an embedded engine on the same disk format as the distributed server - with the same query language and the same transactional guarantees - is what makes it usable as the memory layer for agents that move fluidly between local, edge, and centralised deployments. Faster CRUD, faster scans, and faster indexed lookups aren't just abstract benchmark wins; they're how many tools an agent can call, how much context it can recall per turn, and how many concurrent agents a single host can support. That's the workload SurrealDB 3.x is built for, and it's the workload the next round of benchmarks - covering vector search, graph traversal, and full-text retrieval - will measure head-on.
We intend to expand the benchmarks to also cover CockroachDB, TiDB, MongoDB, and Aerospike for distributed comparisons, which we'll publish in a future round. We also plan to expand the workload set to include graph traversals vector search, and full-text search, two areas where the single-engine, multi-model design of SurrealDB shows its biggest advantages.
Until then: the harness is open source, the results are reproducible, and we'd love for you to run them on your own hardware and tell us what you find.