Chapter 2. Client applications

This section describes how to manage database connections within an application.

This section contains the following:

2.1. The Driver Object

Neo4j client applications require a Driver Object which, from a data access perspective, forms the backbone of the application. It is through this object that all Neo4j interaction is carried out, and it should therefore be made available to all parts of the application that require data access.

In languages where thread safety is an issue, the Driver Object can be considered thread-safe.

A note on lifecycle

Applications will typically construct a Driver Object on startup and destroy it on exit.

Destroying a Driver Object will immediately shut down any connections previously opened via that Driver Object, by closing the associated connection pool.

This will have the consequence of rolling back any open transactions, and closing any unconsumed results.

To construct a driver instance, a connection URI and authentication information must be supplied.

Additional configuration details can be supplied if required. The configuration details are immutable for the lifetime of the Driver Object. Therefore, if multiple configurations are required (such as when working with multiple database users) then multiple Driver Objects must be used.

Example 2.1. The driver lifecycle
public class DriverLifecycleExample : IDisposable
{
    public IDriver Driver { get; }

    public DriverLifecycleExample(string uri, string user, string password)
    {
        Driver = GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
    }

    public void Dispose()
    {
        Driver?.Dispose();
    }
}
public class DriverLifecycleExample implements AutoCloseable
{
    private final Driver driver;

    public DriverLifecycleExample( String uri, String user, String password )
    {
        driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ) );
    }

    @Override
    public void close() throws Exception
    {
        driver.close();
    }
}

Import driver lifecycle. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))

try {
  await driver.verifyConnectivity()
  console.log('Driver created')
} catch (error) {
  console.log(`connectivity verification failed. ${error}`)
}

const session = driver.session()
try {
  await session.run('CREATE (i:Item)')
} catch (error) {
  console.log(`unable to execute query. ${error}`)
} finally {
  await session.close()
}

// ... on application exit:
await driver.close()
class DriverLifecycleExample:
    def __init__(self, uri, auth):
        self.driver = GraphDatabase.driver(uri, auth=auth)

    def close(self):
        self.driver.close()
from neo4j import GraphDatabase

2.2. Connection URIs

A connection URI identifies a graph database and how to connect to it.

The encryption and trust settings provide detail to how that connection should be secured.

There are significant changes to security settings between Neo4j 3.x and Neo4j 4.x

Please consider the information in this section before upgrading from a previous version.

The Migration Guide is also a good source of information about changes in functionality.

Starting with Neo4j 4.0, client-server communication uses only unencrypted local connections by default.

This is a change from previous versions, which switched on encryption by default, but generated a self-signed certificate out of the box.

When a full certificate is installed, and encryption is enabled on the driver, full certificate checks are carried out (refer to Operations Manual → SSL framework ). Full certificates provide better overall security than self-signed certificates as they include a complete chain of trust back to a root certificate authority.

Neo4j Aura is a secure hosted service backed by full certificates signed by a root certificate authority.

To connect to Neo4j Aura, driver users must enable encryption and the complete set of certificate checks (the latter of which are enabled by default).

For more information, see Section 2.2.4, “Examples”.

Table 2.1. Changes in default security settings between 3.x and 4.x
Setting Neo4j 4.x Neo4j 3.x (Drivers 1.x)

Bundled certificate

none

auto-generated, self-signed

Driver encryption

off

on

Bolt interface

localhost

localhost

Certificate expiry check

on

on

Certificate CA check

on

off

Certificate hostname check

on

off

2.2.1. Initial address resolution

The address provided in a neo4j:// URI is used for initial and fallback communication only.

This communication occurs to bootstrap the routing table, through which all subsequent communication is carried out. Fallback occurs when the driver is unable to contact any of the addresses held in the routing table. The initial address is once again reused to bootstrap the system.

Several options are available for providing this initial logical-to-physical host resolution. These include regular DNS, custom middleware such as a load balancer, and the Driver Object resolver function, all of which are described in the following sections.

2.2.1.1. DNS resolution

DNS resolution is the default, and always-available option. As it is possible to configure DNS to resolve a single host name down to multiple IP addresses, this can be used to expose all core server IP addresses under a single host name.

Figure 2.1. Initial address resolution over DNS
dns resolution

