21.2. Bolt Transport Layer

The protocol supports both regular socket and WebSocket transport layers for sending and receiving messages. The transport layer is versioned along with the rest of the data protocol and is responsible for:

  • Negotiating Neo4j protocol version
  • Establishing and terminating sessions
  • Routing messages from clients to specific sessions and back

Sessions

Each connection to the server creates a new session that lives until that connection is closed. Each session is isolated and the server keep track of the current state, based on the requests and responses exchanged within that session.

Neo4j uses sticky sessions, which means that, in a database cluster, each session is tied to one specific Neo4j instance.

Connecting

To begin a new session, the client connects using either a regular socket or a WebSocket. Once connected, both transport layers can be treated identically.

If Neo4j has been configured to enable encryption, TLS, the connections need to be made using a secure socket or a secure WebSocket.

A regular socket connection should be made to the host and port Neo4j has been configured to use for its regular socket listener. The default port for regular socket connections is 7687. Similar configuration exists for the WebSocket listener. The default port for WebSocket connections is 7688.

[Important]Important

If TLS is enabled, and no certificate has been specified, Neo4j will automatically generate a self-signed TLS certificate. It is vital that your database driver not simply accept any certificate without validating it. If you do not verify the certificate it is very simple to bypass the encryption. You should either ensure you have a valid signed certificate installed with Neo4j or that your application implements trust on first use.

Handshake

After connecting, a handshake takes place to establish which Bolt protocol version should be used for that connection. This handshake is a version-independent mini-protocol which is guaranteed to remain the same, regardless of preferred or available protocol versions.

In the handshake, the client fist sends a magic four byte preamble (6060 B017) followed by four protocol versions it supports, in order of preference. The proposal is always represented as four 32-bit unsigned integers. Each integer represents a proposed protocol version to use, or zero (00 00 00 00) for "none".

The server will respond with a single 32-bit unsigned integer representing the chosen protocol. This will always represent the highest-priority protocol version the server supports. If none of the proposed protocols are supported, the server responds with zero (00 00 00 00) and closes the connection.

Initial handshake 

Client: <connect>
Client: 60 60 B0 17
Client: 00 00 00 01  00 00 00 00  00 00 00 00  00 00 00 00
      #  Version 1      None         None         None

Server: 00 00 00 01
      #   Choose
      #  version 1

No supported version 

Client: <connect>
Client: 60 60 B0 17
Client: 00 00 00 06  00 00 00 00  00 00 00 00  00 00 00 00
      #   Version 6      None         None         None

Server: 00 00 00 00
      #    None
      #  supported

Server: <disconnect>

Message framing

The transport protocol uses a framing layer to wrap messages.

Each message is transferred as one or more chunks of data. Each chunk starts with a two-byte header, an unsigned big-endian 16-bit integer, representing the size of the chunk not including the header. A message can be divided across multiple chunks, allowing client and server alike to transfer large messages without having to determine the length of the entire message in advance.

Each message ends with two bytes with the value 00 00, these are not counted towards the chunk length.

A message in one chunk 

Chunk size: 16
Message data: 00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F

00 10  00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F  00 00
chunk  |                    Message                     |   End
header |                     Data                       |  Marker

A message split in two chunks 

Chunk size: 16
Message data: 00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F  01 02 03 04

00 10  00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F  00 04  01 02 03 04  00 00
chunk1 |                    Message                     |  chunk2 | Message |   End
header |                     Data                       |  header |  Data   |  Marker

Two messages 

Chunk size: 16
Message 1 data: 00 01 02 03  04 05 06 07  08 09 0A 0B  0C  0D 0E 0F
Message 2 data: 0F 0E 0D 0C  0B 0A 09 08

00 10  00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F  00 00
chunk  |                   Message 1                    |   End
header |                     Data                       |  Marker

00 08  0F 0E 0D 0C  0B 0A 09 08  00 00
chunk  |       Message 2      |   End
header |         Data         |  Marker

Disconnecting

A session ends when its communication socket is closed. Typically, this will be closed by the client.