Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w2Rky-000IYh-2y for pgsql-bugs@arkaria.postgresql.org; Tue, 17 Mar 2026 10:34:37 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w2Rkx-000L9a-2t for pgsql-bugs@arkaria.postgresql.org; Tue, 17 Mar 2026 10:34:35 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w1m6Z-004d10-2w for pgsql-bugs@lists.postgresql.org; Sun, 15 Mar 2026 14:06:08 +0000 Received: from mahout.postgresql.org ([2001:4800:3e1:1::227]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1w1m6W-00000000FgG-41Rq for pgsql-bugs@lists.postgresql.org; Sun, 15 Mar 2026 14:06:07 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=postgresql.org; s=20171124; h=Message-ID:Date:Reply-To:Cc:From:To:Subject: Content-Transfer-Encoding:MIME-Version:Content-Type:Sender:Content-ID: Content-Description:In-Reply-To:References; bh=LXwMfigkD9ZYxqV2KZoDeZ7xTufL+1gspRtJuKCWZZs=; b=tN0eZ8nfrWHBUqDMEHGl9FilZx OthNjI2JFRkfYGecDCOYkQ0LMalK98rq4UUQMplRFmHg2nMG3u1tFnVpTvyRUkVTzWVIvKGVtSp4Y byh7rfgjX+SJkPsfS/eVE1UOiT3y/HW2Rs3G70bEhYP5P1/rTFcxnGXFTUa7N/F/kZJ800udqYvCq b54sutKsLGlVLQbpowrUAfszpkIMTX7tgpfSQ5FZUaouG2erq/Skj/PEp+lzJzdVcwB89TSSkD4Qh Cx3yLA9OfHVeCx16CN2e+0+aHUFfqq4SSX8ZExYjrHc3nOloxhF3tVbNM2EEpXq4k6QQk6AEucoN6 nfAeXhGg==; Received: from wrigleys.postgresql.org ([2a02:16a8:dc51::60]) by mahout.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1w1m6V-000qxL-32 for pgsql-bugs@lists.postgresql.org; Sun, 15 Mar 2026 14:06:04 +0000 Received: from localhost ([127.0.0.1] helo=wrigleys.postgresql.org) by wrigleys.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w1m6V-001SFE-1x for pgsql-bugs@lists.postgresql.org; Sun, 15 Mar 2026 14:06:03 +0000 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: BUG #19434: adding WHERE to a publication can cause UPDATEs and DELETEs to fail on the source table To: pgsql-bugs@lists.postgresql.org From: PG Bug reporting form Cc: tim@gotab.io Reply-To: tim@gotab.io, pgsql-bugs@lists.postgresql.org Date: Sun, 15 Mar 2026 14:05:49 +0000 Message-ID: <19434-297bf2cbd8d2931a@postgresql.org> X-Auto-Response-Suppress: All Auto-Submitted: auto-generated List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk The following bug has been logged on the website: Bug reference: 19434 Logged by: Tim McLaughlin Email address: tim@gotab.io PostgreSQL version: 18.3 Operating system: all Description: =20 Adding a WHERE clause to a publication can cause UPDATEs and DELETEs to fail on the source table if the filter columns aren't part of the replica identity. While this is a documented behavior, I do think this is a bug and I'll explain why. The core problem is that REPLICA IDENTITY controls two unrelated things: which columns identify a row on the subscriber, and which old column values get written to WAL. Publication row filters need the second capability but have nothing to do with the first. These two purposes should be separated. The result can a bad failure mode (which I experienced catastrophically): a DBA adds a WHERE clause to a publication =E2=80=94 a change that should onl= y affect what gets replicated =E2=80=94 and it breaks writes on the publisher. There= 's no error at DDL time. The failure only appears when the application hits an UPDATE or DELETE, potentially taking down production writes as it did in my case. The current workarounds both have unnecessary costs: - REPLICA IDENTITY FULL writes every column's old value to WAL for every change, increasing WAL volume far beyond what the filter actually needs. - Creating a unique index that includes the filter columns adds storage and maintenance overhead for an index that serves no query purpose. I'd propose that when a publication has a WHERE clause, PostgreSQL automatically includes the referenced columns' old values in WAL without requiring a change to REPLICA IDENTITY. The additional columns being written could be tracked in a new column on pg_publication_rel, making the behavior transparent and inspectable. This would preserve the existing REPLICA IDENTITY for their intended (and semantically sensible) purpose while eliminating a non-obvious way to break a production publisher.