--- a/Makefile
+++ b/Makefile
@@ -39,6 +39,8 @@ DATA = pglogical--1.0.0.sql pglogical--1
 	   pglogical--2.4.3.sql \
 	   pglogical--2.4.3--2.4.4.sql \
 	   pglogical--2.4.4.sql \
+	   pglogical--2.4.4--2.4.5.sql \
+	   pglogical--2.4.5.sql
 
 OBJS = pglogical_apply.o pglogical_conflict.o pglogical_manager.o \
 	   pglogical.o pglogical_node.o pglogical_relcache.o \
@@ -54,7 +56,7 @@ SCRIPTS_built = pglogical_create_subscri
 
 REGRESS = preseed infofuncs init_fail init preseed_check basic extended conflict_secondary_unique \
 		  toasted replication_set matview bidirectional \
-		  interfaces foreign_key functions copy triggers parallel row_filter \
+		  interfaces foreign_key functions copy sequence triggers parallel row_filter \
 		  att_list column_filter apply_delay \
 		  node_origin_cascade drop
 
@@ -66,6 +68,7 @@ EXTRA_CLEAN += compat94/pglogical_compat
 			   compat14/pglogical_compat.o compat14/pglogical_compat.bc \
 			   compat15/pglogical_compat.o compat15/pglogical_compat.bc \
 			   compat16/pglogical_compat.o compat16/pglogical_compat.bc \
+			   compat17/pglogical_compat.o compat17/pglogical_compat.bc \
 			   pglogical_create_subscriber.o
 
 # The # in #define is taken as a comment, per https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=142043
@@ -140,7 +143,7 @@ else
 # But this is still not ideal.
 regresscheck:
 	$(MKDIR_P) regression_output
-	$(pg_regress_check) \
+	$(pg_regress_installcheck) \
 	    --temp-config ./regress-postgresql.conf \
 	    --temp-instance=./tmp_check \
 	    --outputdir=./regression_output \
