Neo4j BOLT Protocol

BOLT protocol support is available starting from ArcadeDB version 26.2.1.

ArcadeDB Server supports the Neo4j BOLT protocol, enabling connectivity from any BOLT-compatible client or driver. This allows you to use the official Neo4j drivers with ArcadeDB, leveraging the native OpenCypher query engine for graph operations.

The BOLT protocol implementation supports:

  • BOLT v3.0, v4.0, and v4.4 protocol versions

  • Full Cypher query support via ArcadeDB’s native OpenCypher implementation

  • Parameterized queries for security and performance

  • Explicit transactions with BEGIN/COMMIT/ROLLBACK

  • Multi-database support with database selection per connection or query

  • Multi-label vertices following Neo4j’s node labeling conventions

Setup

If you’re using ArcadeDB as embedded, add the dependency to the arcadedb-bolt library. If you’re using Maven, include this dependency in your pom.xml file:

<dependency>
    <groupId>com.arcadedb</groupId>
    <artifactId>arcadedb-bolt</artifactId>
    <version>26.5.1</version>
</dependency>

To start the BOLT plugin, enlist it in the server.plugins settings. To specify multiple plugins, use the comma , as separator. Example:

~/arcadedb $ bin/server.sh -Darcadedb.server.plugins="Bolt:com.arcadedb.bolt.BoltProtocolPlugin"

If you’re using MS Windows OS, replace server.sh with server.bat.

In case you’re running ArcadeDB with Docker, use -e to pass settings and open the BOLT default port 7687:

docker run --rm -p 2480:2480 -p 2424:2424 -p 7687:7687 \
       --env JAVA_OPTS="-Darcadedb.server.rootPassword=playwithdata \
          -Darcadedb.server.plugins=Bolt:com.arcadedb.bolt.BoltProtocolPlugin " \
          arcadedata/arcadedb:latest

The Server output will contain this line:

INFO  [ArcadeDBServer] - Bolt Protocol plugin started (host=0.0.0.0 port=7687)

Configuration

The BOLT plugin supports the following configuration options:

Setting Default Description

arcadedb.bolt.port

7687

TCP/IP port for BOLT connections

arcadedb.bolt.host

0.0.0.0

Host/IP address to bind to

arcadedb.bolt.defaultDatabase

(none)

Default database when not specified by client

arcadedb.bolt.maxConnections

0

Maximum concurrent connections (0 = unlimited)

arcadedb.bolt.routing.ttl

300

Time-to-live in seconds for routing table entries

arcadedb.bolt.debug

false

Enable BOLT protocol debug logging

Example configuration:

bin/server.sh -Darcadedb.server.plugins="Bolt:com.arcadedb.bolt.BoltProtocolPlugin" \
              -Darcadedb.bolt.port=7687 \
              -Darcadedb.bolt.defaultDatabase=mydatabase

Compatible Drivers

The Neo4j official drivers are open source and licensed under Apache 2.0. You can use them with ArcadeDB’s BOLT protocol implementation:

Language Driver Installation

Java

neo4j-java-driver

Maven: org.neo4j.driver:neo4j-java-driver

Python

neo4j

pip install neo4j

JavaScript

neo4j-driver

npm install neo4j-driver

.NET

Neo4j.Driver

NuGet: Neo4j.Driver

Go

neo4j-go-driver

go get github.com/neo4j/neo4j-go-driver/v5

For the complete list of community drivers, check the Neo4j Driver documentation.

Java Example

import org.neo4j.driver.*;

// Create driver (without encryption for local development)
Driver driver = GraphDatabase.driver(
    "bolt://localhost:7687",
    AuthTokens.basic("root", "playwithdata"),
    Config.builder().withoutEncryption().build()
);

// Open session for specific database
try (Session session = driver.session(SessionConfig.forDatabase("mydatabase"))) {

    // Execute a simple query
    Result result = session.run("MATCH (n:Person) RETURN n.name AS name LIMIT 10");
    while (result.hasNext()) {
        Record record = result.next();
        System.out.println(record.get("name").asString());
    }

    // Execute parameterized query
    Result paramResult = session.run(
        "MATCH (p:Person) WHERE p.age >= $minAge RETURN p.name, p.age",
        Values.parameters("minAge", 25)
    );

    // Execute in explicit transaction
    try (Transaction tx = session.beginTransaction()) {
        tx.run("CREATE (n:Person {name: $name, age: $age})",
               Values.parameters("name", "Alice", "age", 30));
        tx.run("CREATE (n:Person {name: $name, age: $age})",
               Values.parameters("name", "Bob", "age", 25));
        tx.commit();
    }
}

