Certified, Not Claimed: ArcadeDB's Bolt Compatibility With Every Official Neo4j Driver | ArcadeDB
Back to Blog
Certified, Not Claimed: ArcadeDB's Bolt Compatibility With Every Official Neo4j Driver
Roberto Franchini·<br>July 14, 2026
·<br>14 min read
·
Bolt
Neo4j
Graph Database
Cypher
Drivers
Testing
CI
Compatibility
ArcadeDB
Plenty of databases say they “support the Bolt protocol.” Almost none of them tell you what that sentence leaves out.
ArcadeDB has spoken Bolt for a while, and the honest version of our claim was narrow: the official Neo4j drivers connect, and simple queries work. Useful, but not the same thing as compatibility. The gap between the two is where users get hurt. The driver connects on Monday; on Thursday someone reads a datetime back out of a query and gets a string.
ArcadeDB 26.7.2 closes that gap. It ships a shared conformance spec, all five official drivers under test, fixes for the protocol bugs that testing exposed, and a compatibility matrix that regenerates itself every night and is published where anyone can read it.
The audit
We started by auditing what we actually had (epic #4882). Some of it was reassuring. The full Bolt 3.0/4.0/4.4 message set was implemented, ROUTE included, along with a hand-written PackStream encoder, correct structure tags for Node, Relationship, and Path, TLS via bolt+s, and Neo4j-style structured error codes.
The rest was not:
Bolt 5.x was never advertised. The server negotiated 3.0, 4.0, and 4.4. Modern 5.x drivers worked only by silently downgrading, which nobody had documented or tested as a deliberate stance.
Temporal values went out as strings. Date, Time, LocalDateTime, DateTime and friends were serialized as ISO-8601 text instead of native Bolt structures. Duration and spatial Point had no handling anywhere. The driver dutifully handed your application a String.
Neo.TransientError.* did not exist. Only a handful of ClientError and DatabaseError codes were defined, so the drivers’ managed-transaction retry logic could never fire the way it does against Neo4j.
ROUTE was single-node only. It returned this node’s own address as writer, reader, and router, so neo4j:// routing against a real HA cluster was unproven.
Three of the five official drivers had zero Bolt coverage. The Python and C# e2e suites tested the Postgres wire protocol and HTTP. There was no Go module at all.
Java and JavaScript coverage was shallow. Connect, run a query, one regression test. No transactions, no error paths, no type round-trips.
A compatibility claim you cannot fail is not a compatibility claim. That list is why the epic existed.
The rules we set
Certify depth, not presence. “The driver connects” is not certification. Every driver runs the full feature matrix, and every unsupported cell becomes a documented limitation instead of a silent omission.
Only the real drivers. neo4j-java-driver, neo4j-driver, neo4j, Neo4j.Driver, neo4j-go-driver. No mocks, no bespoke socket clients. If the driver your application imports cannot do it, we do not get to claim it.
One spec, five idiomatic suites. We deliberately did not build a YAML-driven test runner in five languages. The conformance spec is a reference document. Each scenario is hand-written into that language’s native framework (JUnit, jest, pytest, xUnit, go test) and tagged with the scenario ID. The spec owns what gets tested; the code stays polyglot and readable.
“Not supported” is an acceptable answer, as long as it is written down. Byte-for-byte parity with Neo4j server behavior was never the goal. Knowing exactly where we differ was worth more.
The spec: 39 scenarios, 9 areas
The matrix is defined once, in bolt/conformance/spec.yaml, across nine areas taken verbatim from the epic’s feature table:
Area<br>What it pins down
connection<br>bolt://, bolt+s:// with TLS required and optional, neo4j:// routing discovery
auth<br>Basic auth success and failure; the none scheme being rejected (intentional, now certified as such)
transactions<br>Autocommit, explicit BEGIN/COMMIT/ROLLBACK, managed transaction functions, retry on transient errors
causal-consistency<br>Bookmarks enforcing read-after-write across sessions
multi-database<br>Session database selection and isolation between databases on one driver
result-handling<br>Streaming PULL, PULL n resumption, DISCARD, ResultSummary counters
type-roundtrip<br>Node, Relationship, Path, ByteArray, nested collections, nulls, all five temporal types, Duration, Point
errors<br>Neo.ClientError.* and Neo.TransientError.* so driver retry behavior matches Neo4j
protocol<br>3.0/4.0/4.4 negotiation, 5.x negotiation, RESET mid-stream
Each scenario carries a stable ID (TYPE-011, PROTO-002), a fixture, given/when/then steps, and a status. Every test in every language embeds its scenario ID in the test name, so checking coverage is a grep.
The drivers: 14 pinned versions
Testing against latest tells you about today and nothing about tomorrow. Every language is...