2.2.1.2. Custom middleware

Middleware, such as a load balancer, can be used to group the core servers under a single public address.

Figure 2.2. Initial address resolution using custom middleware
custom middleware

2.2.1.3. Resolver function

Neo4j Drivers also present an address resolution intercept hook called the resolver function.

This takes the form of a callback function that accepts a single input address and returns multiple output addresses. The function may hard code the output addresses or may draw them from another configuration source, as required.

Figure 2.3. Initial address resolution using resolver function
resolver function

The example below shows how to expand a single address into multiple (hard-coded) output addresses:

Example 2.2. Custom Address Resolver
private IDriver CreateDriverWithCustomResolver(string virtualUri, IAuthToken token,
    params ServerAddress[] addresses)
{
    return GraphDatabase.Driver(virtualUri, token,
        o => o.WithResolver(new ListAddressResolver(addresses)).WithEncryptionLevel(EncryptionLevel.None));
}

public void AddPerson(string name)
{
    using (var driver = CreateDriverWithCustomResolver("neo4j://x.acme.com",
        AuthTokens.Basic(Username, Password),
        ServerAddress.From("a.acme.com", 7687), ServerAddress.From("b.acme.com", 7877),
        ServerAddress.From("c.acme.com", 9092)))
    {
        using (var session = driver.Session())
        {
            session.Run("CREATE (a:Person {name: $name})", new {name});
        }
    }
}

private class ListAddressResolver : IServerAddressResolver
{
    private readonly ServerAddress[] servers;

    public ListAddressResolver(params ServerAddress[] servers)
    {
        this.servers = servers;
    }

    public ISet<ServerAddress> Resolve(ServerAddress address)
    {
        return new HashSet<ServerAddress>(servers);
    }
}
private Driver createDriver( String virtualUri, String user, String password, ServerAddress... addresses )
{
    Config config = Config.builder()
            .withResolver( address -> new HashSet<>( Arrays.asList( addresses ) ) )
            .build();

    return GraphDatabase.driver( virtualUri, AuthTokens.basic( user, password ), config );
}

private void addPerson( String name )
{
    String username = "neo4j";
    String password = "some password";

    try ( Driver driver = createDriver( "neo4j://x.acme.com", username, password, ServerAddress.of( "a.acme.com", 7676 ),
            ServerAddress.of( "b.acme.com", 8787 ), ServerAddress.of( "c.acme.com", 9898 ) ) )
    {
        try ( Session session = driver.session( builder().withDefaultAccessMode( AccessMode.WRITE ).build() ) )
        {
            session.run( "CREATE (a:Person {name: $name})", parameters( "name", name ) );
        }
    }
}
function createDriver (virtualUri, user, password, addresses) {
  return neo4j.driver(virtualUri, neo4j.auth.basic(user, password), {
    resolver: address => addresses
  })
}

function addPerson (name) {
  const driver = createDriver('neo4j://x.acme.com', user, password, [
    'a.acme.com:7575',
    'b.acme.com:7676',
    'c.acme.com:8787'
  ])
  const session = driver.session({ defaultAccessMode: neo4j.WRITE })

  session
    .run('CREATE (n:Person { name: $name })', { name: name })
    .then(() => session.close())
    .then(() => driver.close())
}
def create_driver(uri, user, password):

    def resolver(address):
        host, port = address
        if host == "x.example.com":
            yield "a.example.com", port
            yield "b.example.com", port
            yield "c.example.com", port
        else:
            yield host, port

    return GraphDatabase.driver(uri, auth=(user, password), resolver=resolver)


def add_person(name):
    driver = create_driver("neo4j://x.example.com", user="neo4j", password="password")
    session = driver.session(default_access_mode=WRITE_ACCESS)
    session.run("CREATE (a:Person {name: $name})", {"name", name})
    session.close()
    driver.close()
from neo4j import (
    GraphDatabase,
    WRITE_ACCESS,
)

2.2.2. Routing table

The routing table acts like the glue between the driver connectivity layer and the database surface. This table contains a list of server addresses, grouped as readers and writers, and is refreshed automatically by the driver as required.

The driver does not expose any API to work directly with the routing table, but it can sometimes be useful to explore when troubleshooting a system.

2.2.3. Routing context

