July 25, 2019·4 min read·engineeringpostgresqlreplicationindexes

pglogical 2.2.2 supports tables with covering unique indexes

A maintenance update improves index compatibility and repairs parallel DDL execution on subscribers. Its changes sit within a replication model that selects tables and changes at database level.

An index chosen for local query performance can also matter to logical replication. pglogical 2.2.2 adds support for replicating tables with covering unique indexes. The July 25 announcement places this compatibility change alongside better failover-slot detection and a fix for crashes during replicated DDL.

This is a maintenance release of a PostgreSQL extension, not a new physical standby mechanism. Its significance becomes clearer when the replication contract is explicit. A logical subscriber receives selected changes and applies them to its own database objects. Compatibility between the provider's schema and the subscriber's schema remains part of making that process work.

I like PostgreSQL's capacity to support substantial extensions, and pglogical is a useful example. The value here is the ability to choose what data moves between databases. That flexibility also makes schema details relevant in ways that a simple description of a replica can conceal.

Replication sets define the work

The documentation at the 2.2.2 tag describes a publish-and-subscribe model operating per database. Physical streaming replication operates at whole-server scope in the comparison given there. pglogical instead groups tables into replication sets and lets subscribers select those sets.

A replication set can control which changes it carries, including whether updates and deletes are replicated. Tables can belong to multiple sets, and subscribers can subscribe to multiple sets. The documented result is the union of the applicable tables and actions. A table does not begin replicating merely because it exists in the provider database.

The extension also supports selected columns and provider-side row filters. This allows the replicated dataset to differ deliberately from the provider's full dataset. That is useful for selective replication and for collecting data from multiple upstream databases, both named use cases in the versioned documentation.

Those capabilities have consequences for setup. Adding all existing tables in a schema to a replication set does not automatically add tables created later. The documented function concerns the tables present when it runs. Automatically assigning future tables requires an additional mechanism, for which the README gives an event-trigger example.

These details help explain why a maintenance fix for a particular index form matters. A table that meets the application's schema requirements must also remain usable by the extension's replication machinery. Supporting covering unique indexes removes one stated compatibility limitation without changing the replication-set model.

Matching names do not guarantee matching semantics

The versioned documentation requires corresponding tables to have the same names and schemas. Their columns must have matching data types, and primary keys must match. Subscriber constraints such as checks and nullability must be the same as, or more permissive than, those on the provider.

The reason is visible in the direction of data movement. A change accepted by the provider can fail to apply if the subscriber imposes a stronger rule. The documentation consequently discourages adding unique constraints beyond the primary key. A subscriber's locally valid schema can still reject an incoming change that was valid upstream.

This is a practical tradeoff of selective logical replication. The subscriber has database objects with their own definitions, so successful delivery depends on compatibility beyond the transport connection. The new covering-index support addresses one part of that interaction, while the existing schema requirements remain relevant.

The announcement does not say that 2.2.2 removes every constraint or identity restriction. It identifies support for tables with covering unique indexes. Reading that as a universal relaxation of subscriber schema requirements would go beyond the release's stated change.

My preference is to describe these systems by the data and operations they reproduce. A subscription to selected tables is useful, but it does not imply that every object and every administrative operation follows automatically. The versioned documentation makes that distinction concrete through its replication sets and explicit DDL interface.

DDL has a separate replication path

The release fixes a crash when replicated DDL uses parallel execution on the subscriber. That places the failure in execution of the schema command, rather than in selecting table rows for replication. It matters to users whose schema-management workflow uses the extension's DDL facility.

The documented pglogical.replicate_ddl_command function executes a command locally and queues it for subscribers belonging to the specified replication sets. The default DDL replication set is named ddl_sql. This is an explicit operation with defined recipients.

The maintenance fix improves that operation's execution path. It does not mean ordinary schema changes are now implicitly transmitted without using the documented mechanism. Separating the interface from the fix prevents an upgrade note from becoming an incorrect promise about automatic schema synchronization.

The announcement also mentions improved tests for column and row filtering, more PostgreSQL-consistent error messages, and improved failover-slot detection. It gives no broader guarantee about automatic failover. The concrete release claims concern those specific components.

The README distinguishes initiating synchronization from waiting for completion. Creating a subscription starts synchronization in the background, while a separate waiting function observes its completion. Likewise, adding a replication set to an existing subscription activates consumption without synchronizing its data. These distinctions remain important when interpreting a healthy connection as evidence of a complete dataset. Version 2.2.2 improves compatibility and execution within that existing model, including the covering-index case and subscriber-side DDL crash.