driver.close();

Python Example

from neo4j import GraphDatabase

# Create driver
driver = GraphDatabase.driver(
    "bolt://localhost:7687",
    auth=("root", "playwithdata")
)

# Query example
with driver.session(database="mydatabase") as session:
    # Simple query
    result = session.run("MATCH (n:Person) RETURN n.name AS name LIMIT 10")
    for record in result:
        print(record["name"])

    # Parameterized query
    result = session.run(
        "MATCH (p:Person) WHERE p.age >= $minAge RETURN p.name, p.age",
        minAge=25
    )

    # Explicit transaction
    with session.begin_transaction() as tx:
        tx.run("CREATE (n:Person {name: $name, age: $age})", name="Alice", age=30)
        tx.run("CREATE (n:Person {name: $name, age: $age})", name="Bob", age=25)
        tx.commit()

driver.close()

JavaScript Example

const neo4j = require('neo4j-driver');

// Create driver
const driver = neo4j.driver(
    'bolt://localhost:7687',
    neo4j.auth.basic('root', 'playwithdata')
);

// Query example
const session = driver.session({ database: 'mydatabase' });

try {
    // Simple query
    const result = await session.run('MATCH (n:Person) RETURN n.name AS name LIMIT 10');
    result.records.forEach(record => {
        console.log(record.get('name'));
    });

    // Parameterized query
    const paramResult = await session.run(
        'MATCH (p:Person) WHERE p.age >= $minAge RETURN p.name, p.age',
        { minAge: 25 }
    );

    // Explicit transaction
    const tx = session.beginTransaction();
    await tx.run('CREATE (n:Person {name: $name, age: $age})', { name: 'Alice', age: 30 });
    await tx.run('CREATE (n:Person {name: $name, age: $age})', { name: 'Bob', age: 25 });
    await tx.commit();

} finally {
    await session.close();
    await driver.close();
}

Cypher Query Examples

Since BOLT protocol uses Cypher as its query language, you can execute any query supported by ArcadeDB’s OpenCypher implementation:

// Create vertices
CREATE (alice:Person {name: 'Alice', age: 30})
CREATE (bob:Person {name: 'Bob', age: 25})

// Create relationship
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
CREATE (a)-[:KNOWS {since: 2020}]->(b)

// Query with pattern matching
MATCH (p:Person)-[:KNOWS]->(friend)
WHERE p.age > 20
RETURN p.name, friend.name

// Variable-length paths
MATCH path = (start:Person)-[:KNOWS*1..3]->(end:Person)
RETURN path

// Aggregations
MATCH (p:Person)
RETURN avg(p.age) AS averageAge, count(p) AS totalPeople

Transactions

BOLT protocol supports explicit transactions:

  • Auto-commit mode: Single queries outside a transaction are automatically committed

  • Explicit transactions: Use BEGIN/COMMIT/ROLLBACK for multi-statement transactions

  • Rollback on error: Transactions are automatically rolled back if an error occurs

// Auto-commit (implicit transaction)
session.run("CREATE (n:Person {name: 'Charlie'})");

// Explicit transaction with multiple operations
try (Transaction tx = session.beginTransaction()) {
    tx.run("CREATE (a:Person {name: 'David'})");
    tx.run("CREATE (b:Person {name: 'Eve'})");
    tx.run("MATCH (a:Person {name: 'David'}), (b:Person {name: 'Eve'}) CREATE (a)-[:FRIENDS]->(b)");
    tx.commit();
}

// Transaction rollback example
try (Transaction tx = session.beginTransaction()) {
    tx.run("CREATE (n:Person {name: 'Frank'})");
    // Rollback - changes will not be persisted
    tx.rollback();
}

Current Limitations

  • TLS/SSL: The current implementation does not support encrypted connections. Use network-level security (VPN, SSH tunnel) for production deployments requiring encryption.

  • Routing: Single-server routing only. In cluster deployments, the routing table returns the connected server for all roles (READ, WRITE, ROUTE).

Troubleshooting

If you encounter connection issues:

  1. Enable debug logging: Start the server with -Darcadedb.bolt.debug=true to see detailed protocol messages.

  2. Check port availability: Ensure port 7687 (or your configured port) is not in use by another service.

  3. Verify authentication: ArcadeDB requires authentication. Ensure you’re providing valid credentials.

  4. Disable encryption in drivers: If using Neo4j drivers, configure them to connect without encryption since TLS is not yet supported.

For Java driver:

Config.builder().withoutEncryption().build()

For Python driver:

driver = GraphDatabase.driver(uri, auth=auth, encrypted=False)