Repository navigation
Conversation
Brar
commented
Oct 25, 2026
- DropReplicationSlot no longer claims that dropping a logical slot created in another database fails. PostgreSQL removed that statement from its own docs as incorrect (14413d0ef5d).
- The StartReplication docs said that the methods return a Task, and one physical overload said it was for logical replication. The timeline parameter now says that 0 selects the server's current timeline.
- The snapshot mode docs named the wrong command as the first one of the transaction. LogicalSlotSnapshotInitMode.Use now says which transaction it needs, and that Npgsql can't start one on a replication connection yet.
- The physical CreateReplicationSlot says that the returned slot has no RestartLsn.
- WalReceiverStatusInterval now says to keep it below the server's wal_sender_timeout if the application can pause between messages.
- TransactionXid is the xid of the subtransaction for changes made in one, and PgOutputReplicationOptions.TwoPhase changes the slot itself.
- Fix the descriptions of the update and delete messages (when PostgreSQL sends which one), of timestamps that are DateTimes, of the prepared transaction base classes, and of the replication slot classes, which also wrap existing slots.
- Updates also carry the old key if a key column is stored externally.
- Remove comments about the removed NoSynchronizationContextScope, and fix the doc of the internal NpgsqlDataSource.Settings, which does contain the password.
- DropReplicationSlot no longer claims that dropping a logical slot created in another database fails. PostgreSQL removed that statement from its own docs as incorrect (14413d0ef5d). - The StartReplication docs said that the methods return a Task, and one physical overload said it was for logical replication. The timeline parameter now says that 0 selects the server's current timeline. - The snapshot mode docs named the wrong command as the first one of the transaction. LogicalSlotSnapshotInitMode.Use now says which transaction it needs, and that Npgsql can't start one on a replication connection yet. - The physical CreateReplicationSlot says that the returned slot has no RestartLsn. - WalReceiverStatusInterval now says to keep it below the server's wal_sender_timeout if the application can pause between messages. - TransactionXid is the xid of the subtransaction for changes made in one, and PgOutputReplicationOptions.TwoPhase changes the slot itself. - Fix the descriptions of the update and delete messages (when PostgreSQL sends which one), of timestamps that are DateTimes, of the prepared transaction base classes, and of the replication slot classes, which also wrap existing slots. - Updates also carry the old key if a key column is stored externally. - Remove comments about the removed NoSynchronizationContextScope, and fix the doc of the internal NpgsqlDataSource.Settings, which does contain the password. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The changes are documentation-only, and the reviewed evidence identifies no unresolved correctness or approval-blocking issues.
No open issues 🎉
What changed in this PR
This PR corrects Npgsql’s replication API documentation without changing runtime behavior, aligning comments with the API types and PostgreSQL behavior.
Changes:
- Clarifies replication slot behavior, snapshot requirements, timelines, keepalive guidance, and two-phase decoding.
- Corrects message descriptions, timestamp documentation, and streaming return types.
- Removes obsolete comments and corrects the internal data source settings documentation.
| File | Description |
|---|---|
src/Npgsql/Replication/TestDecoding/TestDecodingReplicationSlot.cs |
Removes duplicated wording. |
src/Npgsql/Replication/TestDecoding/TestDecodingConnectionExtensions.cs |
Corrects snapshot and return-type docs; removes obsolete comments. |
src/Npgsql/Replication/ReplicationSlot.cs |
Includes existing slots in class and property descriptions. |
src/Npgsql/Replication/ReplicationMessage.cs |
Removes incorrect timestamp-unit wording. |
src/Npgsql/Replication/ReplicationConnection.cs |
Clarifies keepalive guidance and slot-dropping behavior. |
src/Npgsql/Replication/PhysicalReplicationConnection.cs |
Corrects slot creation, timeline, and streaming documentation. |
src/Npgsql/Replication/PgOutput/PgOutputReplicationSlot.cs |
Removes duplicated wording. |
src/Npgsql/Replication/PgOutput/PgOutputReplicationOptions.cs |
Documents persistent two-phase slot changes. |
src/Npgsql/Replication/PgOutput/PgOutputConnectionExtensions.cs |
Corrects snapshot and return-type docs; removes obsolete comments. |
src/Npgsql/Replication/PgOutput/Messages/UpdateMessage.cs |
Corrects update-message descriptions and references. |
src/Npgsql/Replication/PgOutput/Messages/TransactionalMessage.cs |
Explains subtransaction identifiers. |
src/Npgsql/Replication/PgOutput/Messages/PrepareMessageBase.cs |
Includes stream prepare messages in the summary. |
src/Npgsql/Replication/PgOutput/Messages/PreparedTransactionControlMessage.cs |
Lists all supported prepared-transaction message types. |
src/Npgsql/Replication/PgOutput/Messages/IndexUpdateMessage.cs |
Clarifies when updates include the old key. |
src/Npgsql/Replication/PgOutput/Messages/FullDeleteMessage.cs |
Removes duplicated replica identity wording. |
src/Npgsql/Replication/PgOutput/Messages/DeleteMessage.cs |
Corrects the relation’s documentation reference. |
src/Npgsql/Replication/PgOutput/Messages/DefaultUpdateMessage.cs |
Clarifies when updates contain only the new row. |
src/Npgsql/Replication/PgOutput/Messages/BeginMessage.cs |
Removes incorrect timestamp-unit wording. |
src/Npgsql/Replication/LogicalSlotSnapshotInitMode.cs |
Documents transaction requirements and current API limitations. |
src/Npgsql/Replication/Internal/LogicalReplicationSlot.cs |
Generalizes descriptions to include existing logical slots. |
src/Npgsql/Replication/Internal/LogicalReplicationConnectionExtensions.cs |
Corrects snapshot command and streaming return-type docs. |
src/Npgsql/NpgsqlDataSource.cs |
Clarifies that internal settings retain the password. |
Review effort: Balanced
roji
left a comment
There was a problem hiding this comment.
Recommendation: Proceed with this documentation-only cleanup. I found no blocking accuracy issues or requested changes.
Problem. The existing comments contain substantive errors, not just typos: they describe decoded DateTime values as microsecond counts, describe IAsyncEnumerable<T> returns as tasks, and incorrectly tie update-message classes to the table's replica-identity setting. For a table with the default identity:
CREATE TABLE t (id int PRIMARY KEY, value int);
INSERT INTO t VALUES (1, 0);
UPDATE t SET value = 1; -- DefaultUpdateMessage
UPDATE t SET id = 2; -- IndexUpdateMessage, despite REPLICA IDENTITY DEFAULTExpected approach. Correct the XML comments in place, explain protocol-dependent behavior where necessary, and leave the .NET API and implementation unchanged. This does not need new runtime functionality or a broader documentation rewrite.
Alignment. All 22 changed files contain comment-only edits. The revised update-message descriptions match the parser's actual tuple-based dispatch, including unchanged externally stored keys. The new two-phase warning correctly describes persistent slot state rather than a per-session switch. The snapshot-use restriction also accurately distinguishes PostgreSQL's requirements from what Npgsql currently exposes. The other return-type, timestamp, slot-wrapper, inheritance, and stale-comment corrections are appropriate and add no implementation complexity.
Gaps. None requiring changes. I checked the historical snapshot requirements against PostgreSQL 15 and 16 source; I did not run a multi-version server matrix. PostgreSQL's protocol documentation understates the unchanged-TOAST-key case, but its heap implementation and the observed messages support this PR's wording.
Manual validation. I built this checkout and ran a standalone C# API consumer against an isolated PostgreSQL 18.4 server, not just unit tests. It confirmed the example above; unchanged/changed USING INDEX keys; an unchanged externally stored primary key; full-row updates/deletes; UTC timestamps; physical-slot restart positions and timeline 0; cross-database logical-slot deletion; and streamed subtransaction XIDs distinct from the top-level XID. Enabling TwoPhase, disconnecting, and reconnecting without that option still delivered PrepareMessage. A 100 ms status interval kept a paused consumer alive for 3 seconds with a 1-second sender timeout. Direct replication-protocol commands also confirmed that PostgreSQL 18 can disable two-phase decoding and accepts the documented snapshot-use transaction.
Posted by copilot
roji
left a comment
There was a problem hiding this comment.
Doc-only change; agentic review found no issues, approving.