Overview

EdgeDB uses a message-based binary protocol for communication between clients and servers. The protocol is supported over TCP/IP and also over Unix-domain sockets.

The message format descriptions in this section use a C-like struct definitions to describe their layout. The structs are packed, i.e. there are never any alignment gaps.

The following data types are used in the descriptions:

int8

8-bit integer

int8<T>

an 8-bit integer enumeration, where T denotes the name of the enumeration

int16

16-bit integer, most significant byte first

int32

32-bit integer, most significant byte first

int64

64-bit integer, most significant byte first

byte

8-bit unsigned integer

string

a UTF-8 encoded text string prefixed with its byte length as int16

bytes

a byte string prefixed with its length as int16

Headers

a key-value structure with the following layout:

struct Headers {
    int16  num_headers;
    Header headers[num_headers];
};

struct Header {
    int16  key;
    bytes  value;
};

All messages in the EdgeDB wire protocol have the following format:

struct {
    int8  message_type;
    int32 payload_length;
    int8  payload[payload_length - 4];
};

The server and the client MUST always send a complete message, i.e. the entire message must be buffered before initiating a network call. Conversely, when receiving a message, the recipient SHOULD buffer the incoming message before processing it.

At any point the server may send an ErrorResponse indicating an error condition. This is implied in the message flow documentation, and only successful paths are explicitly documented. The handling of the ErrorResponse message depends on the connection phase, as well as the severity of the error.

If the server is not able to recover from an error, the connection is closed immediately after an ErrorResponse message is sent.

Similarly to ErrorResponse the server may send a LogMessage message. The client should handle the message and continue as before.

The server by default accumulates its output messages in a buffer to minimize the number of network calls. Some messages, such as Sync and ReadyForCommand flush the server buffer automatically. In other cases, a client can send a Flush message to ask the server to flush its send buffer.

There are two main phases in the lifetime of an EdgeDB connection: the connection phase, and the command phase. The connection phase is responsible for negotiating the protocol and connection parameters, including authentication. The command phase is the regular operation phase where the server is processing queries sent by the client. In the command phase there are two possible command flows: the script flow and the granular flow.

To begin a session, a client opens a connection to the server, and sends the ClientHandshake. If the requested connection parameters cannot be fully satisfied, the server responds with ServerHandshake to offer the protocol parameters it is willing to support.

The server then initiates the authentication cycle by sending an authentication request message, to which the client must respond with an appropriate authentication response message.

The following messages are sent by the server in the authentication cycle:

AuthenticationOK

Authentication is successful.

AuthenticationSASL

The client must now initiate a SASL negotiation, using one of the SASL mechanisms listed in the message. The client will send a AuthenticationSASLInitialResponse with the name of the selected mechanism, and the first part of the SASL data stream in response to this. If further messages are needed, the server will respond with AuthenticationSASLContinue.

AuthenticationSASLContinue

This message contains challenge data from the previous step of SASL negotiation (AuthenticationSASL, or a previous AuthenticationSASLContinue). The client must respond with a AuthenticationSASLResponse message.

AuthenticationSASLFinal

SASL authentication has completed with additional mechanism-specific data for the client. The server will next send AuthenticationOK to indicate successful authentication, or an ErrorResponse to indicate failure. This message is sent only if the SASL mechanism specifies additional data to be sent from server to client at completion.

If the frontend does not support the authentication method requested by the server, then it should immediately close the connection.

Once the server has confirmed successful authentication with AuthenticationOK, it then sends one or more of the following messages:

ServerKeyData

This message provides per-connection secret-key data that the client must save if it wants to be able to issue certain requests later. The client should not respond to this message.

ParameterStatus

This message informs the frontend about the setting of certain server parameters. The client can ignore this message, or record the settings for its future use. The client should not respond to this message.

The connection phase ends when the server sends the first ReadyForCommand message, indicating the start of a command cycle.

In the command phase, the server can be in one of the three main states:

  • idle: server is waiting for a command;

  • busy: server is executing a command;

  • error: server encountered an error and is discarding incoming messages.

Whenever a server switches to the idle state, it sends a ReadyForCommand message.

Whenever a server encounters an error, it sends a ErrorResponse message. If an error occurred during a granular command flow, the server switches into the error state, otherwise it switches into idle directly.

To switch a server from the error state into the idle state, a Sync message must be sent by the client.

In a script command flow the client follows the server’s ReadyForCommand message with a ExecuteScript message. The message includes one or more EdgeQL commands as a text string. The server then sends a CommandComplete message if the command (or commands) completed successfully, or ErrorResponse in case of an error. The CommandComplete corresponds to the last command in the script.

The script flow is not designed to return any data beyond that included in the CommandComplete message.

EdgeQL scripts are executed in an implicit transaction block, except when a script contains a single command that cannot be executed inside a transaction.

The granular flow is designed to execute EdgeQL commands one-by-one with a series of messages. This flow should be used whenever data needs to be returned from a command, or arguments passed to a command.

In this mode the server expects the client to send one of the following messages:

Prepare

Instructs the server to process and prepare the provided command for execution. The server responds with a PrepareComplete message containing the unique identifier of the statement type descriptor. The client may then send a DescribeStatement if it requires the type descriptor data.

DescribeStatement

Asks the server to return the type descriptor data for a prepared statement. This message is only valid following the receipt of PrepareComplete. The server responds with a CommandDataDescription message.

Execute

Execute a previously prepared command. The server responds with zero or more Data messages, followed by a CommandComplete.

Optimistic Execute

Execute the provided command text directly, assuming prior knowledge of the type descriptor data. This allows the client to perform the prepare/execute operation in a single step. The server responds with zero or more Data messages, followed by a CommandComplete.

All EdgeDB commands (with the exception of a few DDL commands) execute in a transaction block. An explicit transaction block is started by a START TRANSACTION command. If not within an explicit transaction, an implicit transaction block is started when the first message is received by the server. If a START TRANSACTION command is executed in an implicit transaction block, that block becomes explicit. An implicit transaction block ends if:

  • a COMMIT command is executed,

  • a ROLLBACK command is executed,

  • a Sync message is received.

The normal termination procedure is that the client sends a Terminate message and immediately closes the connection. On receipt of this message, the server cleans up the connection resources and closes the connection.

In some cases the server might disconnect without a client request to do so. In such cases the server will attempt to send an ErrorResponse or a LogMessage message to indicate the reason for the disconnection.