A routing context can be included as the query part of a neo4j:// URI.

Routing contexts are defined by means of server policies and allow customization of the contents of the routing table.

Example 2.3. Configure a routing driver with routing context

This example will assume that Neo4j has been configured for server policies as described in Neo4j Operations Manual → Load balancing for multi-data center systems. In particular, a server policy called europe has been defined. Additionally, we have a server neo01.graph.example.com to which we wish to direct the driver.

This URI will use the server policy europe:

neo4j://neo01.graph.example.com?policy=europe

Server-side configuration to enable routing drivers with routing context

A prerequisite for using a routing driver with routing context is that the Neo4j database is operated on a Causal Cluster with the Multi-data center licensing option enabled. Additionally, the routing contexts must be defined within the cluster as routing policies.

For details on how to configure multi-data center routing policies for a Causal Cluster, please refer to Operations Manual → Causal Clustering.

Exposing a single instance deployment on a remote host using the neo4j URI scheme

If you are using a single instance of Neo4j, deployed on a remote machine whilst using the neo4j URI scheme, you will need to complete additional configuration of the server.

To make the server aware of its deployment environment, you need to configure default_advertised_address with your deployment machine’s host name, as visible from the client machine.

2.2.4. Examples

Connection URIs are typically formed according to the following pattern:

neo4j://<HOST>:<PORT>[?<ROUTING_CONTEXT>]

