52.9. Logical Replication Message Formats

This section describes the detailed format of each logical replication message. These messages are returned either by the replication slot SQL interface or are sent by a walsender. In case of a walsender they are encapsulated inside the replication protocol WAL messages as described in Section 52.4 and generally obey same message flow as physical replication.

Begin
Byte1('B')

Identifies the message as a begin message.

Int64

The final LSN of the transaction.

Int64

Commit timestamp of the transaction. The value is in number of microseconds since PostgreSQL epoch (2000-01-01).

Int32

Xid of the transaction.

Commit
Byte1('C')

Identifies the message as a commit message.

Int8

Flags; currently unused (must be 0).

Int64

The LSN of the commit.

Int64

The end LSN of the transaction.

Int64

Commit timestamp of the transaction. The value is in number of microseconds since PostgreSQL epoch (2000-01-01).

Origin
Byte1('O')

Identifies the message as an origin message.

Int64

The LSN of the commit on the origin server.

String

Name of the origin.

Note that there can be multiple Origin messages inside a single transaction.

Relation
Byte1('R')

Identifies the message as a relation message.

Int32

ID of the relation.

String

Namespace (empty string for pg_catalog).

String

Relation name.

Int8

Replica identity setting for the relation (same as relreplident in pg_class).

Int16

Number of columns.

Next, the following message part appears for each column:

Int8

Flags for the column. Currently can be either 0 for no flags or 1 which marks the column as part of the key.

String

Name of the column.

Int32

ID of the column's data type.

Int32

Type modifier of the column (atttypmod).

Type
Byte1('Y')

Identifies the message as a type message.

Int32

ID of the data type.

String

Namespace (empty string for pg_catalog).

String

Name of the data type.

Insert
Byte1('I')

Identifies the message as an insert message.

Int32

ID of the relation corresponding to the ID in the relation message.

Byte1('N')

Identifies the following TupleData message as a new tuple.

TupleData

TupleData message part representing the contents of new tuple.

Update
Byte1('U')

Identifies the message as an update message.

Int32

ID of the relation corresponding to the ID in the relation message.

Byte1('K')

Identifies the following TupleData submessage as a key. This field is optional and is only present if the update changed data in any of the column(s) that are part of the REPLICA IDENTITY index.

Byte1('O')

Identifies the following TupleData submessage as an old tuple. This field is optional and is only present if table in which the update happened has REPLICA IDENTITY set to FULL.

TupleData

TupleData message part representing the contents of the old tuple or primary key. Only present if the previous 'O' or 'K' part is present.

Byte1('N')

Identifies the following TupleData message as a new tuple.

TupleData

TupleData message part representing the contents of a new tuple.

The Update message may contain either a 'K' message part or an 'O' message part or neither of them, but never both of them.

Delete
Byte1('D')

Identifies the message as a delete message.

Int32

ID of the relation corresponding to the ID in the relation message.

Byte1('K')

Identifies the following TupleData submessage as a key. This field is present if the table in which the delete has happened uses an index as REPLICA IDENTITY.

Byte1('O')

Identifies the following TupleData message as a old tuple. This field is present if the table in which the delete has happened has REPLICA IDENTITY set to FULL.

TupleData

TupleData message part representing the contents of the old tuple or primary key, depending on the previous field.

The Delete message may contain either a 'K' message part or an 'O' message part, but never both of them.

The following message parts are shared by the above messages.

TupleData
Int16

Number of columns.

Next, one of the following submessages appears for each column:

Byte1('n')

Identifies the data as NULL value.

Or

Byte1('u')

Identifies unchanged TOASTed value (the actual value is not sent).

Or

Byte1('t')

Identifies the data as text formatted value.

Int32

Length of the column value.

Byten

The value of the column, in text format. (A future release might support additional formats.) n is the above length.