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 1wcBNy-0039QE-2F for pgsql-hackers@arkaria.postgresql.org; Wed, 24 Jun 2026 00:22:34 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wcBNx-00EXl8-1a for pgsql-hackers@arkaria.postgresql.org; Wed, 24 Jun 2026 00:22:33 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wcBNx-00EXkz-0X for pgsql-hackers@lists.postgresql.org; Wed, 24 Jun 2026 00:22:33 +0000 Received: from mail-pg1-x52a.google.com ([2607:f8b0:4864:20::52a]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wcBNu-000000020ux-3sd0 for pgsql-hackers@postgresql.org; Wed, 24 Jun 2026 00:22:32 +0000 Received: by mail-pg1-x52a.google.com with SMTP id 41be03b00d2f7-c858014845aso202492a12.1 for ; Tue, 23 Jun 2026 17:22:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1782260549; cv=none; d=google.com; s=arc-20260327; b=arXys3DgoDK7KQGJqiqFm5U+vjdl8esQ3FMVzIQfyP04JqFfGl3goSmypItvuligWs qMGukqxUXn+jLr5PrnHxOHZz7Z2Da51z9jj4Cxpw7iAub1dypqB2RcR7Z9zLKLORivv9 1qKlfF+N/hO21fx0KjBqHQpNjrWbExjDfFzFGXik2JKa5yrfsxDxjiCIyMenO8RYe8dP e8QI+P6KOQfuYg5AbcPL5iOZ1TksgYvyBUdL9L9XIKvilSZ2kkAMjqO/YI8LYPP1VnDE hltE/Ni6onCthm9Ujn8e/YHbZo3EyK7v7gPW1JBufAh+60bAIwYoeaBO/KqWTxLRM9KG 63CA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=rGqFA1CyGHBZkBGIqEvgoMspWip1zpnJhS5bZjjXlhw=; fh=tphf2O8zkzsBsel/WXW2hapTRaWftzLxtB/3hxhDx3o=; b=apNlwT4UU2NawT42hZzYKXkFjujhbKJJ/HpBq29/RdVHd2J4ZLKFN/A/6gwmh+WNXj 5PI9PM8PoUiN8zM5X0eGbpj93md6viGcyPUz6FyTyo3ArCz77mBDlBsDknV/eqwdrdJG tT/miOmG9qJHplYzURlXXbVrHlQSUY/97gUG4g/pVvGDrTFwCIz7Mz0EH2/puLn5Gjt5 S+m28sLiIh748jstSpU1S2cUXxkWPT8JNzoQ9TZ6vcSpB76BKBVDma+tCqJT1GYQn+2U u6Wv+oqmssdlMfwjm7Uk28NVZMX+F5250OjZq9PdaqRpIB7nXiVzCSOvSyOUPwNQQ8Sw 3z0Q==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1782260549; x=1782865349; darn=postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=rGqFA1CyGHBZkBGIqEvgoMspWip1zpnJhS5bZjjXlhw=; b=nmnPW4+Qq8CnZrKARmAIEJr6xEKx4AMvGOZzadoQwEtEjrkmw8onbmJ4pvy3a/o0Vu JXfIralQsyRQ31te4/HZAbk1445DFRj6ZJ8aUvY1rExjNAs0RObsYhXREJevkQLBwQEs L3jtLKM2HG3Jr+hmySJ5rI2hfmDPtcLaWeHoeQIiw5xAuheSkjPbGLsWWsn3uN/J5Rok dh0r5bo2tNNdX3n+RZ6YO25n+NzmSd+ZJynff15oruwIZMUthFrKdiel8HnPgShSMCYv aPsDJKYnY96iDS91mzCTDUgwHWkXg5OHkCqllAMU0nfkfBK94CFWskPkHC6McgO62mQ0 54qQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1782260549; x=1782865349; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=rGqFA1CyGHBZkBGIqEvgoMspWip1zpnJhS5bZjjXlhw=; b=MNNx8ICpaC4LCTsb8AlxUrKZ3TDdS8UKKgsoKNPeaADbZOEfKKJPTW3ytRLdE/yWbF C9HdFB9a/jiEOIaOrN93Do8uPBDT1UMFFXcinsmNSmHbMHZxJDSD9MqGw8+AS0PBy/ls Sdq+H4GYeJJhoBHazYyQ7NM9ynQJWoLwFYCUMyiHAS7Nv7Yc46KCFZz1r28VpYi5Pj/X eOQ/PamMMkF5SVRE9hjIPpssBUzrz84A2oOYHIxeOxMrH2xYu2RqRwQaaTgzE7whkMi4 1gZA+Gl9vhIaoav1WPciWp6rOalu+QBzCrhsX24gUYboxhuojmDNqBxHI8r2zcLNLzSJ YqTA== X-Forwarded-Encrypted: i=1; AFNElJ9yAPKKmH8/EALf5rbM5jT/L81DUJ5aInmn4VGWMibJbdnJGB3L27XHEJkr7VEsjynhT3NMl3+Cf1I0YzkN@postgresql.org X-Gm-Message-State: AOJu0Yx9q7/+FS+SWIEkueyN9CYqqg5cnJgn5qg/U0sQRt7NWF2noL6I ldBa9vLNREzKlzoVcATs2uArngwDXPM0QUPcjrO2YdurJUb7gzDdSM+4Qs809VnOQ6sj6SAUx7h egfPZIJygERQQERxVIdq+kiXsymz2HE0= X-Gm-Gg: AfdE7cmANSwQc2FQInSRQDwaMmxX423/jjkayHqYdPLoG2HazGDHDFE0hyUfRiDEIpx upVPWrX/gqXPta0JKHlhelz69E9xouYxwzHqJKnd7pO3Yzz5yiwSv+ff38Txk0EgFFSbx+hMidA qwzc/rxeGnQMW6r4v3vYyfiGON/Ya5/MVdm+1yNkaPQwiB2C604IrtKaiK1YTxgJTrwaL40YX03 yvICxKIJ+B7OAtbmw0BZDrJO0o6jVJruDGVzUvaJMOTT4d+Z+3tfg38DNJ34Kxbrt0Ch8SA0US7 KMlAxOCTtvVelsR43HTrm1RAoqU9Ig== X-Received: by 2002:a05:6300:4086:b0:3b5:68ae:1ac8 with SMTP id adf61e73a8af0-3bd10b6816emr6232926637.34.1782260548915; Tue, 23 Jun 2026 17:22:28 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Masahiko Sawada Date: Tue, 23 Jun 2026 17:21:51 -0700 X-Gm-Features: AVVi8Cfwc6cEf4Ai7KHf7ybigWeu9h8_XF0IAxuAMp0jlKzDVy6gWninnx_HfZQ Message-ID: Subject: Re: Add a hook for handling logical decoding messages on subscribers. To: Amit Kapila Cc: Bharath Rupireddy , PostgreSQL-development Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, Jun 23, 2026 at 11:01=E2=80=AFAM Masahiko Sawada wrote: > > On Tue, Jun 23, 2026 at 1:52=E2=80=AFAM Amit Kapila wrote: > > > > On Tue, Jun 23, 2026 at 4:09=E2=80=AFAM Bharath Rupireddy > > wrote: > > > > > > On Fri, Jun 19, 2026 at 3:34=E2=80=AFPM Masahiko Sawada wrote: > > > > > > > > Hi all, > > > > > > > > Commit ac4645c015 allows pgoutput to send logical decoding messages= , > > > > but it's limited to applications that use the pgoutput plugin -- th= e > > > > built-in logical replication doesn't use it. I'd like to propose > > > > introducing a hook to the logical replication message handling so t= hat > > > > extensions can plug in their own handling routine. This feature can= be > > > > used for extensions to implement DDL replication, function > > > > replication, or trigger user-specific routines on the subscriber si= de. > > > > > > Thanks for working on this! > > > > > > > I've attached the PoC patch; it adds a hook function, and adds a ne= w > > > > 'message' subscription option that allows the user to request the > > > > publisher to send logical decoding messages. Therefore, users need = to > > > > enable the 'message' option and set up the hook function at server > > > > startup in order to receive the messages and trigger the hook > > > > function. > > > > > > I understand the intent of the proposal, but I'd like to get the > > > bigger picture first. > > > > > > Do we have any external modules that actually implement DDL > > > replication (or any of the listed use-cases) with a similar hook? Or > > > any existing discussion? I could be missing something because I > > > haven't looked at all the DDL replication related threads. > > > > > > Another thing I'm curious about - why a hook? Is the plan to implemen= t > > > DDL replication as an external module rather than in core? If DDL > > > replication eventually gets into core, I'd expect it to be apply-side > > > logic executing the decoded DDL messages directly, not something goin= g > > > through a hook. > > > > > > > I think it is important to have some example extension implementation > > to see how the hook could be utilized. One more use of such a hook > > could be to use for audit of DDLs replayed on subscribers. > > Right. I'm implementing a basic DDL replication solution using this > hook as a sample implementation. FYI, I've implemented a test extension, pg_logical_ddl[1], which can be used with the proposed patch. The extension uses both hooks ProcessUtility_hook to capture DDL events and LogicalRepMessageHandle_hook to apply the DDL message. It sends a JSON blob containing the DDL command, command tag, user name, and search_path. The implementation is straightforward and I find that the proposed hook is useful to implement DDL replication. One thing that would simplify the implementation, and that I'd like to have, is an easy way to capture the OID of the affected relation (or its object address) without event triggers. That information is useful for figuring out which object a DDL affects: for instance, to filter DDLs by table, or to map the command to the right object on the subscriber. If we use an event trigger to capture DDL events, it would be easy to get the object address, but it's not easy for extensions like pg_logical_ddl that don't rely on event triggers. The OID of the affected table can be resolved by the name and search_path but it's not a reliable solution as its schema can be renamed without taking a heavy lock on the table. If they have to use event triggers, it could be cumbersome to manage additional objects (e.g., users can drop them etc.). It would be good to have a mechanism to easily capture the information that is collected by event triggers today without event triggers. FYI I proposed a similar idea before in the DDL replication thread[2] since the same is true for the in-core DDL replication and I have a PoC patch for that. Also, since this is an extension, it cannot necessarily work well with PUBLICATION; it doesn't respect the table filtering setting and some options like publish_via_partition_root. In that sense, working with the existing publication feature is the advantage of the in-core DDL replication. Regards, [1] https://github.com/MasahikoSawada/pg_logical_ddl [2] https://www.postgresql.org/message-id/CAD21AoCEVO%2BzpLmQqKwZbJ5%2Brvqs= J1e0wnTNBH437p8tDw7B%3Dg%40mail.gmail.com -- Masahiko Sawada Amazon Web Services: https://aws.amazon.com