This targets a routed Neo4j service that may be fulfilled by either a cluster or a single instance. The HOST and PORT values contain a logical hostname and port number targeting the entry point to the Neo4j service (e.g. neo4j://graph.example.com:7687).

In a clustered environment, the URI address will resolve to one of more of the core members; for standalone installations, this will simply point to that server address. The ROUTING_CONTEXT option allows for customization of the routing table and is discussed in more detail in Section 2.2.3, “Routing context”.

An alternative URI form, using the bolt URI scheme (e.g. bolt://graph.example.com:7687), can be used when a single point-to-point connection is required. This variant is useful for the subset client applications (such as admin tooling) that need to be aware of individual servers, as opposed to those which require a highly available database service.

bolt://<HOST>:<PORT>

Each of the neo4j and bolt URI schemes permit variants that contain extra encryption and trust information. The +s variants enable encryption with a full certificate check, and the +ssc variants enable encryption, but with no certificate check. This latter variant is designed specifically for use with self-signed certificates.

Table 2.2. Available URI schemes
URI scheme Routing Description

neo4j

Yes

Unsecured

neo4j+s

Yes

Secured with full certificate

neo4j+ssc

Yes

Secured with self-signed certificate

bolt

No

Unsecured

bolt+s

No

Secured with full certificate

bolt+ssc

No

Secured with self-signed certificate

Neo4j 3.x did not provide a routing table in single instance mode and therefore you should use a bolt:// URI if targeting an older, non-clustered server.

The table below provides example code snippets for different deployment configurations. Each snippet expects an auth variable to have been previously defined, containing the authentication details for that connection.

Example 2.4. Connecting to a service

The table below illustrates examples of how to connect to a service with routing:

Product Security Code snippet Comments

Neo4j Aura

Secured with full certificate

GraphDatabase.Driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the .NET Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
IDriver driver = GraphDatabase.Driver(uri, auth,
           o => o.WithEncryptionLevel(EncryptionLevel.Encrypted));

This is the default (and only option) for Neo4j Aura

Neo4j 4.x

Unsecured

GraphDatabase.Driver("neo4j://graph.example.com:7687", auth);

This is the default for Neo4j 4.x series

Neo4j 4.x

Secured with full certificate

GraphDatabase.Driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the .NET Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
IDriver driver = GraphDatabase.Driver(uri, auth,
           o => o.WithEncryptionLevel(EncryptionLevel.Encrypted));
 

Neo4j 4.x

Secured with self-signed certificate

GraphDatabase.Driver("neo4j+ssc://graph.example.com:7687", auth)

If you do not have at least the .NET Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
IDriver driver = GraphDatabase.Driver(uri, auth,
           o => o.WithEncryptionLevel(EncryptionLevel.Encrypted)
                 .WithTrustManager(TrustManager.CreateInsecure()));
 

Neo4j 3.x

Secured with full certificate

GraphDatabase.Driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the .NET Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
IDriver driver = GraphDatabase.Driver(uri, auth,
           o => o.WithEncryptionLevel(EncryptionLevel.Encrypted));
 

Neo4j 3.x

Secured with self-signed certificate

GraphDatabase.Driver("neo4j+ssc://graph.example.com:7687", auth)

If you do not have at least the .NET Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
IDriver driver = GraphDatabase.Driver(uri, auth,
           o => o.WithEncryptionLevel(EncryptionLevel.Encrypted)
                 .WithTrustManager(TrustManager.CreateInsecure()));

This is the default for Neo4j 3.x series

Neo4j 3.x

Unsecured

GraphDatabase.Driver("neo4j://graph.example.com:7687", auth);
 

To connect to a service without routing, you can replace neo4j with bolt.

The table below illustrates examples of how to connect to a service with routing:

Product Security Code snippet Comments

Neo4j Aura

Secured with full certificate

GraphDatabase.driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the Java Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
Config config = Config.builder()
                     .withEncryption()
                     .build();
Driver driver = GraphDatabase.driver(uri, auth, config);

This is the default (and only option) for Neo4j Aura

Neo4j 4.x

Unsecured

GraphDatabase.driver("neo4j://graph.example.com:7687", auth)

This is the default for Neo4j 4.x series

Neo4j 4.x

Secured with full certificate

GraphDatabase.driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the Java Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
Config config = Config.builder()
                     .withEncryption()
                     .build();
Driver driver = GraphDatabase.driver(uri, auth, config);
 

Neo4j 4.x

Secured with self-signed certificate

GraphDatabase.driver("neo4j+ssc://graph.example.com:7687", auth)

If you do not have at least the Java Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
Config config = Config.builder()
                    .withEncryption()
                    .withTrustStrategy( trustAllCertificates() )
                    .build();
Driver driver = GraphDatabase.driver(uri, auth, config);
 

Neo4j 3.x

Secured with full certificate

GraphDatabase.driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the Java Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
Config config = Config.builder()
                     .withEncryption()
                     .build();
Driver driver = GraphDatabase.driver(uri, auth, config);
 

Neo4j 3.x

Secured with self-signed certificate

GraphDatabase.driver("neo4j+ssc://graph.example.com:7687", auth)

If you do not have at least the Java Driver 4.0.1 patch installed, you will need this snippet instead:

String uri = "neo4j://graph.example.com:7687";
Config config = Config.builder()
                    .withEncryption()
                    .withTrustStrategy( trustAllCertificates() )
                    .build();
Driver driver = GraphDatabase.driver(uri, auth, config);

This is the default for Neo4j 3.x series

Neo4j 3.x

Unsecured

GraphDatabase.driver("neo4j://graph.example.com:7687", auth)
 

To connect to a service without routing, you can replace neo4j with bolt.

The table below illustrates examples of how to connect to a service with routing:

Product Security Code snippet Comments

Neo4j Aura

Secured with full certificate

neo4j.driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the JavaScript Driver 4.0.2 patch installed, you will need this snippet instead:

const uri = 'neo4j://graph.example.com:7687'
const driver = neo4j.driver(uri, auth, {
  encrypted: 'ENCRYPTION_ON'
})

This is the default (and only option) for Neo4j Aura

Neo4j 4.x

Unsecured

neo4j.driver("neo4j://graph.example.com:7687", auth)

This is the default for Neo4j 4.x series

Neo4j 4.x

Secured with full certificate

neo4j.driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the JavaScript Driver 4.0.2 patch installed, you will need this snippet instead:

const uri = 'neo4j://graph.example.com:7687'
const driver = neo4j.driver(uri, auth, {
  encrypted: 'ENCRYPTION_ON'
})
 

Neo4j 4.x

Secured with self-signed certificate

neo4j.driver("neo4j+ssc://graph.example.com:7687", auth)

If you do not have at least the JavaScript Driver 4.0.2 patch installed, you will need this snippet instead:

const uri = 'neo4j://graph.example.com:7687'
const driver = neo4j.driver(uri, auth, {
  encrypted: 'ENCRYPTION_ON',
  trust: 'TRUST_ALL_CERTIFICATES'
})
 

Neo4j 3.x

Secured with full certificate

neo4j.driver("neo4j+s://graph.example.com:7687", auth)

If you do not have at least the JavaScript Driver 4.0.2 patch installed, you will need this snippet instead:

const uri = 'neo4j://graph.example.com:7687'
const driver = neo4j.driver(uri, auth, {
  encrypted: 'ENCRYPTION_ON'
})
 

Neo4j 3.x

Secured with self-signed certificate

neo4j.driver("neo4j+ssc://graph.example.com:7687", auth)

If you do not have at least the JavaScript Driver 4.0.2 patch installed, you will need this snippet instead:

const uri = 'neo4j://graph.example.com:7687'
const driver = neo4j.driver(uri, auth, {
  encrypted: 'ENCRYPTION_ON',
  trust: 'TRUST_ALL_CERTIFICATES'
})

This is the default for Neo4j 3.x series

Neo4j 3.x

Unsecured

neo4j.driver("neo4j://graph.example.com:7687", auth)
 

To connect to a service without routing, you can replace neo4j with bolt.

The table below illustrates examples of how to connect to a service with routing:

Product Security Code snippet Comments

Neo4j Aura

Secured with full certificate

GraphDatabase.driver("neo4j+s://graph.example.com:7687", auth)

For Python Driver versions before 4.0.0 you need this snippet instead:

GraphDatabase.driver("neo4j://graph.example.com:7687", auth,
    "encrypted"=True, "trust"=TRUST_SYSTEM_CA_SIGNED_CERTIFICATES)

This is the default (and only option) for Neo4j Aura

Neo4j 4.x

Unsecured

GraphDatabase.driver("neo4j://graph.example.com:7687", auth)

This is the default for Neo4j 4.x series

Neo4j 4.x

Secured with full certificate

GraphDatabase.driver("neo4j+s://graph.example.com:7687", auth)

For Python Driver versions before 4.0.0 you need this snippet instead:

GraphDatabase.driver("neo4j://graph.example.com:7687", auth,
    "encrypted"=True, "trust"=TRUST_SYSTEM_CA_SIGNED_CERTIFICATES)
 

Neo4j 4.x

Secured with self-signed certificate

neo4j.driver("neo4j+ssc://graph.example.com:7687", auth)

For Python Driver versions before 4.0.0 you need this snippet instead:

GraphDatabase.driver("neo4j://graph.example.com:7687", auth,
    "encrypted"=True, "trust"=TRUST_ALL_CERTIFICATES)
 

Neo4j 3.x

Secured with full certificate

neo4j.driver("neo4j+s://graph.example.com:7687", auth)

For Python Driver versions before 4.0.0 you need this snippet instead:

GraphDatabase.driver("neo4j://graph.example.com:7687", auth,
    "encrypted"=True, "trust"=TRUST_SYSTEM_CA_SIGNED_CERTIFICATES)
 

Neo4j 3.x

Secured with self-signed certificate

neo4j.driver("neo4j+ssc://graph.example.com:7687", auth)

For Python Driver versions before 4.0.0 you need this snippet instead:

GraphDatabase.driver("neo4j://graph.example.com:7687", auth,
    "encrypted"=True, "trust"=TRUST_ALL_CERTIFICATES)

This is the default for Neo4j 3.x series

Neo4j 3.x

Unsecured

neo4j.driver("neo4j://graph.example.com:7687", auth)
 

To connect to a service without routing, you can replace neo4j with bolt.

2.3. Authentication

Authentication details are provided as an auth token which contains the user names, passwords or other credentials required to access the database. Neo4j supports multiple authentication standards but uses basic authentication by default.

2.3.1. Basic authentication

The basic authentication scheme is backed by a password file stored within the server and requires applications to provide a user name and password. For this, use the basic auth helper:

Example 2.5. Basic authentication
public IDriver CreateDriverWithBasicAuth(string uri, string user, string password)
{
    return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
}
public BasicAuthExample( String uri, String user, String password )
{
    driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ) );
}

