{"kind": "decode", "major": "18", "item": {"slug": "pgoutput", "name": "pgoutput", "name_zh": "Core replication", "category": "Core replication", "summary": "The built-in output plugin used by PostgreSQL logical replication.", "aliases": [], "content_hash": "1988aae57b9e4ed3ba61ac20f8b6bffbdb067f30880742d4e9b4ecb4d3d667cc", "versions": {"10": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "6"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "No handler registered in this build", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Logical messages", "callback": "message_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "proto_version"}, {"name": "publication_names"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/10/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=10", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=10", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=10", "label": "Logical tuple representation"}], "release": {"ref": "PostgreSQL 10.23 source archive", "label": "10.23", "major": "10", "channel": "historical", "revision": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9", "source_url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/10/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 10 English manual", "sha256": "482a3652a629e1e1ba6c0c8bf057a3bb6daed03fb1e6b5645810a1ac6277ad7a"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "line": 76, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:76", "sha256": "5de5619f25e44e4084481c4a6465cfb90f5b13c00a37fd1f0ea2f8a43cc9986e", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "/docs/10/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 10 English manual", "sha256": "c023fc2750375bbd45d810f49639e224a847e4ee32db70bdc154b26c397498bc"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "fcb4f0e0f869e6b5bcf80546759b82c9b3582043857dd9986852dbc8aee06798", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->commit_cb = pgoutput_commit_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "filter_by_origin_cb": "pgoutput_origin_filter"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">52.5.\u00a0Logical Streaming Replication Protocol</h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.1.\u00a0Logical Streaming Replication Parameters</h3>\n</div>\n</div>\n</div>\n<p>The logical replication <code class=\"literal\">START_REPLICATION</code> command accepts following parameters:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently only version <code class=\"literal\">1</code> is supported.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.2.\u00a0Logical Replication Protocol Messages</h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/10/protocol-logicalrep-message-formats.html\" title=\"52.9.\u00a0Logical Replication Message Formats\">Section\u00a052.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.3.\u00a0Logical Replication Protocol Message Flow</h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/10/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "filter_by_origin_cb": "pgoutput_origin_filter"}, "source_options": ["proto_version", "publication_names"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1"}}, "comparison_hash": "0aedb7aff9c6ae921c284af0b0cb8efe1460933e81b0608192b68ca8be9c1ab3", "runtime_verified": false}, "11": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "7"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "No handler registered in this build", "feature": "Logical messages", "callback": "message_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "proto_version"}, {"name": "publication_names"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/11/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=11", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=11", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=11", "label": "Logical tuple representation"}], "release": {"ref": "PostgreSQL 11.22 source archive", "label": "11.22", "major": "11", "channel": "historical", "revision": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0", "source_url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/11/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 11 English manual", "sha256": "e407a7f8617f41582d64119f002b64da565da6ab4b4128c4fe45a59db8b70c79"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "line": 78, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:78", "sha256": "e6deb5f7135f5f67899429e60d5a6bfc445a5421c13428ade4010ea99f0c8972", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "/docs/11/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 11 English manual", "sha256": "69b72c5a11a8905c173c8db4a5322f1d58e7876cbc706c7f4feb99402b6ab274"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "2a9e8cef369b4b4a26f603bba781c7cd567aa7d014186589c98b177613eff545", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->commit_cb = pgoutput_commit_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">53.5.\u00a0Logical Streaming Replication Protocol</h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.1.\u00a0Logical Streaming Replication Parameters</h3>\n</div>\n</div>\n</div>\n<p>The logical replication <code class=\"literal\">START_REPLICATION</code> command accepts following parameters:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently only version <code class=\"literal\">1</code> is supported.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.2.\u00a0Logical Replication Protocol Messages</h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/11/protocol-logicalrep-message-formats.html\" title=\"53.9.\u00a0Logical Replication Message Formats\">Section\u00a053.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.3.\u00a0Logical Replication Protocol Message Flow</h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/11/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "source_options": ["proto_version", "publication_names"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1"}}, "comparison_hash": "d5b89f0ab347e450fe25944edd36f88a3ed8974573075374de94ee865149c73d", "runtime_verified": false}, "12": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "7"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "No handler registered in this build", "feature": "Logical messages", "callback": "message_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported. A valid version is required."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "proto_version"}, {"name": "publication_names"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/12/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=12", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=12", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=12", "label": "Logical tuple representation"}], "release": {"ref": "PostgreSQL 12.22 source archive", "label": "12.22", "major": "12", "channel": "historical", "revision": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b", "source_url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/12/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 12 English manual", "sha256": "3e244d08ef9497ae1aeddd890a46e88b71e4cf37cfae4aa00f4b886001d98a61"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "line": 78, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:78", "sha256": "de46941d14a8b988b06b7638f5d451d4d7549a47c16741bab26690ba4c316755", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "/docs/12/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 12 English manual", "sha256": "996af632b11f48ee4f102c7b63c8bf6a2f0e2b6debc1bc76d34a27775c0556b1"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "05c3c4a5bf0de4ae6ba74e668b5a4a368e69ba6a31c5046993a770a62cb8ce5d", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->commit_cb = pgoutput_commit_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">52.5.\u00a0Logical Streaming Replication Protocol</h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.1.\u00a0Logical Streaming Replication Parameters</h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently only version <code class=\"literal\">1</code> is supported. A valid version is required.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.2.\u00a0Logical Replication Protocol Messages</h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/12/protocol-logicalrep-message-formats.html\" title=\"52.9.\u00a0Logical Replication Message Formats\">Section\u00a052.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.3.\u00a0Logical Replication Protocol Message Flow</h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/12/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported. A valid version is required."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "source_options": ["proto_version", "publication_names"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1"}}, "comparison_hash": "e720ae3ea46eba4407a3ce10d76e43106f01751c003969f51e58093113752821", "runtime_verified": false}, "13": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "7"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "No handler registered in this build", "feature": "Logical messages", "callback": "message_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported. A valid version is required."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "proto_version"}, {"name": "publication_names"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/13/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=13", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=13", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=13", "label": "Logical tuple representation"}], "release": {"ref": "PostgreSQL 13.23 source archive", "label": "13.23", "major": "13", "channel": "historical", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "source_url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/13/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 13 English manual", "sha256": "89a2c264cfc945ce4315cba2d564adc0d631254c4264a08fbe3b0c771188e581"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 117, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:117", "sha256": "137949e716bf0db47fce833b808995555f10825302846c2b9caaab1b9e9e6399", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "/docs/13/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 13 English manual", "sha256": "a9a536d274ad7fb994ae70df068b06da58b5077aca4ce86289ed07921baefd4f"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "fb3b349901303ec4122998461121ffd96ea5238d552971d97478d25476d844ed", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->commit_cb = pgoutput_commit_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">52.5.\u00a0Logical Streaming Replication Protocol</h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.1.\u00a0Logical Streaming Replication Parameters</h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently only version <code class=\"literal\">1</code> is supported. A valid version is required.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.2.\u00a0Logical Replication Protocol Messages</h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/13/protocol-logicalrep-message-formats.html\" title=\"52.9.\u00a0Logical Replication Message Formats\">Section\u00a052.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">52.5.3.\u00a0Logical Replication Protocol Message Flow</h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/13/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently only version 1 is supported. A valid version is required."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "source_options": ["proto_version", "publication_names"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1"}}, "comparison_hash": "e720ae3ea46eba4407a3ce10d76e43106f01751c003969f51e58093113752821", "runtime_verified": false}, "14": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "15"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "No handler registered in this build", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "Not registered"}, {"state": "No handler registered in this build", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "Not registered"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 and 2 are supported. A valid version is required. The version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/14/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=14", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=14", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=14", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=14", "label": "Logical Stream Start message"}], "release": {"ref": "PostgreSQL 14.24 source archive", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "source_url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/14/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 14 English manual", "sha256": "ad5619c17b32069e563861948a6dfe2f55ec9bea3e99f2400e8b57afd6927f26"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 149, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:149", "sha256": "f906f70fba365cb8d83cdc6819ea45e61a58973a1cbae4011fa2bafbdcf3bd23", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "/docs/14/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 14 English manual", "sha256": "8657a205ee5dc4698b76016d8df9f89a0aea844bdeaa5466b2308401ad6b6dc4"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "fae79c22efb1fecb13ad7635bb64eb1c2bf54ad456fa230905d2ef0bab88ea25", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">53.5.\u00a0Logical Streaming Replication Protocol</h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.1.\u00a0Logical Streaming Replication Parameters</h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently versions <code class=\"literal\">1</code> and <code class=\"literal\">2</code> are supported. A valid version is required. The version <code class=\"literal\">2</code> is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n<dt><span class=\"term\">binary</span></dt>\n<dd>\n<p>Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust.</p>\n</dd>\n<dt><span class=\"term\">messages</span></dt>\n<dd>\n<p>Boolean option to enable sending the messages that are written by <code class=\"function\">pg_logical_emit_message</code>.</p>\n</dd>\n<dt><span class=\"term\">streaming</span></dt>\n<dd>\n<p>Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.2.\u00a0Logical Replication Protocol Messages</h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/14/protocol-logicalrep-message-formats.html\" title=\"53.9.\u00a0Logical Replication Message Formats\">Section\u00a053.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.3.\u00a0Logical Replication Protocol Message Flow</h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/14/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 and 2 are supported. A valid version is required. The version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter"}, "source_options": ["binary", "messages", "proto_version", "publication_names", "streaming"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2"}}, "comparison_hash": "fb770dffbee4b87a47f7d20428fcdc6e8a74308fa91944bba5d25080a20d9a1a", "runtime_verified": false}, "15": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , and 3 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/15/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=15", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=15", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=15", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=15", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=15", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 15.19 source archive", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "source_url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/15/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 15 English manual", "sha256": "02bd28990f7ac5c4b3a88806ed90fe6b0d724831599e1326895a3a9ebb33baee"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 259, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:259", "sha256": "b62179c45f89cf9aea945d7b0cbdef6d1998cbf54e908ad4ef42091e7515a67d", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "/docs/15/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 15 English manual", "sha256": "6c81b3b643e0a8f47dc1a136953fb61d57b48434a3c8aa7393b06dae440406a5"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "9b04e25ff58eb3e3cbbfac4766d96c6db78529ae80164164e3d1158973d83442", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tAssertVariableIsOfType(&_PG_output_plugin_init, LogicalOutputPluginInit);\n\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">55.5.\u00a0Logical Streaming Replication Protocol</h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">55.5.1.\u00a0Logical Streaming Replication Parameters</h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently versions <code class=\"literal\">1</code>, <code class=\"literal\">2</code>, and <code class=\"literal\">3</code> are supported. A valid version is required.</p>\n<p>Version <code class=\"literal\">2</code> is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.</p>\n<p>Version <code class=\"literal\">3</code> is supported only for server version 15 and above, and it allows streaming of two-phase commits.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n<dt><span class=\"term\">binary</span></dt>\n<dd>\n<p>Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust.</p>\n</dd>\n<dt><span class=\"term\">messages</span></dt>\n<dd>\n<p>Boolean option to enable sending the messages that are written by <code class=\"function\">pg_logical_emit_message</code>.</p>\n</dd>\n<dt><span class=\"term\">streaming</span></dt>\n<dd>\n<p>Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on.</p>\n</dd>\n<dt><span class=\"term\">two_phase</span></dt>\n<dd>\n<p>Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">55.5.2.\u00a0Logical Replication Protocol Messages</h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/15/protocol-logicalrep-message-formats.html\" title=\"55.9.\u00a0Logical Replication Message Formats\">Section\u00a055.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">55.5.3.\u00a0Logical Replication Protocol Message Flow</h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/15/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , and 3 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3"}}, "comparison_hash": "9ff9b317d99bdc01268d07f723dd427172fb3d7e326a4d6eb063af749c003085", "runtime_verified": false}, "16": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}, {"label": "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM", "value": "4"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are \"none\" to only send the changes that have no origin associated, or \"any\" to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "origin"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/16/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=16", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=16", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=16", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=16", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=16", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 16.15 source archive", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "source_url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/16/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 16 English manual", "sha256": "49bf957dc34e5cd53a4766e0283d0aef5223273d1f72e168c7d8b03e557d69a7"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 258, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:258", "sha256": "74dd79304594a7a5b5a8ddb9e567394352706f186ec2a8bddc652a64be712672", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "/docs/16/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 16 English manual", "sha256": "c093330981ad988f2081ad6ac1eb74b0c8ab7fbc19928ca50e12fcdfe7647a4f"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "dfecefee411c6448fd9f366d4f2a458dbb4bd95616306a1b214457302a7b46ed", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">55.5.\u00a0Logical Streaming Replication Protocol </h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">55.5.1.\u00a0Logical Streaming Replication Parameters </h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently versions <code class=\"literal\">1</code>, <code class=\"literal\">2</code>, <code class=\"literal\">3</code>, and <code class=\"literal\">4</code> are supported. A valid version is required.</p>\n<p>Version <code class=\"literal\">2</code> is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.</p>\n<p>Version <code class=\"literal\">3</code> is supported only for server version 15 and above, and it allows streaming of two-phase commits.</p>\n<p>Version <code class=\"literal\">4</code> is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n<dt><span class=\"term\">binary</span></dt>\n<dd>\n<p>Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust.</p>\n</dd>\n<dt><span class=\"term\">messages</span></dt>\n<dd>\n<p>Boolean option to enable sending the messages that are written by <code class=\"function\">pg_logical_emit_message</code>.</p>\n</dd>\n<dt><span class=\"term\">streaming</span></dt>\n<dd>\n<p>Option to enable streaming of in-progress transactions. Valid values are <code class=\"literal\">off</code> (the default), <code class=\"literal\">on</code> and <code class=\"literal\">parallel</code>. The setting <code class=\"literal\">parallel</code> enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it <code class=\"literal\">on</code>. Minimum protocol version 4 is required for the <code class=\"literal\">parallel</code> value.</p>\n</dd>\n<dt><span class=\"term\">two_phase</span></dt>\n<dd>\n<p>Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on.</p>\n</dd>\n<dt><span class=\"term\">origin</span></dt>\n<dd>\n<p>Option to send changes by their origin. Possible values are \"none\" to only send the changes that have no origin associated, or \"any\" to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">55.5.2.\u00a0Logical Replication Protocol Messages </h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/16/protocol-logicalrep-message-formats.html\" title=\"55.9.\u00a0Logical Replication Message Formats\">Section\u00a055.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">55.5.3.\u00a0Logical Replication Protocol Message Flow </h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/16/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are \"none\" to only send the changes that have no origin associated, or \"any\" to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "origin", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3", "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM": "4"}}, "comparison_hash": "caca53c5d8da82cd5b929b0a2d57664baf3fe51f1d73bbfb2de9184b7a206d84", "runtime_verified": false}, "17": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}, {"label": "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM", "value": "4"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are \"none\" to only send the changes that have no origin associated, or \"any\" to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "origin"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/17/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=17", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=17", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=17", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=17", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=17", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 17.11 source archive", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "source_url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/17/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 17 English manual", "sha256": "d067f4d47c559b2f60eb144af3fb642907b256b2f4f48c971fba3cb7169e5533"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 256, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:256", "sha256": "44ff6063db730a29b8acfa13d1eccc2454f2b48f380ed4dfeb18391451810504", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "/docs/17/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 17 English manual", "sha256": "2be04efbf0e2c4266665b8e7b8ebbc04a92456d3fcfdfe2667e8e4486bd70be8"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "50a3f4aaf9976c7206fa89a15abc53cf36d03919a07ed5a255c8b9738e1ecc48", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">53.5.\u00a0Logical Streaming Replication Protocol </h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.1.\u00a0Logical Streaming Replication Parameters </h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently versions <code class=\"literal\">1</code>, <code class=\"literal\">2</code>, <code class=\"literal\">3</code>, and <code class=\"literal\">4</code> are supported. A valid version is required.</p>\n<p>Version <code class=\"literal\">2</code> is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.</p>\n<p>Version <code class=\"literal\">3</code> is supported only for server version 15 and above, and it allows streaming of two-phase commits.</p>\n<p>Version <code class=\"literal\">4</code> is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n<dt><span class=\"term\">binary</span></dt>\n<dd>\n<p>Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust.</p>\n</dd>\n<dt><span class=\"term\">messages</span></dt>\n<dd>\n<p>Boolean option to enable sending the messages that are written by <code class=\"function\">pg_logical_emit_message</code>.</p>\n</dd>\n<dt><span class=\"term\">streaming</span></dt>\n<dd>\n<p>Option to enable streaming of in-progress transactions. Valid values are <code class=\"literal\">off</code> (the default), <code class=\"literal\">on</code> and <code class=\"literal\">parallel</code>. The setting <code class=\"literal\">parallel</code> enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it <code class=\"literal\">on</code>. Minimum protocol version 4 is required for the <code class=\"literal\">parallel</code> value.</p>\n</dd>\n<dt><span class=\"term\">two_phase</span></dt>\n<dd>\n<p>Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on.</p>\n</dd>\n<dt><span class=\"term\">origin</span></dt>\n<dd>\n<p>Option to send changes by their origin. Possible values are \"none\" to only send the changes that have no origin associated, or \"any\" to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.2.\u00a0Logical Replication Protocol Messages </h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/17/protocol-logicalrep-message-formats.html\" title=\"53.9.\u00a0Logical Replication Message Formats\">Section\u00a053.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">53.5.3.\u00a0Logical Replication Protocol Message Flow </h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/17/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are \"none\" to only send the changes that have no origin associated, or \"any\" to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "origin", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3", "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM": "4"}}, "comparison_hash": "caca53c5d8da82cd5b929b0a2d57664baf3fe51f1d73bbfb2de9184b7a206d84", "runtime_verified": false}, "18": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}, {"label": "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM", "value": "4"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "origin"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/18/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=18", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=18", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=18", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=18", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=18", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/18/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 18 English manual", "sha256": "db5675868e641807e48ae6e19f51ed2a9bc9a29bd1b7a365c16eb3cae022a18e"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 262, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:262", "sha256": "0a16f2abc3218286200f1a0a9c1d67fb7115ec0145b5edd7e4bd66ecb4d07566", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "/docs/18/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 18 English manual", "sha256": "e5b3d13adfcc9e33f24524cb09d93eb91a1292fdb3124234002ccccf93f45738"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "1c6101fa446aabe8d78a722fe62c4fce647f5b492ab4d7b460907ce73e035180", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">54.5.\u00a0Logical Streaming Replication Protocol </h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.1.\u00a0Logical Streaming Replication Parameters </h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently versions <code class=\"literal\">1</code>, <code class=\"literal\">2</code>, <code class=\"literal\">3</code>, and <code class=\"literal\">4</code> are supported. A valid version is required.</p>\n<p>Version <code class=\"literal\">2</code> is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.</p>\n<p>Version <code class=\"literal\">3</code> is supported only for server version 15 and above, and it allows streaming of two-phase commits.</p>\n<p>Version <code class=\"literal\">4</code> is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n<dt><span class=\"term\">binary</span></dt>\n<dd>\n<p>Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust.</p>\n</dd>\n<dt><span class=\"term\">messages</span></dt>\n<dd>\n<p>Boolean option to enable sending the messages that are written by <code class=\"function\">pg_logical_emit_message</code>.</p>\n</dd>\n<dt><span class=\"term\">streaming</span></dt>\n<dd>\n<p>Option to enable streaming of in-progress transactions. Valid values are <code class=\"literal\">off</code> (the default), <code class=\"literal\">on</code> and <code class=\"literal\">parallel</code>. The setting <code class=\"literal\">parallel</code> enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it <code class=\"literal\">on</code>. Minimum protocol version 4 is required for the <code class=\"literal\">parallel</code> value.</p>\n</dd>\n<dt><span class=\"term\">two_phase</span></dt>\n<dd>\n<p>Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on.</p>\n</dd>\n<dt><span class=\"term\">origin</span></dt>\n<dd>\n<p>Option to send changes by their origin. Possible values are <code class=\"literal\">none</code> to only send the changes that have no origin associated, or <code class=\"literal\">any</code> to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.2.\u00a0Logical Replication Protocol Messages </h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/18/protocol-logicalrep-message-formats.html\" title=\"54.9.\u00a0Logical Replication Message Formats\">Section\u00a054.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.3.\u00a0Logical Replication Protocol Message Flow </h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/18/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "origin", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3", "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM": "4"}}, "comparison_hash": "825d73cfabb72ac9c0d2de837bc79ea972bb82f3c010a3833852f3f7e9e3935a", "runtime_verified": false}, "19": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}, {"label": "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM", "value": "4"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Specifies the protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported on server version 14 and above, and is required when streaming is set to on to stream large in-progress transactions. Version 3 is supported on server version 15 and above, and is required when two_phase is enabled to stream two-phase commits. Version 4 is supported on server version 16 and above, and is required when streaming is set to parallel to stream large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "A comma-separated list of publication names to subscribe to. The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Enables binary transfer mode. Binary mode is faster than the text mode but slightly less robust. The default is off ."}, {"name": "messages", "definition": "Enables sending the messages that are written by pg_logical_emit_message . The default is off ."}, {"name": "streaming", "definition": "Enables streaming of in-progress transactions. Valid values are off (the default), on and parallel . When set to off , pgoutput fully decodes a transaction before sending it as a whole. This mode works with any protocol version. When set to on , pgoutput streams large in-progress transactions. This requires protocol version 2 or higher. When set to parallel , pgoutput streams large in-progress transactions and also sends extra information in some messages to support parallel processing. This requires protocol version 4 or higher."}, {"name": "two_phase", "definition": "Enables sending two-phase transactions. Minimum protocol version 3 is required to turn it on. The default is off ."}, {"name": "origin", "definition": "Specifies whether to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes. The default is any ."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "origin"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/19/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=19", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=19", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=19", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=19", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=19", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 19beta4 source archive", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "source_url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/19/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 19 English manual", "sha256": "f3c99200f43017c768cf77229e3a02314f4fdf9ba45231f26404494395d571da"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 262, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:262", "sha256": "ae741b78ad21877b8fad6c1f9025fe46db22fea115b80fb62f423ae45c063ad5", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "/docs/19/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 19 English manual", "sha256": "5bbd383a295ed5cdb65b99d721fb7320aafdb7a343b26abbcb022134635d5ff7"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "c382263abcd29845c0b06ea2152cdcea357993fe806bf8bf9c1cb00a0b7678dc", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">54.5.\u00a0Logical Streaming Replication Protocol </h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.1.\u00a0Logical Streaming Replication Parameters </h3>\n</div>\n</div>\n</div>\n<p>The <code class=\"literal\">START_REPLICATION</code> command can pass options to the logical decoding output plugin associated with the specified replication slot. See <a class=\"xref\" href=\"/docs/19/logicaldecoding-output-plugin.html#LOGICALDECODING-PGOUTPUT-OPTIONS\" title=\"47.6.1.1.\u00a0Options\">Section\u00a047.6.1.1</a> for options that are accepted by the standard (<code class=\"literal\">pgoutput</code>) plugin.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.2.\u00a0Logical Replication Protocol Messages </h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/19/protocol-logicalrep-message-formats.html\" title=\"54.9.\u00a0Logical Replication Message Formats\">Section\u00a054.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.3.\u00a0Logical Replication Protocol Message Flow </h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/19/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Specifies the protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported on server version 14 and above, and is required when streaming is set to on to stream large in-progress transactions. Version 3 is supported on server version 15 and above, and is required when two_phase is enabled to stream two-phase commits. Version 4 is supported on server version 16 and above, and is required when streaming is set to parallel to stream large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "A comma-separated list of publication names to subscribe to. The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Enables binary transfer mode. Binary mode is faster than the text mode but slightly less robust. The default is off ."}, {"name": "messages", "definition": "Enables sending the messages that are written by pg_logical_emit_message . The default is off ."}, {"name": "streaming", "definition": "Enables streaming of in-progress transactions. Valid values are off (the default), on and parallel . When set to off , pgoutput fully decodes a transaction before sending it as a whole. This mode works with any protocol version. When set to on , pgoutput streams large in-progress transactions. This requires protocol version 2 or higher. When set to parallel , pgoutput streams large in-progress transactions and also sends extra information in some messages to support parallel processing. This requires protocol version 4 or higher."}, {"name": "two_phase", "definition": "Enables sending two-phase transactions. Minimum protocol version 3 is required to turn it on. The default is off ."}, {"name": "origin", "definition": "Specifies whether to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes. The default is any ."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "origin", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3", "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM": "4"}}, "comparison_hash": "761842f39eae1d9c23b64afdacc7bf910f49481118b5b15614b4b560b5e39432", "runtime_verified": false}, "20": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}, {"label": "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM", "value": "4"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Specifies the protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported on server version 14 and above, and is required when streaming is set to on to stream large in-progress transactions. Version 3 is supported on server version 15 and above, and is required when two_phase is enabled to stream two-phase commits. Version 4 is supported on server version 16 and above, and is required when streaming is set to parallel to stream large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "A comma-separated list of publication names to subscribe to. The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Enables binary transfer mode. Binary mode is faster than the text mode but slightly less robust. The default is off ."}, {"name": "messages", "definition": "Enables sending the messages that are written by pg_logical_emit_message . The default is off ."}, {"name": "streaming", "definition": "Enables streaming of in-progress transactions. Valid values are off (the default), on and parallel . When set to off , pgoutput fully decodes a transaction before sending it as a whole. This mode works with any protocol version. When set to on , pgoutput streams large in-progress transactions. This requires protocol version 2 or higher. When set to parallel , pgoutput streams large in-progress transactions and also sends extra information in some messages to support parallel processing. This requires protocol version 4 or higher."}, {"name": "two_phase", "definition": "Enables sending two-phase transactions. Minimum protocol version 3 is required to turn it on. The default is off ."}, {"name": "origin", "definition": "Specifies whether to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes. The default is any ."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "origin"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/devel/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=20", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=20", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=20", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=20", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=20", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 20devel source archive", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "source_url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "source_snapshot_utc": "26-Sep-2026 20:22"}, "sources": [{"url": "/docs/devel/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 20 English manual", "sha256": "bc3dfd36641355a858bfecf035b81082f0fcce4f083edd1176ba2dba71bbdea0"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 262, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:262", "sha256": "76fc9fd190d2a233e54c0a56a511a641c8682a57d597cff7cdd6c998ca907963", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "/docs/devel/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 20 English manual", "sha256": "c3155ae81ecabd273f3b326b0e44b4cf39954def59a10c58f50f7ec51ac1923c"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "c382263abcd29845c0b06ea2152cdcea357993fe806bf8bf9c1cb00a0b7678dc", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">54.5.\u00a0Logical Streaming Replication Protocol </h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.1.\u00a0Logical Streaming Replication Parameters </h3>\n</div>\n</div>\n</div>\n<p>The <code class=\"literal\">START_REPLICATION</code> command can pass options to the logical decoding output plugin associated with the specified replication slot. See <a class=\"xref\" href=\"/docs/devel/logicaldecoding-output-plugin.html#LOGICALDECODING-PGOUTPUT-OPTIONS\" title=\"47.6.1.1.\u00a0Options\">Section\u00a047.6.1.1</a> for options that are accepted by the standard (<code class=\"literal\">pgoutput</code>) plugin.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.2.\u00a0Logical Replication Protocol Messages </h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/devel/protocol-logicalrep-message-formats.html\" title=\"54.9.\u00a0Logical Replication Message Formats\">Section\u00a054.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.3.\u00a0Logical Replication Protocol Message Flow </h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/devel/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Specifies the protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported on server version 14 and above, and is required when streaming is set to on to stream large in-progress transactions. Version 3 is supported on server version 15 and above, and is required when two_phase is enabled to stream two-phase commits. Version 4 is supported on server version 16 and above, and is required when streaming is set to parallel to stream large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "A comma-separated list of publication names to subscribe to. The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Enables binary transfer mode. Binary mode is faster than the text mode but slightly less robust. The default is off ."}, {"name": "messages", "definition": "Enables sending the messages that are written by pg_logical_emit_message . The default is off ."}, {"name": "streaming", "definition": "Enables streaming of in-progress transactions. Valid values are off (the default), on and parallel . When set to off , pgoutput fully decodes a transaction before sending it as a whole. This mode works with any protocol version. When set to on , pgoutput streams large in-progress transactions. This requires protocol version 2 or higher. When set to parallel , pgoutput streams large in-progress transactions and also sends extra information in some messages to support parallel processing. This requires protocol version 4 or higher."}, {"name": "two_phase", "definition": "Enables sending two-phase transactions. Minimum protocol version 3 is required to turn it on. The default is off ."}, {"name": "origin", "definition": "Specifies whether to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes. The default is any ."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "origin", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3", "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM": "4"}}, "comparison_hash": "761842f39eae1d9c23b64afdacc7bf910f49481118b5b15614b4b560b5e39432", "runtime_verified": false, "collection_tables": [{"key": "decode-catalogue", "rows": [{"scope": "Primary documentation reviewed separately below", "checked": "2026-08-30", "version": "2.6", "postgres": "14, 15, 16, 17, 18", "extension": {"url": "/e/wal2json/", "text": "wal2json"}, "description": "Changing data capture in JSON format"}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "1.0.7", "postgres": "14, 15, 16, 17, 18", "extension": {"url": "/e/wal2mongo/", "text": "wal2mongo"}, "description": "PostgreSQL logical decoding output plugin for MongoDB"}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "3.6.0", "postgres": "14, 15, 16, 17, 18", "extension": {"url": "/e/decoderbufs/", "text": "decoderbufs"}, "description": "Logical decoding plugin that delivers WAL stream changes using a Protocol Buffer format"}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "1.0", "postgres": "14, 15, 16, 17, 18", "extension": {"url": "/e/decoder_raw/", "text": "decoder_raw"}, "description": "Output plugin for logical replication in Raw SQL format"}, {"scope": "Core interface; see versioned entry", "checked": "Not recorded", "version": "-", "postgres": "14, 15, 16, 17, 18", "extension": {"url": "/e/test_decoding/", "text": "test_decoding"}, "description": "SQL-based test/example module for WAL logical decoding"}, {"scope": "Core interface; see versioned entry", "checked": "Not recorded", "version": "-", "postgres": "14, 15, 16, 17, 18", "extension": {"url": "/e/pgoutput/", "text": "pgoutput"}, "description": "Logical Replication output plugin"}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "0.1.0", "postgres": "Unknown", "extension": {"url": "/e/jsoncdc/", "text": "jsoncdc"}, "description": "JSON logical decoding output plugin"}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "0.1", "postgres": "Unknown", "extension": {"url": "/e/replisome/", "text": "replisome"}, "description": "Logical-decoding output plugin and Python consumer framework for streaming PostgreSQL row changes as JSON."}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "0.1.0", "postgres": "Unknown", "extension": {"url": "/e/putpostlogic/", "text": "putpostlogic"}, "description": "Unreleased logical decoding output-plugin prototype that emits JSON changes through PostgreSQL, Kafka, or Nanomsg."}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "0.0.0", "postgres": "Unknown", "extension": {"url": "/e/pboutput/", "text": "pboutput"}, "description": "Binary logical-decoding output plugin that encodes PostgreSQL changes as Protocol Buffers."}, {"scope": "Catalogue candidate; interface unverified", "checked": "2026-08-30", "version": "1.0", "postgres": "Unknown", "extension": {"url": "/e/pg_turso/", "text": "pg_turso"}, "description": "Postgres output plugin for replicating data to Turso."}], "title": "Logical-decoding plugin candidates", "caption": "Current catalogue observation 2026-09-29 from pgext.universe. Extension versions, source metadata dates and declared PostgreSQL compatibility are independent of the selected core version. Catalogue classification does not establish capabilities or maintenance support.", "columns": [{"key": "extension", "label": "Existing extension"}, {"key": "version", "label": "Catalogued version"}, {"key": "postgres", "label": "Declared PG majors"}, {"key": "checked", "label": "Metadata checked"}, {"key": "scope", "label": "Evidence scope"}, {"key": "description", "label": "Catalogued purpose"}]}, {"key": "decode-reviewed-capabilities", "rows": [{"state": "Verified in documentation", "detail": "Format 1 emits one JSON object per transaction; format 2 emits one per tuple with optional transaction boundaries.", "version": "2.6", "evidence": {"url": "https://github.com/eulerto/wal2json/blob/75629c2e1e81a12350cc9d63782fc53252185d8d/README.md", "text": "2026-09-29 \u00b7 75629c2e1e81 \u00b7 README.md"}, "extension": {"url": "/e/wal2json/", "text": "wal2json"}, "capability": "Output granularity"}, {"state": "Conditional", "detail": "UPDATE and DELETE old-row availability depends on replica identity.", "version": "2.6", "evidence": {"url": "https://github.com/eulerto/wal2json/blob/75629c2e1e81a12350cc9d63782fc53252185d8d/README.md", "text": "2026-09-29 \u00b7 75629c2e1e81 \u00b7 README.md"}, "extension": {"url": "/e/wal2json/", "text": "wal2json"}, "capability": "Old row values"}, {"state": "Conditional", "detail": "The actions option controls changes; format 1 excludes TRUNCATE for compatibility.", "version": "2.6", "evidence": {"url": "https://github.com/eulerto/wal2json/blob/75629c2e1e81a12350cc9d63782fc53252185d8d/README.md", "text": "2026-09-29 \u00b7 75629c2e1e81 \u00b7 README.md"}, "extension": {"url": "/e/wal2json/", "text": "wal2json"}, "capability": "TRUNCATE"}, {"state": "Verified in documentation", "detail": "Options select or exclude tables, origins and logical-message prefixes.", "version": "2.6", "evidence": {"url": "https://github.com/eulerto/wal2json/blob/75629c2e1e81a12350cc9d63782fc53252185d8d/README.md", "text": "2026-09-29 \u00b7 75629c2e1e81 \u00b7 README.md"}, "extension": {"url": "/e/wal2json/", "text": "wal2json"}, "capability": "Table and message filters"}, {"state": "Unknown", "detail": "A streaming-protocol connection does not itself establish these capabilities; this documentation review does not verify them.", "version": "2.6", "evidence": {"url": "https://github.com/eulerto/wal2json/blob/75629c2e1e81a12350cc9d63782fc53252185d8d/README.md", "text": "2026-09-29 \u00b7 75629c2e1e81 \u00b7 README.md"}, "extension": {"url": "/e/wal2json/", "text": "wal2json"}, "capability": "In-progress transaction streaming / two-phase decoding"}], "title": "Primary-source capability observations", "caption": "Each statement applies to its named extension version and immutable source revision. Unlisted capabilities remain unknown. These are documentation observations, not runtime tests or current maintenance guarantees.", "columns": [{"key": "extension", "label": "Extension"}, {"key": "version", "label": "Reviewed version"}, {"key": "capability", "label": "Capability"}, {"key": "state", "label": "Evidence state"}, {"key": "detail", "label": "Conditions"}, {"key": "evidence", "label": "Evidence date and source"}]}], "extension_reviews": [{"kind": "decode", "name": "wal2json", "claims": [{"text": "Format 1 emits one JSON object per transaction; format 2 emits one per tuple with optional transaction boundaries.", "label": "Output granularity", "state": "Verified in documentation"}, {"text": "UPDATE and DELETE old-row availability depends on replica identity.", "label": "Old row values", "state": "Conditional"}, {"text": "The actions option controls changes; format 1 excludes TRUNCATE for compatibility.", "label": "TRUNCATE", "state": "Conditional"}, {"text": "Options select or exclude tables, origins and logical-message prefixes.", "label": "Table and message filters", "state": "Verified in documentation"}, {"text": "A streaming-protocol connection does not itself establish these capabilities; this documentation review does not verify them.", "label": "In-progress transaction streaming / two-phase decoding", "state": "Unknown"}], "sources": [{"url": "https://github.com/eulerto/wal2json/blob/75629c2e1e81a12350cc9d63782fc53252185d8d/README.md", "path": "README.md", "sha256": "efa1cb3070aa6f9f5694885555b9856e6412bdb53ebb89eb00d769ab06a9c431", "local_name": "wal2json-readme.txt"}], "version": "2.6", "revision": "75629c2e1e81a12350cc9d63782fc53252185d8d", "checked_at": "2026-09-29"}], "catalog_observation": {"sha256": "a8f35f83709025575037ce50331f20fc27727e478464e35b48bb501e687cc121", "source": "data.pgext.universe", "identities": [{"id": 9630, "name": "wal2json"}, {"id": 9640, "name": "wal2mongo"}, {"id": 9650, "name": "decoderbufs"}, {"id": 9660, "name": "decoder_raw"}, {"id": 9970, "name": "test_decoding"}, {"id": 9980, "name": "pgoutput"}, {"id": 100073, "name": "jsoncdc"}, {"id": 100315, "name": "replisome"}, {"id": 100678, "name": "putpostlogic"}, {"id": 101508, "name": "pboutput"}, {"id": 101638, "name": "pg_turso"}], "observed_at": "2026-09-29T15:02:21.407129+00:00", "catalogue_rows": 2452, "candidate_count": 11}}}}, "snapshot": {"facts": [{"label": "Interface family", "value": "Logical-decoding output plugin"}, {"label": "Handler or routine", "value": "_PG_output_plugin_init"}, {"label": "Recorded callbacks", "value": "20"}, {"label": "LOGICALREP_PROTO_MIN_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_VERSION_NUM", "value": "1"}, {"label": "LOGICALREP_PROTO_STREAM_VERSION_NUM", "value": "2"}, {"label": "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM", "value": "3"}, {"label": "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM", "value": "4"}], "tables": [{"key": "callbacks", "rows": [{"state": "Handler registered; conditions apply", "feature": "Begin transaction", "callback": "begin_cb", "implementation": "pgoutput_begin_txn"}, {"state": "Handler registered; conditions apply", "feature": "Row changes", "callback": "change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Commit", "callback": "commit_cb", "implementation": "pgoutput_commit_txn"}, {"state": "Handler registered; conditions apply", "feature": "TRUNCATE", "callback": "truncate_cb", "implementation": "pgoutput_truncate"}, {"state": "Handler registered; conditions apply", "feature": "Logical messages", "callback": "message_cb", "implementation": "pgoutput_message"}, {"state": "Handler registered; conditions apply", "feature": "Start streamed transaction", "callback": "stream_start_cb", "implementation": "pgoutput_stream_start"}, {"state": "Handler registered; conditions apply", "feature": "Stream row changes", "callback": "stream_change_cb", "implementation": "pgoutput_change"}, {"state": "Handler registered; conditions apply", "feature": "Prepare transaction", "callback": "prepare_cb", "implementation": "pgoutput_prepare_txn"}, {"state": "Handler registered; conditions apply", "feature": "Commit prepared", "callback": "commit_prepared_cb", "implementation": "pgoutput_commit_prepared_txn"}, {"state": "Handler registered; conditions apply", "feature": "Rollback prepared", "callback": "rollback_prepared_cb", "implementation": "pgoutput_rollback_prepared_txn"}], "title": "Registered interface handlers", "columns": [{"key": "feature", "label": "Interface operation"}, {"key": "state", "label": "Source observation"}, {"key": "callback", "label": "Callback"}, {"key": "implementation", "label": "Implementation"}]}, {"key": "options", "rows": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "title": "Documented options", "columns": [{"key": "name", "label": "Option"}, {"key": "definition", "label": "Same-version definition"}]}, {"key": "source-options", "rows": [{"name": "binary"}, {"name": "messages"}, {"name": "origin"}, {"name": "proto_version"}, {"name": "publication_names"}, {"name": "streaming"}, {"name": "two_phase"}], "title": "Option names recognized by this plugin build", "caption": "Extracted from the option parser; names alone do not describe defaults, accepted values or protocol requirements.", "columns": [{"key": "name", "label": "Source option name"}]}], "related": [{"url": "/docs/18/logicaldecoding-output-plugin.html", "label": "Logical decoding output interface"}, {"url": "/e/pgoutput/", "label": "Existing extension catalogue identity"}, {"url": "/wiki/protocol/logical-begin/?v=18", "label": "Logical Begin message"}, {"url": "/wiki/protocol/logical-relation/?v=18", "label": "Logical Relation message"}, {"url": "/wiki/protocol/logical-tupledata/?v=18", "label": "Logical tuple representation"}, {"url": "/wiki/protocol/logical-stream-start/?v=18", "label": "Logical Stream Start message"}, {"url": "/wiki/protocol/logical-prepare/?v=18", "label": "Logical Prepare message"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "/docs/18/protocol-logical-replication.html", "path": "protocol-logical-replication.html", "label": "PostgreSQL 18 English manual", "sha256": "db5675868e641807e48ae6e19f51ed2a9bc9a29bd1b7a365c16eb3cae022a18e"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 262, "path": "src/backend/replication/pgoutput/pgoutput.c", "label": "src/backend/replication/pgoutput/pgoutput.c:262", "sha256": "0a16f2abc3218286200f1a0a9c1d67fb7115ec0145b5edd7e4bd66ecb4d07566", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "/docs/18/logicaldecoding-output-plugin.html", "path": "logicaldecoding-output-plugin.html", "label": "PostgreSQL 18 English manual", "sha256": "e5b3d13adfcc9e33f24524cb09d93eb91a1292fdb3124234002ccccf93f45738"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/replication/logicalproto.h", "label": "Logical replication protocol constants", "sha256": "1c6101fa446aabe8d78a722fe62c4fce647f5b492ab4d7b460907ce73e035180", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "sections": [{"title": "Interface and capability boundaries", "paragraphs": ["The matrix records callbacks actually registered in this source build. Registration identifies an implemented interface hook; options, query shape, privileges and provider rules determine whether an operation is allowed.", "The complete same-version manual below retains configuration, constraints and examples. No runtime capability test is claimed."]}, {"title": "Output and protocol boundaries", "paragraphs": ["Callback presence and protocol versions are separate from client negotiation and enabled plugin options. Streaming and two-phase processing require the matching protocol and configuration.", "test_decoding is an example/test output format; pgoutput implements the logical-replication protocol. Their output contracts are not interchangeable."]}, {"code": "{\n\tcb->startup_cb = pgoutput_startup;\n\tcb->begin_cb = pgoutput_begin_txn;\n\tcb->change_cb = pgoutput_change;\n\tcb->truncate_cb = pgoutput_truncate;\n\tcb->message_cb = pgoutput_message;\n\tcb->commit_cb = pgoutput_commit_txn;\n\n\tcb->begin_prepare_cb = pgoutput_begin_prepare_txn;\n\tcb->prepare_cb = pgoutput_prepare_txn;\n\tcb->commit_prepared_cb = pgoutput_commit_prepared_txn;\n\tcb->rollback_prepared_cb = pgoutput_rollback_prepared_txn;\n\tcb->filter_by_origin_cb = pgoutput_origin_filter;\n\tcb->shutdown_cb = pgoutput_shutdown;\n\n\t/* transaction streaming */\n\tcb->stream_start_cb = pgoutput_stream_start;\n\tcb->stream_stop_cb = pgoutput_stream_stop;\n\tcb->stream_abort_cb = pgoutput_stream_abort;\n\tcb->stream_commit_cb = pgoutput_stream_commit;\n\tcb->stream_change_cb = pgoutput_change;\n\tcb->stream_message_cb = pgoutput_message;\n\tcb->stream_truncate_cb = pgoutput_truncate;\n\t/* transaction streaming - two-phase commit */\n\tcb->stream_prepare_cb = pgoutput_stream_prepare_txn;\n}", "title": "Registered implementation in core source"}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "description": ["The built-in output plugin used by PostgreSQL logical replication."], "manual_html": "<div class=\"sect1\" id=\"PROTOCOL-LOGICAL-REPLICATION\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\">54.5.\u00a0Logical Streaming Replication Protocol </h2>\n</div>\n</div>\n</div>\n\n<p>This section describes the logical replication protocol, which is the message flow started by the <code class=\"literal\">START_REPLICATION</code> <code class=\"literal\">SLOT</code> <em class=\"replaceable\"><code>slot_name</code></em> <code class=\"literal\">LOGICAL</code> replication command.</p>\n<p>The logical streaming replication protocol builds on the primitives of the physical streaming replication protocol.</p>\n<p><span class=\"productname\">PostgreSQL</span> logical decoding supports output plugins. <code class=\"literal\">pgoutput</code> is the standard one used for the built-in logical replication.</p>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-REPLICATION-PARAMS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.1.\u00a0Logical Streaming Replication Parameters </h3>\n</div>\n</div>\n</div>\n<p>Using the <code class=\"literal\">START_REPLICATION</code> command, <code class=\"literal\">pgoutput</code> accepts the following options:</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\">proto_version</span></dt>\n<dd>\n<p>Protocol version. Currently versions <code class=\"literal\">1</code>, <code class=\"literal\">2</code>, <code class=\"literal\">3</code>, and <code class=\"literal\">4</code> are supported. A valid version is required.</p>\n<p>Version <code class=\"literal\">2</code> is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.</p>\n<p>Version <code class=\"literal\">3</code> is supported only for server version 15 and above, and it allows streaming of two-phase commits.</p>\n<p>Version <code class=\"literal\">4</code> is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel.</p>\n</dd>\n<dt><span class=\"term\">publication_names</span></dt>\n<dd>\n<p>Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required.</p>\n</dd>\n<dt><span class=\"term\">binary</span></dt>\n<dd>\n<p>Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust.</p>\n</dd>\n<dt><span class=\"term\">messages</span></dt>\n<dd>\n<p>Boolean option to enable sending the messages that are written by <code class=\"function\">pg_logical_emit_message</code>.</p>\n</dd>\n<dt><span class=\"term\">streaming</span></dt>\n<dd>\n<p>Option to enable streaming of in-progress transactions. Valid values are <code class=\"literal\">off</code> (the default), <code class=\"literal\">on</code> and <code class=\"literal\">parallel</code>. The setting <code class=\"literal\">parallel</code> enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it <code class=\"literal\">on</code>. Minimum protocol version 4 is required for the <code class=\"literal\">parallel</code> value.</p>\n</dd>\n<dt><span class=\"term\">two_phase</span></dt>\n<dd>\n<p>Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on.</p>\n</dd>\n<dt><span class=\"term\">origin</span></dt>\n<dd>\n<p>Option to send changes by their origin. Possible values are <code class=\"literal\">none</code> to only send the changes that have no origin associated, or <code class=\"literal\">any</code> to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.2.\u00a0Logical Replication Protocol Messages </h3>\n</div>\n</div>\n</div>\n<p>The individual protocol messages are discussed in the following subsections. Individual messages are described in <a class=\"xref\" href=\"/docs/18/protocol-logicalrep-message-formats.html\" title=\"54.9.\u00a0Logical Replication Message Formats\">Section\u00a054.9</a>.</p>\n<p>All top-level protocol messages begin with a message type byte. While represented in code as a character, this is a signed byte with no associated encoding.</p>\n<p>Since the streaming replication protocol supplies a message length there is no need for top-level protocol messages to embed a length in their header.</p>\n</div>\n<div class=\"sect2\" id=\"PROTOCOL-LOGICAL-MESSAGES-FLOW\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\">54.5.3.\u00a0Logical Replication Protocol Message Flow </h3>\n</div>\n</div>\n</div>\n<p>With the exception of the <code class=\"literal\">START_REPLICATION</code> command and the replay progress messages, all information flows only from the backend to the frontend.</p>\n<p>The logical replication protocol sends individual transactions one by one. This means that all messages between a pair of Begin and Commit messages belong to the same transaction. Similarly, all messages between a pair of Begin Prepare and Prepare messages belong to the same transaction. It also sends changes of large in-progress transactions between a pair of Stream Start and Stream Stop messages. The last stream of such a transaction contains a Stream Commit or Stream Abort message.</p>\n<p>Every sent transaction contains zero or more DML messages (Insert, Update, Delete). In case of a cascaded setup it can also contain Origin messages. The origin message indicates that the transaction originated on different replication node. Since a replication node in the scope of logical replication protocol can be pretty much anything, the only identifier is the origin name. It's downstream's responsibility to handle this as needed (if needed). The Origin message is always sent before any DML messages in the transaction.</p>\n<p>Every DML message contains a relation OID, identifying the publisher's relation that was acted on. Before the first DML message for a given relation OID, a Relation message will be sent, describing the schema of that relation. Subsequently, a new Relation message will be sent if the relation's definition has changed since the last Relation message was sent for it. (The protocol assumes that the client is capable of remembering this metadata for as many relations as needed.)</p>\n<p>Relation messages identify column types by their OIDs. In the case of a built-in type, it is assumed that the client can look up that type OID locally, so no additional data is needed. For a non-built-in type OID, a Type message will be sent before the Relation message, to provide the type name associated with that OID. Thus, a client that needs to specifically identify the types of relation columns should cache the contents of Type messages, and first consult that cache to see if the type OID is defined there. If not, look up the type OID locally.</p>\n</div>\n</div>", "manual_path": "/docs/18/protocol-logical-replication.html", "evidence_kind": "source and documentation", "comparison_data": {"options": [{"name": "proto_version", "definition": "Protocol version. Currently versions 1 , 2 , 3 , and 4 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits. Version 4 is supported only for server version 16 and above, and it allows streams of large in-progress transactions to be applied in parallel."}, {"name": "publication_names", "definition": "Comma-separated list of publication names for which to subscribe (receive changes). The individual publication names are treated as standard objects names and can be quoted the same as needed. At least one publication name is required."}, {"name": "binary", "definition": "Boolean option to use binary transfer mode. Binary mode is faster than the text mode but slightly less robust."}, {"name": "messages", "definition": "Boolean option to enable sending the messages that are written by pg_logical_emit_message ."}, {"name": "streaming", "definition": "Option to enable streaming of in-progress transactions. Valid values are off (the default), on and parallel . The setting parallel enables sending extra information with some messages to be used for parallelization. Minimum protocol version 2 is required to turn it on . Minimum protocol version 4 is required for the parallel value."}, {"name": "two_phase", "definition": "Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on."}, {"name": "origin", "definition": "Option to send changes by their origin. Possible values are none to only send the changes that have no origin associated, or any to send the changes regardless of their origin. This can be used to avoid loops (infinite replication of the same data) among replication nodes."}], "callbacks": {"begin_cb": "pgoutput_begin_txn", "change_cb": "pgoutput_change", "commit_cb": "pgoutput_commit_txn", "message_cb": "pgoutput_message", "prepare_cb": "pgoutput_prepare_txn", "startup_cb": "pgoutput_startup", "shutdown_cb": "pgoutput_shutdown", "truncate_cb": "pgoutput_truncate", "stream_stop_cb": "pgoutput_stream_stop", "stream_abort_cb": "pgoutput_stream_abort", "stream_start_cb": "pgoutput_stream_start", "begin_prepare_cb": "pgoutput_begin_prepare_txn", "stream_change_cb": "pgoutput_change", "stream_commit_cb": "pgoutput_stream_commit", "stream_message_cb": "pgoutput_message", "stream_prepare_cb": "pgoutput_stream_prepare_txn", "commit_prepared_cb": "pgoutput_commit_prepared_txn", "stream_truncate_cb": "pgoutput_truncate", "filter_by_origin_cb": "pgoutput_origin_filter", "rollback_prepared_cb": "pgoutput_rollback_prepared_txn"}, "source_options": ["binary", "messages", "origin", "proto_version", "publication_names", "streaming", "two_phase"], "protocol_versions": {"LOGICALREP_PROTO_VERSION_NUM": "1", "LOGICALREP_PROTO_MIN_VERSION_NUM": "1", "LOGICALREP_PROTO_STREAM_VERSION_NUM": "2", "LOGICALREP_PROTO_TWOPHASE_VERSION_NUM": "3", "LOGICALREP_PROTO_STREAM_PARALLEL_VERSION_NUM": "4"}}, "comparison_hash": "825d73cfabb72ac9c0d2de837bc79ea972bb82f3c010a3833852f3f7e9e3935a", "runtime_verified": false}, "comparison": {"left": "14", "right": "15", "status": "changed", "diff": "--- PostgreSQL 14\n+++ PostgreSQL 15\n@@ -1,16 +1,21 @@\n {\n   \"callbacks\": {\n     \"begin_cb\": \"pgoutput_begin_txn\",\n+    \"begin_prepare_cb\": \"pgoutput_begin_prepare_txn\",\n     \"change_cb\": \"pgoutput_change\",\n     \"commit_cb\": \"pgoutput_commit_txn\",\n+    \"commit_prepared_cb\": \"pgoutput_commit_prepared_txn\",\n     \"filter_by_origin_cb\": \"pgoutput_origin_filter\",\n     \"message_cb\": \"pgoutput_message\",\n+    \"prepare_cb\": \"pgoutput_prepare_txn\",\n+    \"rollback_prepared_cb\": \"pgoutput_rollback_prepared_txn\",\n     \"shutdown_cb\": \"pgoutput_shutdown\",\n     \"startup_cb\": \"pgoutput_startup\",\n     \"stream_abort_cb\": \"pgoutput_stream_abort\",\n     \"stream_change_cb\": \"pgoutput_change\",\n     \"stream_commit_cb\": \"pgoutput_stream_commit\",\n     \"stream_message_cb\": \"pgoutput_message\",\n+    \"stream_prepare_cb\": \"pgoutput_stream_prepare_txn\",\n     \"stream_start_cb\": \"pgoutput_stream_start\",\n     \"stream_stop_cb\": \"pgoutput_stream_stop\",\n     \"stream_truncate_cb\": \"pgoutput_truncate\",\n@@ -18,7 +23,7 @@\n   },\n   \"options\": [\n     {\n-      \"definition\": \"Protocol version. Currently versions 1 and 2 are supported. A valid version is required. The version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions.\",\n+      \"definition\": \"Protocol version. Currently versions 1 , 2 , and 3 are supported. A valid version is required. Version 2 is supported only for server version 14 and above, and it allows streaming of large in-progress transactions. Version 3 is supported only for server version 15 and above, and it allows streaming of two-phase commits.\",\n       \"name\": \"proto_version\"\n     },\n     {\n@@ -36,11 +41,16 @@\n     {\n       \"definition\": \"Boolean option to enable streaming of in-progress transactions. Minimum protocol version 2 is required to turn it on.\",\n       \"name\": \"streaming\"\n+    },\n+    {\n+      \"definition\": \"Boolean option to enable two-phase transactions. Minimum protocol version 3 is required to turn it on.\",\n+      \"name\": \"two_phase\"\n     }\n   ],\n   \"protocol_versions\": {\n     \"LOGICALREP_PROTO_MIN_VERSION_NUM\": \"1\",\n     \"LOGICALREP_PROTO_STREAM_VERSION_NUM\": \"2\",\n+    \"LOGICALREP_PROTO_TWOPHASE_VERSION_NUM\": \"3\",\n     \"LOGICALREP_PROTO_VERSION_NUM\": \"1\"\n   },\n   \"source_options\": [\n@@ -48,6 +58,7 @@\n     \"messages\",\n     \"proto_version\",\n     \"publication_names\",\n-    \"streaming\"\n+    \"streaming\",\n+    \"two_phase\"\n   ]\n }"}}