From 57a38f1734e09a508c44ad702ac015121f6d5d5d Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Fri, 23 Jan 2026 10:26:32 +0100 Subject: [PATCH 1/9] Clarify how to connect to clusters --- common-content/modules/ROOT/partials/connect.adoc | 12 ++++++++++++ python-manual/modules/ROOT/pages/connect.adoc | 3 +++ 2 files changed, 15 insertions(+) create mode 100644 common-content/modules/ROOT/partials/connect.adoc diff --git a/common-content/modules/ROOT/partials/connect.adoc b/common-content/modules/ROOT/partials/connect.adoc new file mode 100644 index 00000000..51c9d412 --- /dev/null +++ b/common-content/modules/ROOT/partials/connect.adoc @@ -0,0 +1,12 @@ +# tag::cluster[] + +[[cluster]] +== Connect to a cluster + +You connect to a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster] by using the address of any machine belonging to it. +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. + +You can override the default DNS resolution via a xref:connect-advanced.adoc#_custom_address_resolver[Custom address resolver]. +You can also connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + +# end::cluster[] diff --git a/python-manual/modules/ROOT/pages/connect.adoc b/python-manual/modules/ROOT/pages/connect.adoc index f822f751..b30f16d3 100644 --- a/python-manual/modules/ROOT/pages/connect.adoc +++ b/python-manual/modules/ROOT/pages/connect.adoc @@ -66,6 +66,9 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +include::{common-partial}/connect.adoc[tag=cluster] + + == Close connections Always close `Driver` objects to free up all allocated resources, even upon unsuccessful connection or runtime errors. From 801eb2925f124f764c30cf72852a8d11aaf02fa7 Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Tue, 27 Jan 2026 10:03:48 +0100 Subject: [PATCH 2/9] more --- .../modules/ROOT/partials/connect.adoc | 29 ++++++++++++++++--- .../modules/ROOT/pages/connect-advanced.adoc | 6 +++- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/common-content/modules/ROOT/partials/connect.adoc b/common-content/modules/ROOT/partials/connect.adoc index 51c9d412..4f1a80e1 100644 --- a/common-content/modules/ROOT/partials/connect.adoc +++ b/common-content/modules/ROOT/partials/connect.adoc @@ -3,10 +3,31 @@ [[cluster]] == Connect to a cluster -You connect to a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster] by using the address of any machine belonging to it. -Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. -You can override the default DNS resolution via a xref:connect-advanced.adoc#_custom_address_resolver[Custom address resolver]. -You can also connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, python] +---- +from neo4j import GraphDatabase + + +def custom_resolver(socket_address): + yield "server01.example.com", 7687 + yield "server02.example.com", 7687 + yield "server03.example.com", 7687 + yield "backup.another.com", 7687 + + +driver = GraphDatabase.driver( + "neo4j://example.com:7687", auth=(USERNAME, PASSWORD), + resolver=custom_resolver) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). # end::cluster[] diff --git a/python-manual/modules/ROOT/pages/connect-advanced.adoc b/python-manual/modules/ROOT/pages/connect-advanced.adoc index ba7ff7bf..042479a6 100644 --- a/python-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/python-manual/modules/ROOT/pages/connect-advanced.adoc @@ -206,10 +206,14 @@ cert_provider.update_certificate( For more information, see link:https://neo4j.com/docs/api/python-driver/current/api.html#neo4j.auth_management.ClientCertificateProvider[API docs -> `ClientCertificateProvider`]. +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve any addresses the driver receives ahead of DNS resolution. -Your resolver function is called with an link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] object and should return an iterable of link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] objects (or values that can be used to construct `Address` objects) +Your resolver function is called with an link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] object and should return an iterable of link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] objects (or values that can be used to construct `Address` objects). + +The resolved address(es) must have the same URI scheme as the initial one. In the example below, the driver is initialized with a `neo4j://` URI scheme, so the resolved addresses must also be available at `neo4j://`. + .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, python] From 95b2858d28bc028970aa0e4a33f0e4c5c76e8c82 Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Tue, 27 Jan 2026 10:21:44 +0100 Subject: [PATCH 3/9] final python --- common-content/modules/ROOT/partials/connect.adoc | 2 +- python-manual/modules/ROOT/pages/connect-advanced.adoc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common-content/modules/ROOT/partials/connect.adoc b/common-content/modules/ROOT/partials/connect.adoc index 4f1a80e1..cd7437ec 100644 --- a/common-content/modules/ROOT/partials/connect.adoc +++ b/common-content/modules/ROOT/partials/connect.adoc @@ -19,7 +19,7 @@ def custom_resolver(socket_address): yield "server01.example.com", 7687 yield "server02.example.com", 7687 yield "server03.example.com", 7687 - yield "backup.another.com", 7687 + yield "backup.example.org", 7687 driver = GraphDatabase.driver( diff --git a/python-manual/modules/ROOT/pages/connect-advanced.adoc b/python-manual/modules/ROOT/pages/connect-advanced.adoc index 042479a6..32c780b7 100644 --- a/python-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/python-manual/modules/ROOT/pages/connect-advanced.adoc @@ -212,8 +212,8 @@ For more information, see link:https://neo4j.com/docs/api/python-driver/current/ When creating a `Driver` object, you can specify a _resolver_ function to resolve any addresses the driver receives ahead of DNS resolution. Your resolver function is called with an link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] object and should return an iterable of link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] objects (or values that can be used to construct `Address` objects). -The resolved address(es) must have the same URI scheme as the initial one. In the example below, the driver is initialized with a `neo4j://` URI scheme, so the resolved addresses must also be available at `neo4j://`. - +[NOTE] +`Address` objects don't carry a scheme, so a custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, python] From 5cb7090b2a6f76cb9cf5e986cb933a0a0ec05a4c Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Tue, 27 Jan 2026 10:32:07 +0100 Subject: [PATCH 4/9] java --- .../modules/ROOT/pages/connect-advanced.adoc | 6 ++- java-manual/modules/ROOT/pages/connect.adoc | 39 +++++++++++++++++++ .../modules/ROOT/pages/connect-advanced.adoc | 2 +- python-manual/modules/ROOT/pages/connect.adoc | 30 +++++++++++++- 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/java-manual/modules/ROOT/pages/connect-advanced.adoc b/java-manual/modules/ROOT/pages/connect-advanced.adoc index f8018ac9..adf5b036 100644 --- a/java-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/java-manual/modules/ROOT/pages/connect-advanced.adoc @@ -287,13 +287,17 @@ java.util.logging.ConsoleHandler.level = FINE ---- +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. -Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. +Note that addresses that the driver receives in routing tables are not resolved with the custom resolver: the custom resolver is only used for the initial connection. You specify a resolver through the link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/Config.ConfigBuilder.html#withResolver(org.neo4j.driver.net.ServerAddressResolver)[`.withResolver()`] config method, which works with link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/net/ServerAddress.html[`ServerAddress`] objects. +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). + .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, java] ---- diff --git a/java-manual/modules/ROOT/pages/connect.adoc b/java-manual/modules/ROOT/pages/connect.adoc index 0e49d00c..3291e18d 100644 --- a/java-manual/modules/ROOT/pages/connect.adoc +++ b/java-manual/modules/ROOT/pages/connect.adoc @@ -90,6 +90,45 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, java] +---- +// import java.util.Set; +// import org.neo4j.driver.AuthTokens; +// import org.neo4j.driver.Config; +// import org.neo4j.driver.GraphDatabase; +// import org.neo4j.driver.net.ServerAddress; + +var addresses = Set.of( + ServerAddress.of("server01.example.com", 7687), + ServerAddress.of("server02.example.com", 7687), + ServerAddress.of("server03.example.com", 7687), + ServerAddress.of("backup.example.org", 7687) +); +var config = Config.builder() + .withResolver(address -> addresses) + .build(); +try (var driver = GraphDatabase.driver( + "neo4j://example.com:7687", + AuthTokens.basic(dbUser, dbPassword), + config)) { + driver.verifyConnectivity(); +} +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `Driver` objects to free up all allocated resources, even upon unsuccessful connection or runtime errors. diff --git a/python-manual/modules/ROOT/pages/connect-advanced.adoc b/python-manual/modules/ROOT/pages/connect-advanced.adoc index 32c780b7..5d9f32b7 100644 --- a/python-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/python-manual/modules/ROOT/pages/connect-advanced.adoc @@ -213,7 +213,7 @@ When creating a `Driver` object, you can specify a _resolver_ function to resolv Your resolver function is called with an link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] object and should return an iterable of link:{neo4j-docs-base-uri}/api/python-driver/current/api.html#neo4j.Address[`Address`] objects (or values that can be used to construct `Address` objects). [NOTE] -`Address` objects don't carry a scheme, so a custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, python] diff --git a/python-manual/modules/ROOT/pages/connect.adoc b/python-manual/modules/ROOT/pages/connect.adoc index b30f16d3..e45a4ca3 100644 --- a/python-manual/modules/ROOT/pages/connect.adoc +++ b/python-manual/modules/ROOT/pages/connect.adoc @@ -66,7 +66,35 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. -include::{common-partial}/connect.adoc[tag=cluster] +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, python] +---- +from neo4j import GraphDatabase + + +def custom_resolver(socket_address): + yield "server01.example.com", 7687 + yield "server02.example.com", 7687 + yield "server03.example.com", 7687 + yield "backup.example.org", 7687 + + +driver = GraphDatabase.driver( + "neo4j://example.com:7687", auth=(USERNAME, PASSWORD), + resolver=custom_resolver) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). == Close connections From 2cf9b7e585937017a9987286e2d579c9cd52e168 Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Tue, 27 Jan 2026 10:39:30 +0100 Subject: [PATCH 5/9] js --- .../modules/ROOT/partials/connect.adoc | 33 ------------------- .../modules/ROOT/pages/connect-advanced.adoc | 6 +++- .../modules/ROOT/pages/connect.adoc | 28 ++++++++++++++++ 3 files changed, 33 insertions(+), 34 deletions(-) delete mode 100644 common-content/modules/ROOT/partials/connect.adoc diff --git a/common-content/modules/ROOT/partials/connect.adoc b/common-content/modules/ROOT/partials/connect.adoc deleted file mode 100644 index cd7437ec..00000000 --- a/common-content/modules/ROOT/partials/connect.adoc +++ /dev/null @@ -1,33 +0,0 @@ -# tag::cluster[] - -[[cluster]] -== Connect to a cluster - -When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. - -Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. - -- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. -- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + -+ -[source, python] ----- -from neo4j import GraphDatabase - - -def custom_resolver(socket_address): - yield "server01.example.com", 7687 - yield "server02.example.com", 7687 - yield "server03.example.com", 7687 - yield "backup.example.org", 7687 - - -driver = GraphDatabase.driver( - "neo4j://example.com:7687", auth=(USERNAME, PASSWORD), - resolver=custom_resolver) ----- -- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. - -You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). - -# end::cluster[] diff --git a/javascript-manual/modules/ROOT/pages/connect-advanced.adoc b/javascript-manual/modules/ROOT/pages/connect-advanced.adoc index 19641279..5d201492 100644 --- a/javascript-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/javascript-manual/modules/ROOT/pages/connect-advanced.adoc @@ -184,10 +184,14 @@ clientCertificateProvider.updateCertificate({ ===== +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. -Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. +Note that addresses that the driver receives in routing tables are not resolved with the custom resolver: the custom resolver is only used for the initial connection. + +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, javascript] diff --git a/javascript-manual/modules/ROOT/pages/connect.adoc b/javascript-manual/modules/ROOT/pages/connect.adoc index 9e11988a..7ea631b4 100644 --- a/javascript-manual/modules/ROOT/pages/connect.adoc +++ b/javascript-manual/modules/ROOT/pages/connect.adoc @@ -93,6 +93,34 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, javascript] +---- +let URI = 'neo4j://example.com:7687' +let addresses = [ + 'server01.example.com:7687', + 'server02.example.com:7687', + 'server03.example.com:7687', + 'backup.example.org:7687' +] +let driver = neo4j.driver(URI, neo4j.auth.basic(USER, PASSWORD), { + resolver: address => addresses +}) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `Driver` objects via `Driver.close()` to free up all allocated resources, even upon unsuccessful connection or runtime errors. From 882a0b61efa1fbb255334d766cd8347d3430d80f Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Wed, 28 Jan 2026 13:02:40 +0100 Subject: [PATCH 6/9] c# and go --- dotnet-manual/modules/ROOT/pages/connect.adoc | 48 +++++++++++++++++++ .../modules/ROOT/pages/connect-advanced.adoc | 1 + go-manual/modules/ROOT/pages/connect.adoc | 35 ++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/dotnet-manual/modules/ROOT/pages/connect.adoc b/dotnet-manual/modules/ROOT/pages/connect.adoc index 92eff5c7..99743dcf 100644 --- a/dotnet-manual/modules/ROOT/pages/connect.adoc +++ b/dotnet-manual/modules/ROOT/pages/connect.adoc @@ -72,6 +72,54 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, csharp, test-skip] +---- +using Neo4j.Driver; + +const string dbUser = ""; +const string dbPassword = ""; + +var addresses = new ListAddressResolver( + ServerAddress.From("server01.example.com", 7687), + ServerAddress.From("server02.example.com", 7687), + ServerAddress.From("server03.example.com", 7687), + ServerAddress.From("backup.example.org", 7687) +); + +await using var driver = GraphDatabase.Driver( + "neo4j://example.com:7687", + AuthTokens.Basic(dbUser, dbPassword), + conf => conf.WithResolver(addresses) +); +await driver.VerifyConnectivityAsync(); + +class ListAddressResolver : IServerAddressResolver { + private readonly ServerAddress[] _servers; + + public ListAddressResolver(params ServerAddress[] servers) { + _servers = servers; + } + + public ISet Resolve(ServerAddress address) { + return new HashSet(_servers); + } +} +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Close connections Always close `IDriver` objects to free up all allocated resources, even upon unsuccessful connection or runtime errors. diff --git a/go-manual/modules/ROOT/pages/connect-advanced.adoc b/go-manual/modules/ROOT/pages/connect-advanced.adoc index 2e30440e..0a0b98e1 100644 --- a/go-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/go-manual/modules/ROOT/pages/connect-advanced.adoc @@ -177,6 +177,7 @@ if err != nil { For more information, see link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/auth#ClientCertificateProvider[API docs -> `ClientCertificateProvider`]. +[#custom-address-resolver] == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. diff --git a/go-manual/modules/ROOT/pages/connect.adoc b/go-manual/modules/ROOT/pages/connect.adoc index 34620d2c..486e23d3 100644 --- a/go-manual/modules/ROOT/pages/connect.adoc +++ b/go-manual/modules/ROOT/pages/connect.adoc @@ -104,6 +104,41 @@ An Aura instance is not conceptually different from any other Neo4j instance, as When interacting with a Neo4j database through the driver, it doesn't make a difference whether it is an Aura instance it is working with or a different deployment. +[[cluster]] +== Connect to a cluster + +When working with a link:https://neo4j.com/docs/operations-manual/current/clustering/[Neo4j cluster], you have a few options to connect to it, depending on how it's deployed. + +Upon connection, the driver gets a _routing table_ containing information about all the machines in the cluster (including their roles), and will point requests to primaries or secondaries as needed. The routing table is periodically refreshed. + +- If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. +- If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + ++ +[source, go] +---- +// import "github.com/neo4j/neo4j-go-driver/v6/neo4j/config" + +addresses := []config.ServerAddress{ + neo4j.NewServerAddress("server01.example.com", "7687"), + neo4j.NewServerAddress("server02.example.com", "7687"), + neo4j.NewServerAddress("server03.example.com", "7687"), + neo4j.NewServerAddress("backup.example.org", "7687"), +} + +driver, err := neo4j.NewDriver( + "neo4j://example.com:7687", neo4j.BasicAuth(dbUser, dbPassword, ""), + func(conf *config.Config) { + conf.AddressResolver = func(address config.ServerAddress) []config.ServerAddress { + return addresses + } +}) +defer driver.Close(ctx) +---- +- You can also use the address of any machine belonging to the cluster: the driver will discover the others. This is the least fail-safe option, because if the machine you use as entrypoint becomes unavailable, the driver won't be able to fetch a routing table. + +You can also bypass the routing table and connect to a specific machine in the cluster using its address together with the `bolt[+s[sc]]://` scheme (see xref:connect-advanced.adoc#_connection_uri[connection URI] for more information). + + == Further connection parameters For more `Driver` configuration parameters and further connection settings, see xref:connect-advanced.adoc[Advanced connection information]. From 66b4eadd91bcbbf771126f6b24265b64792a3d9e Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Wed, 28 Jan 2026 13:05:10 +0100 Subject: [PATCH 7/9] missing note --- go-manual/modules/ROOT/pages/connect-advanced.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go-manual/modules/ROOT/pages/connect-advanced.adoc b/go-manual/modules/ROOT/pages/connect-advanced.adoc index 0a0b98e1..804ddd1f 100644 --- a/go-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/go-manual/modules/ROOT/pages/connect-advanced.adoc @@ -184,6 +184,9 @@ When creating a `Driver` object, you can specify a _resolver_ function to resolv Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. Your resolver function is called with a link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/config#ServerAddress[`ServerAddress`] object and should return a list of link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/config#ServerAddress[`ServerAddress`] objects. +[NOTE] +A custom address resolver cannot alter the URI scheme (`neo4j://` in the example below). + .Connection to `example.com` on port `9999` is resolved to `localhost` on port `7687` [source, go] ---- From d7f6b3a87ae8b68c3d6c99c14cca57b2ad7725bd Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Wed, 28 Jan 2026 14:09:21 +0100 Subject: [PATCH 8/9] test skip --- java-manual/modules/ROOT/pages/connect.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-manual/modules/ROOT/pages/connect.adoc b/java-manual/modules/ROOT/pages/connect.adoc index 3291e18d..1556b6fe 100644 --- a/java-manual/modules/ROOT/pages/connect.adoc +++ b/java-manual/modules/ROOT/pages/connect.adoc @@ -100,7 +100,7 @@ Upon connection, the driver gets a _routing table_ containing information about - If the cluster members are all link:https://neo4j.com/docs/operations-manual/current/clustering/setup/discovery/#clustering-discovery-dns[discoverable] via a hostname that provides multiple `A`/`AAAA` records, you can use the hostname and port. - If the addresses of the cluster members are known, but not advertised via `A`/`AAAA` records, you can use a xref:connect-advanced.adoc#custom-address-resolver[Custom address resolver] to extend the DNS resolution on the client side. + + -[source, java] +[source, java, test-skip] ---- // import java.util.Set; // import org.neo4j.driver.AuthTokens; From 9d11e4ab6c497e691094675d504895cedc5e7f8f Mon Sep 17 00:00:00 2001 From: Stefano Ottolenghi Date: Thu, 29 Jan 2026 18:01:10 +0100 Subject: [PATCH 9/9] Update connect-advanced.adoc --- go-manual/modules/ROOT/pages/connect-advanced.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go-manual/modules/ROOT/pages/connect-advanced.adoc b/go-manual/modules/ROOT/pages/connect-advanced.adoc index 804ddd1f..fe5e500b 100644 --- a/go-manual/modules/ROOT/pages/connect-advanced.adoc +++ b/go-manual/modules/ROOT/pages/connect-advanced.adoc @@ -181,7 +181,7 @@ For more information, see link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driv == Custom address resolver When creating a `Driver` object, you can specify a _resolver_ function to resolve the connection address the driver is initialized with. -Note that addresses that the driver receives in routing tables are not resolved with the custom resolver. +Note that addresses that the driver receives in routing tables are not resolved with the custom resolver: the custom resolver is only used for the initial connection. Your resolver function is called with a link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/config#ServerAddress[`ServerAddress`] object and should return a list of link:https://pkg.go.dev/github.com/neo4j/neo4j-go-driver/v6/neo4j/config#ServerAddress[`ServerAddress`] objects. [NOTE]