Import basic authentication. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Result;

const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
def __init__(self, uri, user, password):
    self.driver = GraphDatabase.driver(uri, auth=(user, password))
from neo4j import GraphDatabase

The basic authentication scheme can also be used to authenticate against an LDAP server.

2.3.2. Kerberos authentication

The Kerberos authentication scheme provides a simple way to create a Kerberos authentication token with a base64 encoded server authentication ticket. The best way to create a Kerberos authentication token is shown below:

Example 2.6. Kerberos authentication
public IDriver CreateDriverWithKerberosAuth(string uri, string ticket)
{
    return GraphDatabase.Driver(uri, AuthTokens.Kerberos(ticket),
        o => o.WithEncryptionLevel(EncryptionLevel.None));
}
public KerberosAuthExample( String uri, String ticket )
{
    driver = GraphDatabase.driver( uri, AuthTokens.kerberos( ticket ) );
}

Import Kerberos authentication. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

const driver = neo4j.driver(uri, neo4j.auth.kerberos(ticket))
def __init__(self, uri, ticket):
    self._driver = GraphDatabase.driver(uri, auth=kerberos_auth(ticket))
from neo4j import (
    GraphDatabase,
    kerberos_auth,
)

The Kerberos authentication token can only be understood by the server if the server has the Kerberos Add-on installed.