--- /dev/null
+++ b/compat17/pglogical_compat.c
@@ -0,0 +1,12 @@
+/*-------------------------------------------------------------------------
+ *
+ * pglogical_compat.c
+ *              compatibility functions (mainly with different PG versions)
+ *
+ * Copyright (c) 2015, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *              pglogical_compat.c
+ *
+ *-------------------------------------------------------------------------
+ */
--- /dev/null
+++ b/compat17/pglogical_compat.h
@@ -0,0 +1,169 @@
+#ifndef PG_LOGICAL_COMPAT_H
+#define PG_LOGICAL_COMPAT_H
+
+#include "access/amapi.h"
+#include "access/heapam.h"
+#include "access/table.h"
+#include "access/tableam.h"
+#include "utils/varlena.h"
+
+#define WaitLatchOrSocket(latch, wakeEvents, sock, timeout) \
+	WaitLatchOrSocket(latch, wakeEvents, sock, timeout, PG_WAIT_EXTENSION)
+
+#define WaitLatch(latch, wakeEvents, timeout) \
+	WaitLatch(latch, wakeEvents, timeout, PG_WAIT_EXTENSION)
+
+#define GetCurrentIntegerTimestamp() GetCurrentTimestamp()
+
+#define pg_analyze_and_rewrite(parsetree, query_string, paramTypes, numParams) \
+	pg_analyze_and_rewrite_fixedparams(parsetree, query_string, paramTypes, numParams, NULL)
+
+#define CreateCommandTag(raw_parsetree) \
+	CreateCommandTag(raw_parsetree->stmt)
+
+#define PortalRun(portal, count, isTopLevel, dest, altdest, qc) \
+	PortalRun(portal, count, isTopLevel, true, dest, altdest, qc)
+
+#define ExecAlterExtensionStmt(stmt) \
+	ExecAlterExtensionStmt(NULL, stmt)
+
+/*
+ * Pg 11 adds an argument here.  We don't need to special-case 2ndQPostgres
+ * anymore because it adds a separate ExecBRDeleteTriggers2 now, so this only
+ * handles the stock Pg11 change.
+ */
+#define ExecBRDeleteTriggers(estate, epqstate, relinfo, tupleid, fdw_trigtuple) \
+	ExecBRDeleteTriggers(estate, epqstate, relinfo, tupleid, fdw_trigtuple, NULL, NULL, NULL)
+
+#undef ExecEvalExpr
+#define ExecEvalExpr(expr, econtext, isNull, isDone) \
+	((*(expr)->evalfunc) (expr, econtext, isNull))
+
+#define Form_pg_sequence Form_pg_sequence_data
+
+#define InitResultRelInfo(resultRelInfo, resultRelationDesc, resultRelationIndex, instrument_options) \
+	InitResultRelInfo(resultRelInfo, resultRelationDesc, resultRelationIndex, NULL, instrument_options)
+
+#define ExecARUpdateTriggers(estate, relinfo, tupleid, fdw_trigtuple, newslot, recheckIndexes) \
+	ExecARUpdateTriggers(estate, relinfo, NULL, NULL, tupleid, fdw_trigtuple, newslot, recheckIndexes, NULL, false)
+
+#define ExecARInsertTriggers(estate, relinfo, slot, recheckIndexes) \
+	ExecARInsertTriggers(estate, relinfo, slot, recheckIndexes, NULL)
+
+#define ExecARDeleteTriggers(estate, relinfo, tupleid, fdw_trigtuple) \
+	ExecARDeleteTriggers(estate, relinfo, tupleid, fdw_trigtuple, NULL, false)
+
+#define ExecBRUpdateTriggers(estate, epqstate, relinfo, tupleid, fdw_trigtuple, slot) \
+	ExecBRUpdateTriggers(estate, epqstate, relinfo, tupleid, fdw_trigtuple, slot, NULL, NULL)
+
+#define makeDefElem(name, arg) makeDefElem(name, arg, -1)
+
+#define PGLstandard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, sentToRemote, qc) \
+	standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc)
+
+#define PGLnext_ProcessUtility_hook(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, sentToRemote, qc) \
+	next_ProcessUtility_hook(pstmt, queryString, readOnlyTree, context, params, queryEnv, dest, qc)
+
+#define PGLCreateTrigger(stmt, queryString, relOid, refRelOid, constraintOid, indexOid, isInternal) \
+	CreateTrigger(stmt, queryString, relOid, refRelOid, constraintOid, indexOid, InvalidOid, InvalidOid, NULL, isInternal, false);
+
+#define	PGLDoCopy(stmt, queryString, processed) \
+	do \
+	{ \
+		ParseState* pstate = make_parsestate(NULL); \
+		DoCopy(pstate, stmt, -1, 0, processed); \
+		free_parsestate(pstate); \
+	} while (false);
+
+#define PGLReplicationSlotCreate(name, db_specific, persistency) ReplicationSlotCreate(name, db_specific, persistency)
+
+#ifndef rbtxn_has_catalog_changes
+#define rbtxn_has_catalog_changes(txn) (txn->has_catalog_changes)
+#endif
+
+/* ad7dbee368a */
+#define ExecInitExtraTupleSlot(estate) \
+	ExecInitExtraTupleSlot(estate, NULL, &TTSOpsHeapTuple)
+
+#define ACL_OBJECT_RELATION OBJECT_TABLE
+#define ACL_OBJECT_SEQUENCE OBJECT_SEQUENCE
+
+#define DatumGetJsonb DatumGetJsonbP
+
+#define pgl_heap_attisnull(tup, attnum, tupledesc) \
+	heap_attisnull(tup, attnum, tupledesc)
+
+/* 2a10fdc4307a667883f7a3369cb93a721ade9680 */
+#define getObjectDescription(object) getObjectDescription(object, false)
+
+/* e997a0c642860a96df0151cbeccfecbdf0450d08 */
+#define GetFlushRecPtr() GetFlushRecPtr(NULL)
+
+/* 216a784829c2c5f03ab0c43e009126cbb819e9b2 */
+#define PGLreplorigin_session_setup(node) replorigin_session_setup(node, 0)
+
+/* 19d8e2308bc51ec4ab993ce90077342c915dd116 */
+#define ExecInsertIndexTuples(resultRelInfo, slot, estate, update, noDupErr, specConflict, arbiterIndexes) \
+	ExecInsertIndexTuples(resultRelInfo, slot, estate, update, noDupErr, specConflict, arbiterIndexes, false)
+
+/* 70b42f2790292cc30aa07563f343f7ba6749af01 */
+#define EvalPlanQualInit(epqstate, parentestate, subplan, auxrowmarks, epqParam) \
+	EvalPlanQualInit(epqstate, parentestate, subplan, auxrowmarks, epqParam, NIL)
+
+/* 6a72c42fd5af7ada49584694f543eb06dddb4a87 */
+#define MemoryContextResetAndDeleteChildren(ctx) MemoryContextReset(ctx)
+
+/* 75680c3d805e2323cd437ac567f0677fdfc7b680 */
+#define SPI_push() ((void) 0)
+#define SPI_pop()  ((void) 0)
+#define tuplestore_donestoring(state)  ((void) 0)
+
+/* 89e5ef7e21812916c9cf9fcf56e45f0f74034656 */
+typedef enum ObjectClass
+{
+   OCLASS_CLASS,               /* pg_class */
+   OCLASS_PROC,                /* pg_proc */
+   OCLASS_TYPE,                /* pg_type */
+   OCLASS_CAST,                /* pg_cast */
+   OCLASS_COLLATION,           /* pg_collation */
+   OCLASS_CONSTRAINT,          /* pg_constraint */
+   OCLASS_CONVERSION,          /* pg_conversion */
+   OCLASS_DEFAULT,             /* pg_attrdef */
+   OCLASS_LANGUAGE,            /* pg_language */
+   OCLASS_LARGEOBJECT,         /* pg_largeobject */
+   OCLASS_OPERATOR,            /* pg_operator */
+   OCLASS_OPCLASS,             /* pg_opclass */
+   OCLASS_OPFAMILY,            /* pg_opfamily */
+   OCLASS_AM,                  /* pg_am */
+   OCLASS_AMOP,                /* pg_amop */
+   OCLASS_AMPROC,              /* pg_amproc */
+   OCLASS_REWRITE,             /* pg_rewrite */
+   OCLASS_TRIGGER,             /* pg_trigger */
+   OCLASS_SCHEMA,              /* pg_namespace */
+   OCLASS_STATISTIC_EXT,       /* pg_statistic_ext */
+   OCLASS_TSPARSER,            /* pg_ts_parser */
+   OCLASS_TSDICT,              /* pg_ts_dict */
+   OCLASS_TSTEMPLATE,          /* pg_ts_template */
+   OCLASS_TSCONFIG,            /* pg_ts_config */
+   OCLASS_ROLE,                /* pg_authid */
+   OCLASS_ROLE_MEMBERSHIP,     /* pg_auth_members */
+   OCLASS_DATABASE,            /* pg_database */
+   OCLASS_TBLSPACE,            /* pg_tablespace */
+   OCLASS_FDW,                 /* pg_foreign_data_wrapper */
+   OCLASS_FOREIGN_SERVER,      /* pg_foreign_server */
+   OCLASS_USER_MAPPING,        /* pg_user_mapping */
+   OCLASS_DEFACL,              /* pg_default_acl */
+   OCLASS_EXTENSION,           /* pg_extension */
+   OCLASS_EVENT_TRIGGER,       /* pg_event_trigger */
+   OCLASS_PARAMETER_ACL,       /* pg_parameter_acl */
+   OCLASS_POLICY,              /* pg_policy */
+   OCLASS_PUBLICATION,         /* pg_publication */
+   OCLASS_PUBLICATION_NAMESPACE,   /* pg_publication_namespace */
+   OCLASS_PUBLICATION_REL,     /* pg_publication_rel */
+   OCLASS_SUBSCRIPTION,        /* pg_subscription */
+   OCLASS_TRANSFORM            /* pg_transform */
+} ObjectClass;
+
+#define LAST_OCLASS        OCLASS_TRANSFORM
+
+#endif
--- a/compat94/pglogical_compat.h
+++ b/compat94/pglogical_compat.h
@@ -188,4 +188,6 @@ extern void CatalogTupleDelete(Relation
 #define pg_plan_queries(querytrees, query_string, cursorOptions, boundParams) \
 	pg_plan_queries(querytrees, cursorOptions, boundParams)
 
+#define PGLreplorigin_session_setup(node) replorigin_session_setup(node)
+
 #endif
--- a/docs/README.md
+++ b/docs/README.md
@@ -4,6 +4,13 @@ The pglogical 2 extension provides logic
 using a publish/subscribe model. It is based on technology developed as part
 of the BDR project (http://2ndquadrant.com/BDR).
 
+While pglogical is actively maintained, EnterpriseDB (which acquired
+2ndQuadrant in 2020) focuses new feature development on a descendant
+of pglogical: [Postgres
+Distributed](https://www.enterprisedb.com/docs/pgd/latest/overview/). Postgres
+Distributed introduced new features such as DDL replication, write
+leaders, parallel apply, and more.
+
 We use the following terms to describe data streams between nodes, deliberately
 reused from the earlier Slony technology:
 * Nodes - PostgreSQL database instances
@@ -73,7 +80,6 @@ If you don’t have PostgreSQL already:
 
  - Install the appropriate PGDG repo rpm from http://yum.postgresql.org/repopackages.php
  - Install PostgreSQL
-    - PostgreSQL 9.4: `yum install postgresql94-server postgresql94-contrib`
     - PostgreSQL 9.5: `yum install postgresql95-server postgresql95-contrib`
     - PostgreSQL 9.6: `yum install postgresql96-server postgresql96-contrib`
     - PostgreSQL 10: `yum install postgresql10-server postgresql10-contrib`
@@ -82,40 +88,23 @@ If you don’t have PostgreSQL already:
     - PostgreSQL 13: `yum install postgresql13-server postgresql13-contrib`
     - PostgreSQL 14: `yum install postgresql14-server postgresql14-contrib`
     - PostgreSQL 15: `yum install postgresql15-server postgresql15-contrib`
-
-Then install the “2ndQuadrant’s General Public” repository for your PostgreSQL
-version, by running the following instructions as root on the destination Linux server:
-
- - PostgreSQL 9.4: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/9.4/rpm | bash`
- - PostgreSQL 9.5: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/9.5/rpm | bash`
- - PostgreSQL 9.6: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/9.6/rpm | bash`
- - PostgreSQL 10: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/10/rpm | bash`
- - PostgreSQL 11: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/11/rpm | bash`
- - PostgreSQL 12: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/12/rpm | bash`
- - PostgreSQL 13: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/13/rpm | bash`
- - PostgreSQL 14: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/14/rpm | bash`
- - PostgreSQL 15: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/15/rpm | bash`
+    - PostgreSQL 16: `yum install postgresql16-server postgresql16-contrib`
+    - PostgreSQL 17: `yum install postgresql17-server postgresql17-contrib`
 
 ##### Installation
 
-Once the repository is installed, you can proceed to pglogical for your PostgreSQL version:
-
- - PostgreSQL 9.4: `yum install postgresql94-pglogical`
- - PostgreSQL 9.5: `yum install postgresql95-pglogical`
- - PostgreSQL 9.6: `yum install postgresql96-pglogical`
- - PostgreSQL 10: `yum install postgresql10-pglogical`
- - PostgreSQL 11: `yum install postgresql11-pglogical`
- - PostgreSQL 12: `yum install postgresql12-pglogical`
- - PostgreSQL 13: `yum install postgresql13-pglogical`
- - PostgreSQL 14: `yum install postgresql14-pglogical`
- - PostgreSQL 15: `yum install postgresql15-pglogical`
+You can proceed to install pglogical for your PostgreSQL version:
 
-You may be prompted to accept the repository GPG key for package signing:
-
-    Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-2NDQ-DL-DEFAULT Importing GPG key 0xD6BAF0C3: Userid : "Public repository signing key 2ndQuadrant <ci@2ndquadrant.com>" Fingerprint: 8565 305c ea7d 0b66 4933 d250 9904 cd4b d6ba f0c3 From : /etc/pki/rpm-gpg/RPM-GPG-KEY-2NDQ-DL-DEFAULT Is this ok [y/N]:
-
-If so, accept the key (if it matches the above) by pressing ‘y’ then enter.
-(It’s signed by the 2ndQuadrant master packaging key, if you want to verify that.)
+ - PostgreSQL 9.5: `yum install pglogical_95`
+ - PostgreSQL 9.6: `yum install pglogical_96`
+ - PostgreSQL 10: `yum install pglogical_10`
+ - PostgreSQL 11: `yum install pglogical_11`
+ - PostgreSQL 12: `yum install pglogical_12`
+ - PostgreSQL 13: `yum install pglogical_13`
+ - PostgreSQL 14: `yum install pglogical_14`
+ - PostgreSQL 15: `yum install pglogical_15`
+ - PostgreSQL 16: `yum install pglogical_16`
+ - PostgreSQL 17: `yum install pglogical_17`
 
 #### Installing pglogical with APT
 
@@ -124,16 +113,23 @@ Debian (e.g. Ubuntu).
 
 ##### Pre-requisites
 
-You can install the “2ndQuadrant’s General Public” repository by running the
-following instructions as root on the destination Linux server: `curl https://techsupport.enterprisedb.com/api/repository/dl/default/release/deb | bash`
-
- - Add the http://apt.postgresql.org/ repository. See the site for instructions.
+ - Add the https://apt.postgresql.org/ repository. See the site for instructions.
+ - Install PostgreSQL
+    - PostgreSQL 9.5: `sudo apt-get install postgresql-9.5`
+    - PostgreSQL 9.6: `sudo apt-get install postgresql-9.6`
+    - PostgreSQL 10: `sudo apt-get install postgresql-10`
+    - PostgreSQL 11: `sudo apt-get install postgresql-11`
+    - PostgreSQL 12: `sudo apt-get install postgresql-12`
+    - PostgreSQL 13: `sudo apt-get install postgresql-13`
+    - PostgreSQL 14: `sudo apt-get install postgresql-14`
+    - PostgreSQL 15: `sudo apt-get install postgresql-15`
+    - PostgreSQL 16: `sudo apt-get install postgresql-16`
+    - PostgreSQL 17: `sudo apt-get install postgresql-17`
 
 ##### Installation
 
 Once pre-requisites are complete, installing pglogical is simply a matter of executing the following for your version of PostgreSQL:
 
- - PostgreSQL 9.4: `sudo apt-get install postgresql-9.4-pglogical`
  - PostgreSQL 9.5: `sudo apt-get install postgresql-9.5-pglogical`
  - PostgreSQL 9.6: `sudo apt-get install postgresql-9.6-pglogical`
  - PostgreSQL 10: `sudo apt-get install postgresql-10-pglogical`
@@ -142,6 +138,8 @@ Once pre-requisites are complete, instal
  - PostgreSQL 13: `sudo apt-get install postgresql-13-pglogical`
  - PostgreSQL 14: `sudo apt-get install postgresql-14-pglogical`
  - PostgreSQL 15: `sudo apt-get install postgresql-15-pglogical`
+ - PostgreSQL 16: `sudo apt-get install postgresql-16-pglogical`
+ - PostgreSQL 17: `sudo apt-get install postgresql-17-pglogical`
 
 ### From source code
 
@@ -156,12 +154,12 @@ you don't have `pg_config`.
 Then run `make` to compile, and `make install` to
 install. You might need to use `sudo` for the install step.
 
-e.g. for a typical Fedora or RHEL 7 install, assuming you're using the
+e.g. for a typical Fedora or RHEL 9 install, assuming you're using the
 [yum.postgresql.org](http://yum.postgresql.org) packages for PostgreSQL:
 
-    sudo dnf install postgresql95-devel
-    PATH=/usr/pgsql-9.5/bin:$PATH make clean all
-    sudo PATH=/usr/pgsql-9.5/bin:$PATH make install
+    sudo dnf install postgresql17-devel
+    PATH=/usr/pgsql-17/bin:$PATH make clean all
+    sudo PATH=/usr/pgsql-17/bin:$PATH make install
 
 ## Usage
 
@@ -832,6 +830,10 @@ subscriber database(s) remain compatible
 pglogical provides the `pglogical.replicate_ddl_command` function to allow DDL
 to be run on the provider and subscriber at a consistent point.
 
+If you need DDL replication, you can look at EnterpriseDB's [Postgres
+Distributed](https://www.enterprisedb.com/docs/pgd/latest/overview/)
+product which is built on pglogical.
+
 ### No replication queue flush
 
 There's no support for freezing transactions on the master and waiting until
@@ -956,6 +958,18 @@ pglogical copyright is donated to Postgr
 
 ## Appendix B: Release Notes
 
+### pglogical 2.4.5
+
+Version 2.4.5 is a maintenance release of pglogical 2.
+
+#### Changes
+
+* Add support for PostgreSQL 17.
+
+* Maintain indexes when updating pglogical.sequence_state.
+
+* Don't use invalid indexes for conflict resolution.
+
 ### pglogical 2.4.4
 
 Version 2.4.4 is a maintenance release of pglogical 2.
--- a/expected/init.out
+++ b/expected/init.out
@@ -58,7 +58,7 @@ ALTER EXTENSION pglogical UPDATE;
                    List of installed extensions
    Name    | Version |  Schema   |          Description           
 -----------+---------+-----------+--------------------------------
- pglogical | 2.4.4   | pglogical | PostgreSQL Logical Replication
+ pglogical | 2.4.5   | pglogical | PostgreSQL Logical Replication
 (1 row)
 
 SELECT * FROM pglogical.create_node(node_name := 'test_provider', dsn := (SELECT provider_dsn FROM pglogical_regress_variables()) || ' user=super');
--- /dev/null
+++ b/expected/sequence.out
@@ -0,0 +1,57 @@
+-- like bt_index_check('pglogical.sequence_state', true)
+CREATE FUNCTION heapallindexed() RETURNS void AS $$
+DECLARE
+	count_seqscan int;
+	count_idxscan int;
+BEGIN
+	count_seqscan := (SELECT count(*) FROM pglogical.sequence_state);
+	SET enable_seqscan = off;
+	count_idxscan := (SELECT count(*) FROM pglogical.sequence_state);
+	RESET enable_seqscan;
+	IF count_seqscan <> count_idxscan THEN
+		RAISE 'seqscan found % rows, but idxscan found % rows',
+			count_seqscan, count_idxscan;
+	END IF;
+END
+$$ LANGUAGE plpgsql;
+-- Replicate one sequence.
+CREATE SEQUENCE stress;
+SELECT * FROM pglogical.create_replication_set('stress_seq');
+ create_replication_set 
+------------------------
+             2261733486
+(1 row)
+
+SELECT * FROM pglogical.replication_set_add_sequence('stress_seq', 'stress');
+ replication_set_add_sequence 
+------------------------------
+ t
+(1 row)
+
+SELECT pglogical.synchronize_sequence('stress');
+ synchronize_sequence 
+----------------------
+ t
+(1 row)
+
+SELECT heapallindexed();
+ heapallindexed 
+----------------
+ 
+(1 row)
+
+-- Sync it 400 times in one transaction, to cross a pglogical.sequence_state
+-- page boundary and get a non-HOT update.
+DO $$
+BEGIN
+  FOR i IN 1..400 LOOP
+    PERFORM pglogical.synchronize_sequence('stress');
+  END LOOP;
+END;
+$$;
+SELECT heapallindexed();
+ heapallindexed 
+----------------
+ 
+(1 row)
+
--- /dev/null
+++ b/pglogical--2.4.5.sql
@@ -0,0 +1,249 @@
+\echo Use "CREATE EXTENSION pglogical" to load this file. \quit
+
+CREATE TABLE pglogical.node (
+    node_id oid NOT NULL PRIMARY KEY,
+    node_name name NOT NULL UNIQUE
+) WITH (user_catalog_table=true);
+
+CREATE TABLE pglogical.node_interface (
+    if_id oid NOT NULL PRIMARY KEY,
+    if_name name NOT NULL, -- default same as node name
+    if_nodeid oid REFERENCES node(node_id),
+    if_dsn text NOT NULL,
+    UNIQUE (if_nodeid, if_name)
+);
+
+CREATE TABLE pglogical.local_node (
+    node_id oid PRIMARY KEY REFERENCES node(node_id),
+    node_local_interface oid NOT NULL REFERENCES node_interface(if_id)
+);
+
+CREATE TABLE pglogical.subscription (
+    sub_id oid NOT NULL PRIMARY KEY,
+    sub_name name NOT NULL UNIQUE,
+    sub_origin oid NOT NULL REFERENCES node(node_id),
+    sub_target oid NOT NULL REFERENCES node(node_id),
+    sub_origin_if oid NOT NULL REFERENCES node_interface(if_id),
+    sub_target_if oid NOT NULL REFERENCES node_interface(if_id),
+    sub_enabled boolean NOT NULL DEFAULT true,
+    sub_slot_name name NOT NULL,
+    sub_replication_sets text[],
+    sub_forward_origins text[],
+    sub_apply_delay interval NOT NULL DEFAULT '0',
+    sub_force_text_transfer boolean NOT NULL DEFAULT 'f'
+);
+
+CREATE TABLE pglogical.local_sync_status (
+    sync_kind "char" NOT NULL CHECK (sync_kind IN ('i', 's', 'd', 'f')),
+    sync_subid oid NOT NULL REFERENCES pglogical.subscription(sub_id),
+    sync_nspname name,
+    sync_relname name,
+    sync_status "char" NOT NULL,
+	sync_statuslsn pg_lsn NOT NULL,
+    UNIQUE (sync_subid, sync_nspname, sync_relname)
+);
+
+
+CREATE FUNCTION pglogical.create_node(node_name name, dsn text)
+RETURNS oid STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_create_node';
+CREATE FUNCTION pglogical.drop_node(node_name name, ifexists boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_drop_node';
+
+CREATE FUNCTION pglogical.alter_node_add_interface(node_name name, interface_name name, dsn text)
+RETURNS oid STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_node_add_interface';
+CREATE FUNCTION pglogical.alter_node_drop_interface(node_name name, interface_name name)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_node_drop_interface';
+
+CREATE FUNCTION pglogical.create_subscription(subscription_name name, provider_dsn text,
+    replication_sets text[] = '{default,default_insert_only,ddl_sql}', synchronize_structure boolean = false,
+    synchronize_data boolean = true, forward_origins text[] = '{all}', apply_delay interval DEFAULT '0',
+    force_text_transfer boolean = false)
+RETURNS oid STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_create_subscription';
+CREATE FUNCTION pglogical.drop_subscription(subscription_name name, ifexists boolean DEFAULT false)
+RETURNS oid STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_drop_subscription';
+
+CREATE FUNCTION pglogical.alter_subscription_interface(subscription_name name, interface_name name)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_interface';
+
+CREATE FUNCTION pglogical.alter_subscription_disable(subscription_name name, immediate boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_disable';
+CREATE FUNCTION pglogical.alter_subscription_enable(subscription_name name, immediate boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_enable';
+
+CREATE FUNCTION pglogical.alter_subscription_add_replication_set(subscription_name name, replication_set name)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_add_replication_set';
+CREATE FUNCTION pglogical.alter_subscription_remove_replication_set(subscription_name name, replication_set name)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_remove_replication_set';
+
+CREATE FUNCTION pglogical.show_subscription_status(subscription_name name DEFAULT NULL,
+    OUT subscription_name text, OUT status text, OUT provider_node text,
+    OUT provider_dsn text, OUT slot_name text, OUT replication_sets text[],
+    OUT forward_origins text[])
+RETURNS SETOF record STABLE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_show_subscription_status';
+
+CREATE TABLE pglogical.replication_set (
+    set_id oid NOT NULL PRIMARY KEY,
+    set_nodeid oid NOT NULL,
+    set_name name NOT NULL,
+    replicate_insert boolean NOT NULL DEFAULT true,
+    replicate_update boolean NOT NULL DEFAULT true,
+    replicate_delete boolean NOT NULL DEFAULT true,
+    replicate_truncate boolean NOT NULL DEFAULT true,
+    UNIQUE (set_nodeid, set_name)
+) WITH (user_catalog_table=true);
+
+CREATE TABLE pglogical.replication_set_table (
+    set_id oid NOT NULL,
+    set_reloid regclass NOT NULL,
+    set_att_list text[],
+    set_row_filter pg_node_tree,
+    PRIMARY KEY(set_id, set_reloid)
+) WITH (user_catalog_table=true);
+
+CREATE TABLE pglogical.replication_set_seq (
+    set_id oid NOT NULL,
+    set_seqoid regclass NOT NULL,
+    PRIMARY KEY(set_id, set_seqoid)
+) WITH (user_catalog_table=true);
+
+CREATE TABLE pglogical.sequence_state (
+	seqoid oid NOT NULL PRIMARY KEY,
+	cache_size integer NOT NULL,
+	last_value bigint NOT NULL
+) WITH (user_catalog_table=true);
+
+CREATE TABLE pglogical.depend (
+    classid oid NOT NULL,
+    objid oid NOT NULL,
+    objsubid integer NOT NULL,
+
+    refclassid oid NOT NULL,
+    refobjid oid NOT NULL,
+    refobjsubid integer NOT NULL,
+
+	deptype "char" NOT NULL
+) WITH (user_catalog_table=true);
+
+CREATE VIEW pglogical.TABLES AS
+    WITH set_relations AS (
+        SELECT s.set_name, r.set_reloid
+          FROM pglogical.replication_set_table r,
+               pglogical.replication_set s,
+               pglogical.local_node n
+         WHERE s.set_nodeid = n.node_id
+           AND s.set_id = r.set_id
+    ),
+    user_tables AS (
+        SELECT r.oid, n.nspname, r.relname, r.relreplident
+          FROM pg_catalog.pg_class r,
+               pg_catalog.pg_namespace n
+         WHERE r.relkind = 'r'
+           AND r.relpersistence = 'p'
+           AND n.oid = r.relnamespace
+           AND n.nspname !~ '^pg_'
+           AND n.nspname != 'information_schema'
+           AND n.nspname != 'pglogical'
+    )
+    SELECT r.oid AS relid, n.nspname, r.relname, s.set_name
+      FROM pg_catalog.pg_namespace n,
+           pg_catalog.pg_class r,
+           set_relations s
+     WHERE r.relkind = 'r'
+       AND n.oid = r.relnamespace
+       AND r.oid = s.set_reloid
+     UNION
+    SELECT t.oid AS relid, t.nspname, t.relname, NULL
+      FROM user_tables t
+     WHERE t.oid NOT IN (SELECT set_reloid FROM set_relations);
+
+CREATE FUNCTION pglogical.create_replication_set(set_name name,
+    replicate_insert boolean = true, replicate_update boolean = true,
+    replicate_delete boolean = true, replicate_truncate boolean = true)
+RETURNS oid STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_create_replication_set';
+CREATE FUNCTION pglogical.alter_replication_set(set_name name,
+    replicate_insert boolean DEFAULT NULL, replicate_update boolean DEFAULT NULL,
+    replicate_delete boolean DEFAULT NULL, replicate_truncate boolean DEFAULT NULL)
+RETURNS oid CALLED ON NULL INPUT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_replication_set';
+CREATE FUNCTION pglogical.drop_replication_set(set_name name, ifexists boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_drop_replication_set';
+
+CREATE FUNCTION pglogical.replication_set_add_table(set_name name, relation regclass, synchronize_data boolean DEFAULT false,
+	columns text[] DEFAULT NULL, row_filter text DEFAULT NULL)
+RETURNS boolean CALLED ON NULL INPUT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replication_set_add_table';
+CREATE FUNCTION pglogical.replication_set_add_all_tables(set_name name, schema_names text[], synchronize_data boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replication_set_add_all_tables';
+CREATE FUNCTION pglogical.replication_set_remove_table(set_name name, relation regclass)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replication_set_remove_table';
+
+CREATE FUNCTION pglogical.replication_set_add_sequence(set_name name, relation regclass, synchronize_data boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replication_set_add_sequence';
+CREATE FUNCTION pglogical.replication_set_add_all_sequences(set_name name, schema_names text[], synchronize_data boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replication_set_add_all_sequences';
+CREATE FUNCTION pglogical.replication_set_remove_sequence(set_name name, relation regclass)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replication_set_remove_sequence';
+
+CREATE FUNCTION pglogical.alter_subscription_synchronize(subscription_name name, truncate boolean DEFAULT false)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_synchronize';
+
+CREATE FUNCTION pglogical.alter_subscription_resynchronize_table(subscription_name name, relation regclass,
+	truncate boolean DEFAULT true)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_alter_subscription_resynchronize_table';
+
+CREATE FUNCTION pglogical.synchronize_sequence(relation regclass)
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_synchronize_sequence';
+
+CREATE FUNCTION pglogical.table_data_filtered(reltyp anyelement, relation regclass, repsets text[])
+RETURNS SETOF anyelement CALLED ON NULL INPUT STABLE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_table_data_filtered';
+
+CREATE FUNCTION pglogical.show_repset_table_info(relation regclass, repsets text[], OUT relid oid, OUT nspname text,
+	OUT relname text, OUT att_list text[], OUT has_row_filter boolean)
+RETURNS record STRICT STABLE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_show_repset_table_info';
+
+CREATE FUNCTION pglogical.show_subscription_table(subscription_name name, relation regclass, OUT nspname text, OUT relname text, OUT status text)
+RETURNS record STRICT STABLE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_show_subscription_table';
+
+CREATE TABLE pglogical.queue (
+    queued_at timestamp with time zone NOT NULL,
+    role name NOT NULL,
+    replication_sets text[],
+    message_type "char" NOT NULL,
+    message json NOT NULL
+);
+
+CREATE FUNCTION pglogical.replicate_ddl_command(command text, replication_sets text[] DEFAULT '{ddl_sql}')
+RETURNS boolean STRICT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_replicate_ddl_command';
+
+CREATE OR REPLACE FUNCTION pglogical.queue_truncate()
+RETURNS trigger LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_queue_truncate';
+
+CREATE FUNCTION pglogical.pglogical_node_info(OUT node_id oid, OUT node_name text, OUT sysid text, OUT dbname text, OUT replication_sets text)
+RETURNS record
+STABLE STRICT LANGUAGE c AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION pglogical.pglogical_gen_slot_name(name, name, name)
+RETURNS name
+IMMUTABLE STRICT LANGUAGE c AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION pglogical_version() RETURNS text
+LANGUAGE c AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION pglogical_version_num() RETURNS integer
+LANGUAGE c AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION pglogical_max_proto_version() RETURNS integer
+LANGUAGE c AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION pglogical_min_proto_version() RETURNS integer
+LANGUAGE c AS 'MODULE_PATHNAME';
+
+CREATE FUNCTION
+pglogical.wait_slot_confirm_lsn(slotname name, target pg_lsn)
+RETURNS void LANGUAGE c AS 'pglogical','pglogical_wait_slot_confirm_lsn';
+CREATE FUNCTION pglogical.wait_for_subscription_sync_complete(subscription_name name)
+RETURNS void RETURNS NULL ON NULL INPUT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_wait_for_subscription_sync_complete';
+
+CREATE FUNCTION pglogical.wait_for_table_sync_complete(subscription_name name, relation regclass)
+RETURNS void RETURNS NULL ON NULL INPUT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_wait_for_table_sync_complete';
+
+CREATE FUNCTION pglogical.xact_commit_timestamp_origin("xid" xid, OUT "timestamp" timestamptz, OUT "roident" oid)
+RETURNS record RETURNS NULL ON NULL INPUT VOLATILE LANGUAGE c AS 'MODULE_PATHNAME', 'pglogical_xact_commit_timestamp_origin';
--- a/pglogical.h
+++ b/pglogical.h
@@ -27,8 +27,8 @@
 
 #include "pglogical_compat.h"
 
-#define PGLOGICAL_VERSION "2.4.4"
-#define PGLOGICAL_VERSION_NUM 20404
+#define PGLOGICAL_VERSION "2.4.5"
+#define PGLOGICAL_VERSION_NUM 20405
 
 #define PGLOGICAL_MIN_PROTO_VERSION_NUM 1
 #define PGLOGICAL_MAX_PROTO_VERSION_NUM 1
--- a/pglogical_conflict.c
+++ b/pglogical_conflict.c
@@ -397,6 +397,18 @@ pglogical_tuple_find_conflict(ResultRelI
 		if (RelationGetRelid(idxrel) == replidxoid)
 			continue;
 
+		/*
+		 * If this index may not be complete enough to exhibit
+		 * uniqueness and drive correct query results, move on to other
+		 * indexes.  If no index meets all qualifications and this one
+		 * is ii_ReadyForInserts, one could argue for using this one
+		 * instead of using no index.  We don't offer that.  (The
+		 * server's infer_arbiter_indexes(), which performs a similar
+		 * role, also requires indisvalid.)
+		 */
+		if (!idxrel->rd_index->indisvalid)
+			continue;
+
 		if (build_index_scan_key(index_key, relinfo->ri_RelationDesc,
 								 idxrel, tuple))
 			continue;
--- a/pglogical_output_plugin.c
+++ b/pglogical_output_plugin.c
@@ -489,7 +489,11 @@ pglogical_change_filter(PGLogicalOutputD
 		/* Special case - queue table */
 		if (change->action == REORDER_BUFFER_CHANGE_INSERT)
 		{
+#if PG_VERSION_NUM >= 170000
+			HeapTuple		tup = change->data.tp.newtuple;
+#else
 			HeapTuple		tup = &change->data.tp.newtuple->tuple;
+#endif
 			QueuedMessage  *q;
 			ListCell	   *qlc;
 
@@ -537,12 +541,21 @@ pglogical_change_filter(PGLogicalOutputD
 		PGLogicalRepSet	   *replicated_set;
 		ListCell		   *plc;
 
+#if PG_VERSION_NUM >= 170000
+		if (change->action == REORDER_BUFFER_CHANGE_UPDATE)
+			 tup = change->data.tp.newtuple;
+		else if (change->action == REORDER_BUFFER_CHANGE_DELETE)
+			 tup = change->data.tp.oldtuple;
+		else
+			return false;
+#else
 		if (change->action == REORDER_BUFFER_CHANGE_UPDATE)
 			 tup = &change->data.tp.newtuple->tuple;
 		else if (change->action == REORDER_BUFFER_CHANGE_DELETE)
 			 tup = &change->data.tp.oldtuple->tuple;
 		else
 			return false;
+#endif
 
 		replicated_set = replication_set_from_tuple(tup);
 		foreach (plc, data->replication_sets)
@@ -608,10 +621,15 @@ pglogical_change_filter(PGLogicalOutputD
 		EState		   *estate;
 		ExprContext	   *econtext;
 		TupleDesc		tupdesc = RelationGetDescr(relation);
+#if PG_VERSION_NUM >= 170000
+		HeapTuple		oldtup = change->data.tp.oldtuple;
+		HeapTuple		newtup = change->data.tp.newtuple;
+#else
 		HeapTuple		oldtup = change->data.tp.oldtuple ?
 			&change->data.tp.oldtuple->tuple : NULL;
 		HeapTuple		newtup = change->data.tp.newtuple ?
 			&change->data.tp.newtuple->tuple : NULL;
+#endif
 
 		/* Skip empty changes. */
 		if (!newtup && !oldtup)
@@ -698,20 +716,36 @@ pg_decode_change(LogicalDecodingContext
 	{
 		case REORDER_BUFFER_CHANGE_INSERT:
 			OutputPluginPrepareWrite(ctx, true);
+#if PG_VERSION_NUM >= 170000
+			data->api->write_insert(ctx->out, data, relation,
+									change->data.tp.newtuple,
+									att_list);
+#else
 			data->api->write_insert(ctx->out, data, relation,
 									&change->data.tp.newtuple->tuple,
 									att_list);
+#endif
 			OutputPluginWrite(ctx, true);
 			break;
 		case REORDER_BUFFER_CHANGE_UPDATE:
 			{
+#if PG_VERSION_NUM >= 170000
+				HeapTuple oldtuple = change->data.tp.oldtuple;
+#else
 				HeapTuple oldtuple = change->data.tp.oldtuple ?
 					&change->data.tp.oldtuple->tuple : NULL;
+#endif
 
 				OutputPluginPrepareWrite(ctx, true);
+#if PG_VERSION_NUM >= 170000
+				data->api->write_update(ctx->out, data, relation, oldtuple,
+										change->data.tp.newtuple,
+										att_list);
+#else
 				data->api->write_update(ctx->out, data, relation, oldtuple,
 										&change->data.tp.newtuple->tuple,
 										att_list);
+#endif
 				OutputPluginWrite(ctx, true);
 				break;
 			}
@@ -719,9 +753,15 @@ pg_decode_change(LogicalDecodingContext
 			if (change->data.tp.oldtuple)
 			{
 				OutputPluginPrepareWrite(ctx, true);
+#if PG_VERSION_NUM >= 170000
+				data->api->write_delete(ctx->out, data, relation,
+										change->data.tp.oldtuple,
+										att_list);
+#else
 				data->api->write_delete(ctx->out, data, relation,
 										&change->data.tp.oldtuple->tuple,
 										att_list);
+#endif
 				OutputPluginWrite(ctx, true);
 			}
 			else
--- a/pglogical_sequences.c
+++ b/pglogical_sequences.c
@@ -116,9 +116,6 @@ synchronize_sequences(void)
 		char		   *nspname;
 		char		   *relname;
 		StringInfoData	json;
-#if PG_VERSION_NUM >= 160000
-		TU_UpdateIndexes	updateIndexes = TU_None;
-#endif
 
 		CHECK_FOR_INTERRUPTS();
 
@@ -141,11 +138,7 @@ synchronize_sequences(void)
 									 newseq->cache_size * 2);
 
 		newseq->last_value = last_value + newseq->cache_size;
-#if PG_VERSION_NUM >= 160000
-		simple_heap_update(rel, &tuple->t_self, newtup, &updateIndexes);
-#else
-		simple_heap_update(rel, &tuple->t_self, newtup);
-#endif
+		CatalogTupleUpdate(rel, &tuple->t_self, newtup);
 
 		repsets = get_seq_replication_sets(local_node->node->id,
 										   oldseq->seqoid);
@@ -203,9 +196,6 @@ synchronize_sequence(Oid seqoid)
 	char		   *relname;
 	StringInfoData	json;
 	PGLogicalLocalNode	   *local_node = get_local_node(true, false);
-#if PG_VERSION_NUM >= 160000
-	TU_UpdateIndexes	updateIndexes = TU_None;
-#endif
 
 	/* Check if the oid points to actual sequence. */
 	seqrel = table_open(seqoid, AccessShareLock);
@@ -241,11 +231,7 @@ synchronize_sequence(Oid seqoid)
 	last_value = sequence_get_last_value(seqoid);
 
 	newseq->last_value = last_value + newseq->cache_size;
-#if PG_VERSION_NUM >= 160000
-	simple_heap_update(rel, &tuple->t_self, newtup, &updateIndexes);
-#else
-	simple_heap_update(rel, &tuple->t_self, newtup);
-#endif
+	CatalogTupleUpdate(rel, &tuple->t_self, newtup);
 
 	repsets = get_seq_replication_sets(local_node->node->id, seqoid);
 	repset_names = NIL;
--- a/pglogical_sync.c
+++ b/pglogical_sync.c
@@ -305,9 +305,15 @@ ensure_replication_slot_snapshot(PGconn
 retry:
 	initStringInfo(&query);
 
+#if PG_VERSION_NUM >= 170000
+	appendStringInfo(&query, "CREATE_REPLICATION_SLOT \"%s\" LOGICAL %s%s",
+					 slot_name, "pglogical_output",
+					 use_failover_slot ? " (FAILOVER)" : "");
+#else
 	appendStringInfo(&query, "CREATE_REPLICATION_SLOT \"%s\" LOGICAL %s%s",
 					 slot_name, "pglogical_output",
 					 use_failover_slot ? " FAILOVER" : "");
+#endif
 
 
 	res = PQexec(repl_conn, query.data);
--- /dev/null
+++ b/sql/sequence.sql
@@ -0,0 +1,34 @@
+-- like bt_index_check('pglogical.sequence_state', true)
+CREATE FUNCTION heapallindexed() RETURNS void AS $$
+DECLARE
+	count_seqscan int;
+	count_idxscan int;
+BEGIN
+	count_seqscan := (SELECT count(*) FROM pglogical.sequence_state);
+	SET enable_seqscan = off;
+	count_idxscan := (SELECT count(*) FROM pglogical.sequence_state);
+	RESET enable_seqscan;
+	IF count_seqscan <> count_idxscan THEN
+		RAISE 'seqscan found % rows, but idxscan found % rows',
+			count_seqscan, count_idxscan;
+	END IF;
+END
+$$ LANGUAGE plpgsql;
+
+-- Replicate one sequence.
+CREATE SEQUENCE stress;
+SELECT * FROM pglogical.create_replication_set('stress_seq');
+SELECT * FROM pglogical.replication_set_add_sequence('stress_seq', 'stress');
+SELECT pglogical.synchronize_sequence('stress');
+SELECT heapallindexed();
+
+-- Sync it 400 times in one transaction, to cross a pglogical.sequence_state
+-- page boundary and get a non-HOT update.
+DO $$
+BEGIN
+  FOR i IN 1..400 LOOP
+    PERFORM pglogical.synchronize_sequence('stress');
+  END LOOP;
+END;
+$$;
+SELECT heapallindexed();
--- a/t/011_pglogical_cascade_sub.pl
+++ b/t/011_pglogical_cascade_sub.pl
@@ -119,7 +119,12 @@ $node_b->safe_psql($dbname,
 			"SELECT * FROM pglogical.replication_set_add_table('set_b', 'b2c', false);");
 
 $node_c->safe_psql($dbname, q[create table a2b( x int primary key)]);
-$node_c->safe_psql($dbname, q[create table b2c( x int primary key)]);
+$node_c->safe_psql($dbname, q[create table b2c( x int)]);
+# Add an INVALID index, then add the real PRIMARY KEY.
+$node_c->safe_psql($dbname, q[insert into b2c values (1),(1)]);
+$node_c->psql($dbname, q[create unique index concurrently on b2c(x)]);
+$node_c->safe_psql($dbname, q[delete from b2c]);
+$node_c->safe_psql($dbname, q[alter table b2c add primary key (x)]);
 
 #insert some rows in the a2b table to check that it actually worked
 $node_a->safe_psql($dbname, q[INSERT INTO a2b VALUES (1)]);
--- /dev/null
+++ b/pglogical--2.4.4--2.4.5.sql
@@ -0,0 +1 @@
+-- empty
