Your Cypher queries work as-is. ArcadeDB's native OpenCypher engine has passed 97.8% of the official TCK with zero failures. Add multi-model, embedded mode, and 6 query languages — all under the Apache 2.0 license.
| Neo4j | ArcadeDB | |
|---|---|---|
| Data Models | Graph only | Graph + Document + Key/Value + Search + Vector |
| Query Languages | Cypher | Cypher + SQL + Gremlin + GraphQL + MongoDB QL + Redis |
| BOLT Protocol | Native | Compatible (v3.0, v4.0, v4.4) |
| OpenCypher TCK | Reference impl. | 97.8% pass rate (0 failures) |
| HA / Replication | Enterprise only ($) | Built-in (free) |
| License | GPL / Commercial | Apache 2.0 (free for commercial use) |
This matters more than most people realize. Neo4j Community Edition is licensed under GPL (GNU General Public License), a copyleft license. If you distribute software that includes or links to GPL code, your entire application must also be released under GPL — meaning you must publish your source code. For most commercial products, this is a non-starter. The alternative is paying for Neo4j's commercial Enterprise license.
ArcadeDB is licensed under Apache 2.0, a permissive license. You can embed ArcadeDB in proprietary software, modify it, distribute it, and sell products built on it — with no obligation to open-source your code. No license fees, no usage limits, no "call us for Enterprise pricing." Every feature, including HA replication and clustering, is available to everyone under the same permissive license. But licensing is just the beginning.
Neo4j is graph-only. ArcadeDB natively supports 5 data models in one engine: Graph, Document, Key/Value, Full-Text Search, and Vector Embeddings. The same record can be a vertex and a document — no duplication.
Neo4j speaks Cypher only. ArcadeDB speaks OpenCypher, SQL, Gremlin, GraphQL, MongoDB QL, and Redis on the same data. Keep your Cypher queries and add SQL for analytics.
Run ArcadeDB inside your JVM process with zero network overhead. Ideal for microservices, edge computing, testing, and batch processing. Scale to server mode when ready.
Use the official Neo4j drivers for Java, Python, JavaScript, .NET, and Go to connect to ArcadeDB. Change the connection URL and credentials — your code stays the same.
Statement & plan caching, cost-based optimizer, async API, LSM-Tree indexes, and minimal GC pressure. Designed for millions of records per second.
Neo4j reserves clustering for its paid Enterprise edition. ArcadeDB includes leader-follower replication and automatic failover in the open-source distribution at no cost.
ArcadeDB ships a dedicated Neo4j Importer that reads a Neo4j database exported in JSONL format and creates a fully indexed ArcadeDB database. No manual schema creation, no scripting — it handles everything automatically.
Use the APOC library to export your Neo4j database:
CALL apoc.export.json.all("neo4j-export.jsonl", {})
This produces a JSONL file (one JSON object per line) containing all nodes and relationships:
{"type":"node","id":"0","labels":["User"],"properties":{"born":"2015-07-04T19:32:24","name":"Adam","age":42}}
{"type":"node","id":"1","labels":["User"],"properties":{"name":"Jim","age":42}}
{"type":"relationship","label":"KNOWS","properties":{"since":1993},"start":{"id":"0","labels":["User"]},"end":{"id":"1","labels":["User"]}}
The simplest way is through the ArcadeDB Console:
> CREATE DATABASE MyDatabase
{MyDatabase}> IMPORT DATABASE file:///path/to/neo4j-export.jsonl
The importer runs a three-pass process:
For programmatic migrations, use the Neo4jImporter class directly:
Neo4jImporter importer = new Neo4jImporter(
"-i", "/path/to/neo4j-export.jsonl",
"-d", "./databases/MyDatabase",
"-o" // overwrite if exists
);
importer.run();
Neo4j supports multiple labels per node (e.g., a node can be both User and
Administrator). ArcadeDB requires each vertex to have exactly one type, so the importer handles this
elegantly using type inheritance.
A Neo4j node with labels ["User", "Administrator"] becomes a vertex of type
Administrator~User (labels sorted alphabetically, joined with ~) that extends
both Administrator and User types. The tilde separator avoids conflicts with
user type names that may contain underscores.
This means:
SELECT FROM User returns all Users and all Administrator~User vertices
(polymorphism)
SELECT FROM Administrator returns all Administrators and all Administrator~User
vertices
Your Cypher queries work as-is in ArcadeDB — the native OpenCypher engine is TCK-compliant. What changes is the surrounding Java code: how you open the database, manage transactions, and (optionally) use the Java API for performance-critical paths.
Neo4j
Driver driver = GraphDatabase.driver("bolt://localhost:7687",
AuthTokens.basic("neo4j", "password"));
Session session = driver.session();
ArcadeDB (embedded — recommended)
Database database = new DatabaseFactory("./databases/mydb").open();
ArcadeDB (via BOLT — drop-in replacement)
// Same Neo4j driver, just change the URL and credentials
Driver driver = GraphDatabase.driver("bolt://localhost:7687",
AuthTokens.basic("root", "arcadedb_password"),
Config.builder().withoutEncryption().build());
Session session = driver.session(SessionConfig.forDatabase("mydb"));
// From here on, your existing code works unchanged
If you go with BOLT, your Cypher code stays identical. The rest of this section covers the embedded Java API for those who want maximum performance.
Neo4j (Cypher)
CREATE CONSTRAINT FOR (p:Person) REQUIRE p.id IS UNIQUE
ArcadeDB (SQL)
CREATE VERTEX TYPE Person
CREATE EDGE TYPE KNOWS
CREATE PROPERTY Person.id LONG
CREATE INDEX ON Person (id) UNIQUE
The syntax is close to Neo4j's but more explicit: you define vertex and edge types separately, then add properties and indexes. This also gives you schema validation that Neo4j doesn't enforce by default.
Where Neo4j requires the driver and Cypher even for simple operations, ArcadeDB's embedded Java API gives you direct, type-safe access:
database.transaction(() -> {
MutableVertex alice = database.newVertex("Person");
alice.set("name", "Alice");
alice.set("born", 1985);
alice.save();
MutableVertex bob = database.newVertex("Person");
bob.set("name", "Bob");
bob.set("born", 1990);
bob.save();
// Create an edge with properties -- one line
alice.newEdge("KNOWS", bob, "since", 2015);
});
Neo4j
Result result = session.run(
"MATCH (p:Person)-[:KNOWS]->(friend) WHERE p.name = $name RETURN friend.name AS name",
Map.of("name", "Alice"));
while (result.hasNext()) {
Record record = result.next();
System.out.println(record.get("name").asString());
}
ArcadeDB (direct graph traversal — zero parsing overhead)
Vertex alice = database.lookupByKey("Person", "name", "Alice").next().asVertex();
for (Vertex friend : alice.getVertices(Vertex.DIRECTION.OUT, "KNOWS"))
System.out.println(friend.getString("name"));
You can also mix: use Cypher for complex pattern matching and the Java API for hot-path traversals.
Neo4j
try (Transaction tx = session.beginTransaction()) {
tx.run("CREATE (p:Person {name: 'Charlie'})");
tx.run("MATCH (a:Person {name: 'Alice'}), (c:Person {name: 'Charlie'}) CREATE (a)-[:KNOWS]->(c)");
tx.commit();
}
ArcadeDB
database.transaction(() -> {
MutableVertex charlie = database.newVertex("Person");
charlie.set("name", "Charlie");
charlie.save();
Vertex alice = database.lookupByKey("Person", "name", "Alice").next().asVertex();
alice.asVertex().newEdge("KNOWS", charlie);
});
Neo4j requires USING PERIODIC COMMIT or the neo4j-admin import tool. ArcadeDB provides
a native asynchronous API:
database.async().onError(exception -> exception.printStackTrace());
for (int i = 0; i < 1_000_000; i++) {
MutableVertex v = database.newVertex("Person");
v.set("id", i);
v.set("name", "Person_" + i);
database.async().createRecord(v, null);
}
Export your Neo4j database, run the built-in importer, and your Cypher queries work as-is. It's that simple.