2.3.3. Custom authentication

For advanced deployments, where a custom security provider has been built, the custom authentication helper can be used.

Example 2.7. Custom authentication
public IDriver CreateDriverWithCustomizedAuth(string uri,
    string principal, string credentials, string realm, string scheme,
    Dictionary<string, object> parameters)
{
    return GraphDatabase.Driver(uri, AuthTokens.Custom(principal, credentials, realm, scheme, parameters),
        o=>o.WithEncryptionLevel(EncryptionLevel.None));
}
public CustomAuthExample( String uri, String principal, String credentials, String realm, String scheme,
        Map<String,Object> parameters )
{
    driver = GraphDatabase.driver( uri, AuthTokens.custom( principal, credentials, realm, scheme, parameters ) );
}

Import custom authentication. 

import java.util.Map;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

const driver = neo4j.driver(
  uri,
  neo4j.auth.custom(principal, credentials, realm, scheme, parameters)
)
def __init__(self, uri, principal, credentials, realm, scheme, **parameters):
    auth = custom_auth(principal, credentials, realm, scheme, **parameters)
    self.driver = GraphDatabase.driver(uri, auth=auth)
from neo4j import (
    GraphDatabase,
    custom_auth,
)

2.4. Configuration

ConnectionAcquisitionTimeout

The maximum amount of time a session will wait when requesting a connection from the connection pool. For connection pools where all connections are currently being used and the MaxConnectionPoolSize limit has been reached, a session will wait this duration for a connection to be made available. Since the process of acquiring a connection may involve creating a new connection, ensure that the value of this configuration is higher than the configured ConnectionTimeout.

Setting a low value will allow for transactions to fail fast when all connections in the pool have been acquired by other transactions. Setting a higher value will result in these transactions being queued, increasing the chances of eventually acquiring a connection at the cost of longer time to receive feedback on failure. Finding an optimal value may require an element of experimentation, taking into consideration the expected levels of parallelism within your application as well as the MaxConnectionPoolSize.

Default: 60 seconds

Example 2.8. Configure connection pool
public IDriver CreateDriverWithCustomizedConnectionPool(string uri, string user, string password)
{
    return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password),
        o => o.WithMaxConnectionLifetime(TimeSpan.FromMinutes(30))
            .WithMaxConnectionPoolSize(50)
            .WithConnectionAcquisitionTimeout(TimeSpan.FromMinutes(2)));
}
public ConfigConnectionPoolExample( String uri, String user, String password )
{
    Config config = Config.builder()
            .withMaxConnectionLifetime( 30, TimeUnit.MINUTES )
            .withMaxConnectionPoolSize( 50 )
            .withConnectionAcquisitionTimeout( 2, TimeUnit.MINUTES )
            .build();

    driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ), config );
}

Import connection pool configuration. 

import java.util.concurrent.TimeUnit;

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;
import org.neo4j.driver.Result;

const driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {
  maxConnectionLifetime: 3 * 60 * 60 * 1000, // 3 hours
  maxConnectionPoolSize: 50,
  connectionAcquisitionTimeout: 2 * 60 * 1000 // 120 seconds
})
def __init__(self, uri, auth):
    self.driver = GraphDatabase.driver(uri, auth=auth,
                                       max_connection_lifetime=30 * 60,
                                       max_connection_pool_size=50,
                                       connection_acquisition_timeout=2 * 60)
from neo4j import GraphDatabase
ConnectionTimeout

The maximum amount of time to wait for a TCP connection to be established. Connections are only created when a session requires one unless there is an available connection in the connection pool. The driver maintains a pool of open connections which can be loaned to a session when one is available. If a connection is not available, then an attempt to create a new connection (provided the MaxConnectionPoolSize limit has not been reached) is made with this configuration option, providing the maximum amount of time to wait for the connection to be established.

In environments with high latency and high occurrences of connection timeouts it is recommended to configure a higher value. For lower latency environments and quicker feedback on potential network issues configure with a lower value.

Default: 30 seconds

Example 2.9. Configure connection timeout
public IDriver CreateDriverWithCustomizedConnectionTimeout(string uri, string user, string password)
{
    return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password),
        o => o.WithConnectionTimeout(TimeSpan.FromSeconds(15)));
}
public ConfigConnectionTimeoutExample( String uri, String user, String password )
{
    Config config = Config.builder()
            .withConnectionTimeout( 15, SECONDS )
            .build();

    driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ), config );
}

Import connection timeout configuration. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

import static java.util.concurrent.TimeUnit.SECONDS;

const driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {
  connectionTimeout: 20 * 1000 // 20 seconds
})
def __init__(self, uri, auth):
    self.driver = GraphDatabase.driver(uri, auth=auth, connection_timeout=15)
from neo4j import GraphDatabase
CustomResolver
Specify a custom server address resolver used by the routing driver to resolve the initial address used to create the driver. See Section 2.2.1.3, “Resolver function” for more details.
Encryption

Specify whether to use an encrypted connection between the driver and server.

Default: None

Example 2.10. Unencrypted configuration
public IDriver CreateDriverWithCustomizedSecurityStrategy(string uri, string user, string password)
{
    return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password),
        o=>o.WithEncryptionLevel(EncryptionLevel.None));
}
public ConfigUnencryptedExample( String uri, String user, String password )
{
    Config config = Config.builder()
            .withoutEncryption()
            .build();

    driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ), config );
}

Import unencrypted configuration. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

const driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {
  encrypted: 'ENCRYPTION_OFF'
})
def __init__(self, uri, auth):
    self.driver = GraphDatabase.driver(uri, auth=auth, encrypted=False)
from neo4j import GraphDatabase
MaxConnectionLifetime

The maximum duration the driver will keep a connection for before being removed from the pool. Note that while the driver will respect this value, it is possible that the network environment will close connections inside this lifetime. This is beyond the control of the driver. The check on the connection’s lifetime happens when a session requires a connection. If the available connection’s lifetime is over this limit it is closed and a new connection is created, added to the pool and returned to the requesting session. Changing this configuration value would be useful in environments where users don’t have full control over the network environment and wish to proactively ensure all connections are ready.

Setting this option to a low value will cause a high connection churn rate, and can result in a performance drop. It is recommended to pick a value smaller than the maximum lifetime exposed by the surrounding system infrastructure (such as operating system, router, load balancer, proxy and firewall). Negative values result in lifetime not being checked.

Default: 1 hour (3600 seconds)

MaxConnectionPoolSize

The maximum total number of connections allowed, per host (i.e. cluster nodes), to be managed by the connection pool. In other words, for a direct driver using the bolt:// scheme, this sets the maximum number of connections towards a single database server. For a driver connected to a cluster using the neo4j:// scheme, this sets the maximum amount of connections per cluster member. If a session or transaction tries to acquire a connection at a time when the pool size is at its full capacity, it must wait until a free connection is available in the pool or the request to acquire a new connection times out. The connection acquiring timeout is configured via ConnectionAcquisitionTimeout.

This configuration option allows you to manage the memory and I/O resources being used by the driver and tuning this option is dependent on these factors, in addition to number of cluster members.

Default: 100 connections (except .NET Driver with 500 connections)

MaxTransactionRetryTime

The maximum amount of time that a managed transaction will retry for before failing. Queries that are executed within a managed transaction gain the benefit of being retried when a transient error occurs. When this happens the transaction is retired multiple times up to the MaxTransactionRetryTime.

Configure this option higher in high latency environments or if you are executing many large transactions which could limit the number of times that they are retired and therefore their chance to succeed. Configure lower in low latency environments and where your workload mainly consists of many smaller transactions. Failing transactions faster may highlight the reasons behind the transient errors making it easier to fix underlying issues.

Default: 30 seconds

Example 2.11. Configure maximum retry time
public IDriver CreateDriverWithCustomizedMaxRetryTime(string uri, string user, string password)
{
    return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password),
        o => o.WithMaxTransactionRetryTime(TimeSpan.FromSeconds(15)));
}
public ConfigMaxRetryTimeExample( String uri, String user, String password )
{
    Config config = Config.builder()
            .withMaxTransactionRetryTime( 15, SECONDS )
            .build();

    driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ), config );
}

Import maximum retry time configuration. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

import static java.util.concurrent.TimeUnit.SECONDS;

const maxRetryTimeMs = 15 * 1000 // 15 seconds
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {
  maxTransactionRetryTime: maxRetryTimeMs
})
def __init__(self, uri, auth):
    self.driver = GraphDatabase.driver(uri, auth=auth, max_transaction_retry_time=15)
from neo4j import GraphDatabase
TrustStrategy

Specify how to determine the authenticity of encryption certificates provided by the Neo4j instance that you are connecting to. There are three choices as to which strategy to use:

  • TRUST_SYSTEM_CA_SIGNED_CERTIFICATES - Accept any certificate that can be verified against a custom CA.
  • TRUST_CUSTOM_CA_SIGNED_CERTIFICATES - Accept any certificate that can be verified against the system store.
  • TRUST_ALL_CERTIFICATES - Accept any certificate provided by the server, regardless of CA chain. We do not recommend using this setting for production environments.

Default: TRUST_SYSTEM_CA_SIGNED_CERTIFICATES (Note - only when encryption is enabled)

Example 2.12. Configure trusted certificates
public IDriver CreateDriverWithCustomizedTrustStrategy(string uri, string user, string password)
{
    return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password),
        o => o.WithTrustManager(TrustManager.CreateInsecure()));
}
public ConfigTrustExample( String uri, String user, String password )
{
    Config config = Config.builder()
            .withTrustStrategy( Config.TrustStrategy.trustSystemCertificates() )
            .build();

    driver = GraphDatabase.driver( uri, AuthTokens.basic( user, password ), config );
}

Import trusted certificate configuration. 

import org.neo4j.driver.AuthTokens;
import org.neo4j.driver.Config;
import org.neo4j.driver.Driver;
import org.neo4j.driver.GraphDatabase;

const driver = neo4j.driver(uri, neo4j.auth.basic(user, password), {
  encrypted: 'ENCRYPTION_ON',
  trust: 'TRUST_ALL_CERTIFICATES'
})
def __init__(self, uri, auth):
    self.driver = GraphDatabase.driver(uri, auth=auth, encrypted=True, trust=TRUST_ALL_CERTIFICATES)
from neo4j import (
    GraphDatabase,
    TRUST_SYSTEM_CA_SIGNED_CERTIFICATES,
    TRUST_ALL_CERTIFICATES,
)
KeepAlive

Specify whether TCP keep-alive should be enabled. To ensure that the connection between the driver and server is still operational, the TCP layer can periodically send messages to check the connection.

Default: True

This is currently only configurable in the:

  • .NET Driver
  • Python Driver

2.5. Logging

All official Neo4j Drivers log information to standard logging channels. This can typically be accessed in an ecosystem-specific way.

The code snippets below show how to redirect log messages to standard output.

.NET

#Please note that you will have to provide your own console logger implementing the ILogger interface.
IDriver driver = GraphDatabase.Driver(..., o => o.WithLogger(logger));

Java

ConfigBuilder.withLogging(Logging.console(Level.DEBUG))

JavaScript

const loggingConfig = {logging: neo4j.logging.console('debug')};
const driver = neo4j.driver(..., loggingConfig);

Python

from logging import getLogger, StreamHandler, DEBUG
handler = StreamHandler()
handler.setLevel(DEBUG)
getLogger("neo4j").addHandler(handler)