CREATE_SUBSCRIPTION(7pg18)

๐Ÿ“ฆ version 18.6, in opensuse-leap 16.0

๐Ÿ’– CREATE_SUBSCRIPTION ๐Ÿ’–

okay bestie, welcome to the <strong>CREATE SUBSCRIPTION(7)</strong> page โ€” PostgreSQL 18.6 Documentation, but make it cute. this is the one where you tell Postgres "hey, go follow that other database's posts, no cap" ๐Ÿซถ


โœจ NAME โœจ

CREATE_SUBSCRIPTION โ€” define a new subscription ๐Ÿ’…


๐ŸŒธ SYNOPSIS ๐ŸŒธ

CREATE SUBSCRIPTION subscription_name
    CONNECTION 'conninfo'
    PUBLICATION publication_name [, ...]
    [ WITH ( subscription_parameter [= value] [, ... ] ) ]

look at her. so simple. so powerful. the commas are doing SO much work here bestie. ๐Ÿฆ‹


๐ŸŽ€ DESCRIPTION ๐ŸŽ€

okay so CREATE SUBSCRIPTION adds a brand new logical-replication subscription. that's the whole vibe. โœจ

the user who creates a subscription becomes the owner of the subscription. like, it's yours now. main character energy. ๐Ÿ‘‘

and the subscription name? it must be distinct from the name of any existing subscription in the current database. no twinning allowed, sorry, there can only be one ๐Ÿ’€


a subscription basically represents a replication connection to the publisher. so bestie, it's not just chillin' in your local catalogs โ€” nope. in addition to adding definitions in the local catalogs, this command normally creates a replication slot on the publisher. it's giving "commitment." ๐Ÿ”ฅ

then a logical replication worker gets started to replicate data for the new subscription โ€” and the timing? at the commit of the transaction where this command is run. โฐ

โš ๏ธ caveat, queen: the worker does <strong>not</strong> start if the subscription is initially disabled. so if you turn it off from the jump, nothing runs yet. don't come for me, that's just how it is ๐Ÿ™ˆ

๐Ÿซถ the prerequisites (yes, there are some, sorry) ๐Ÿซถ

to be able to create a subscription, you must have:

  • the privileges of the pg_create_subscription role โœจ
  • <strong>and</strong> CREATE privileges on the current database ๐Ÿ’…

both. not one. both. periodt. ๐Ÿ‘‘


๐ŸŒˆ where to learn more ๐ŸŒˆ

additional info about subscriptions and logical replication as a whole lives at Section 29.2 and Chapter 29. go read those, iykyk ๐Ÿ“š

โ€ฆand that's just part 1 bestie, we're not done yet โ€” keep scrolling, there's more coming ๐Ÿ’œ

โœจ PARAMETERS โœจ

okay bestie, deep breath โ€” this is the part where all the lil knobs and dials live. turn them however you want, no judgement ๐Ÿ’…

  • subscription_name โ€” the name of your new subscription. that's it, that's the whole thing. pick something cute, you're gonna be saying it a lot ๐ŸŽ€
  • CONNECTION 'conninfo' โ€” the libpq connection string that tells Postgres how to actually reach the publisher database. all the deets for building it are in Section 32.1.1 ๐Ÿ‘‘
  • PUBLICATION publication_name [, ...] โ€” the names of the publications on the publisher that you're subscribing to. yes you can list more than one. comma-separated. go off โœจ
  • WITH ( subscription_parameter [= value] [, ... ] ) โ€” this clause is where you drop your optional parameters. optional, but honestly? iconic ๐Ÿ’–

so the next four parameters control what goes down while the subscription is being created ๐ŸŒฑ

  • connect (boolean) โ€” says whether the CREATE SUBSCRIPTION command should connect to the publisher at all. default is true. setting it to false will force the values of create_slot, enabled and copy_data to false. (and no, you cannot combine connect set to false with create_slot, enabled, or copy_data set to true โ€” that combo is just not happening, bestie ๐Ÿ™…)

and listen, since no connection gets made when this is false, no tables are subscribed. to actually initiate replication you've gotta manually create the replication slot, enable the failover if required, enable the subscription, and refresh the subscription. examples are waiting for you in Section 29.2.3 ๐Ÿ“–

  • create_slot (boolean) โ€” says whether the command should create the replication slot on the publisher. default is true.

if you set it to false, you are responsible for creating the publisher's slot some other way. Section 29.2.3 has examples, go look ๐Ÿ‘€

  • enabled (boolean) โ€” says whether the subscription should be actively replicating, or whether it should just be set up but not started yet. default is true.
  • slot_name (string) โ€” the name of the publisher's replication slot to use. by default it just uses the name of the subscription as the slot name. easy โœจ

setting slot_name to NONE means there will be no replication slot associated with the subscription. such subscriptions must also have both enabled and create_slot set to false. use this when you're gonna create the replication slot later, manually. Section 29.2.3 for examples.

and here's a heads-up that matters: when you set slot_name to a valid name and create_slot to false, the failover property value of the named slot may differ from the counterpart failover parameter you specified in the subscription. always make sure the slot property failover matches the counterpart parameter of the subscription, and vice versa. otherwise the slot on the publisher may behave differently from what these subscription options say โ€” like, the slot on the publisher could either be synced to the standbys even when the subscription's failover option is disabled, or it could be disabled for sync even when the subscription's failover option is enabled. messy. don't do it ๐Ÿ˜ญ


and these ones control the subscription's replication behavior after it's been created ๐Ÿฆ‹

  • binary (boolean) โ€” says whether the subscription will request the publisher to send the data in binary format (as opposed to text). default is false. any initial table synchronization copy (see copy_data) also uses the same format. binary format can be faster than text, but it's less portable across machine architectures and PostgreSQL versions. it's also super data type specific โ€” for example, it will not allow copying from a smallint column to an integer column, even though that would work totally fine in text format. and even when this option is enabled, only data types that have binary send and receive functions will be transferred in binary. also note: the initial synchronization requires all data types to have binary send and receive functions, otherwise the synchronization will fail (peep CREATE TYPE (CREATE_TYPE(7)) for more about send/receive functions).

when you're doing cross-version replication, it could be that the publisher has a binary send function for some data type, but the subscriber is missing a binary receive function for that type. in that case, data transfer will fail, and the binary option just can't be used. periodt ๐Ÿ’€

oh and โ€” if the publisher is a PostgreSQL version before 16, then any initial table synchronization will use text format even if binary = true. no cap.

  • copy_data (boolean) โ€” says whether to copy pre-existing data in the publications you're subscribing to when replication starts. default is true.

if the publications contain WHERE clauses, it will affect what data gets copied. refer to the Notes for details.

and also see Notes for details of how copy_data = true can interact with the origin parameter ๐Ÿ‘€

  • streaming (enum) โ€” says whether to enable streaming of in-progress transactions for this subscription. the default value is parallel, meaning incoming changes are directly applied via one of the parallel apply workers, if available. if no parallel apply worker is free to handle streaming transactions, then the changes get written to temporary files and applied after the transaction is committed. note that if an error happens in a parallel apply worker, the finish LSN of the remote transaction might not be reported in the server log ๐Ÿ™ˆ
โš ๏ธ Caution: there's a risk of deadlock when the schemas of the publisher and subscriber differ, although such cases are rare. the apply worker is equipped to retry these transactions automatically. so like, it's handled, but still.

if set to on, the incoming changes are written to temporary files and then applied only after the transaction is committed on the publisher and received by the subscriber.

if set to off, all transactions are fully decoded on the publisher and only then sent to the subscriber as a whole.

  • synchronous_commit (enum) โ€” the value of this parameter overrides the synchronous_commit setting within this subscription's apply worker processes. the default value is off.

it is safe to use off for logical replication: if the subscriber loses transactions because of missing synchronization, the data will be sent again from the publisher. ๐Ÿ’–

a different setting might be appropriate when doing synchronous logical replication. the logical replication workers report the positions of writes and flushes to the publisher, and when using synchronous replication, the publisher will wait for the actual flush. this means that setting synchronous_commit for the subscriber to off when the subscription is used for synchronous replication might increase the latency for COMMIT on the publisher. in this scenario, it can be advantageous to set synchronous_commit to local or higher. iykyk ๐Ÿงš

  • two_phase (boolean) โ€” says whether two-phase commit is enabled for this subscription. default is false.

when two-phase commit is enabled, prepared transactions are sent to the subscriber at the time of PREPARE TRANSACTION, and are processed as two-phase transactions on the subscriber too. otherwise, prepared transactions are sent to the subscriber only when committed, and are then processed immediately by the subscriber.

the implementation of two-phase commit requires that replication has successfully finished the initial table synchronization phase. so even when two_phase is enabled for a subscription, the internal two-phase state remains temporarily โ€œpendingโ€ until the initialization phase completes. check column subtwophasestate of pg_subscription to know the actual two-phase state ๐Ÿ”

  • disable_on_error (boolean) โ€” says whether the subscription should be automatically disabled if any errors are detected by subscription workers during data replication from the publisher. default is false.
  • password_required (boolean) โ€” if set to true, connections to the publisher made as a result of this subscription must use password authentication, and the password must be specified as a part of the connection string. this setting is ignored when the subscription is owned by a superuser. default is true. only superusers can set this value to false. ๐Ÿ”
  • run_as_owner (boolean) โ€” if true, all replication actions are performed as the subscription owner. if false, replication workers will perform actions on each table as the owner of that table. the latter configuration is generally much more secure; for details, see Section 29.11. default is false. ๐Ÿ‘‘
  • origin (string) โ€” says whether the subscription will request the publisher to only send changes that don't have an origin, or to send changes regardless of origin. setting origin to none means the subscription will request the publisher to only send changes that don't have an origin. setting origin to any means the publisher sends changes regardless of their origin. default is any.

see Notes for details of how copy_data = true can interact with the origin parameter ๐Ÿ‘€

  • failover (boolean) โ€” says whether the replication slots associated with the subscription are enabled to be synced to the standbys, so that logical replication can be resumed from the new primary after failover. default is false. ๐ŸŒˆ

oh and one lil shortcut before you go: when you're specifying a parameter of type boolean, the = value part can be omitted, which is equivalent to specifying TRUE. so copy_data alone hits the same as copy_data = true. slay โœจ

๐Ÿ“ NOTES ๐Ÿ“

Okay bestie, this is the โœจfine printโœจ section and honestly it's giving "read me or perish" energy, so let's go ๐Ÿ’…

Wanna know how to set up access control between the subscription and the publication instance? Peep Section 29.11, it's all there ๐Ÿซถ

When you're creating a replication slot โ€” and btw that's the default behavior, no cap โ€” CREATE SUBSCRIPTION cannot be run inside a transaction block. Periodt. ๐Ÿ™…โ€โ™€๏ธ

Now here's a spicy one ๐Ÿ”ฅ If you're creating a subscription that connects to the same database cluster (like, replicating between databases in the same cluster, or replicating within the same database), it will only succeed if the replication slot is not created as part of the same command. Otherwise your CREATE SUBSCRIPTION call will literally just hang. ๐Ÿ’€ To make it work, create the replication slot separately โ€” using the function pg_create_logical_replication_slot with the plugin name pgoutput โ€” and then create the subscription using the parameter create_slot = false. Section 29.2.3 has examples if you need them. This is an implementation restriction that might get lifted in a future release, so likeโ€ฆ watch this space ๐Ÿ‘€


If any table in the publication has a WHERE clause, rows where the expression evaluates to false or NULL will not be published. Simple as that.

If your subscription has several publications where the same table got published with different WHERE clauses, a row will be published if any of the expressions (referring to that publish operation) are satisfied. ๐Ÿค

And in the case of different WHERE clauses โ€” if one of the publications has no WHERE clause (again, referring to that publish operation), or the publication is declared as FOR ALL TABLES or FOR TABLES IN SCHEMA, then rows are always published regardless of what the other expressions say. That one publication is the main character and it overrides everything ๐Ÿ‘‘

If the subscriber is a PostgreSQL version before 15, then any row filtering is ignored during the initial data synchronization phase. In that case, you might wanna consider deleting any initially copied data that would be incompatible with subsequent filtering. Because initial data synchronization does not take into account the publication publish parameter when copying existing table data, some rows may get copied that would not be replicated using DML. Section 29.2.2 has examples ๐Ÿ“

Subscriptions having several publications in which the same table has been published with different column lists are not supported. Not a vibe, just facts. ๐Ÿ˜ญ

We allow non-existent publications to be specified so users can add those later. Which means pg_subscription can have non-existent publications. Iconic, honestly.

Now, when you use a subscription parameter combo of copy_data = true and origin = NONE, the initial sync table data gets copied directly from the publisher โ€” meaning knowledge of the true origin of that data is justโ€ฆ not possible. ๐Ÿ™ˆ If the publisher also has subscriptions, then the copied table data might have originated from further upstream. This scenario gets detected and a WARNING is logged to the user, but heads up: that warning is only an indication of a potential problem. It is the user's responsibility to make the necessary checks to ensure the copied data origins are really as wanted or not. No one else is gonna do it for you, bestie ๐Ÿ’œ

Wanna find which tables might potentially include non-local origins (due to other subscriptions created on the publisher)? Try this SQL query:

# substitute <pub-names> below with your publication name(s) to be queried
SELECT DISTINCT PT.schemaname, PT.tablename
FROM pg_publication_tables PT
     JOIN pg_class C ON (C.relname = PT.tablename)
     JOIN pg_namespace N ON (N.nspname = PT.schemaname),
     pg_subscription_rel PS
WHERE C.relnamespace = N.oid AND
      (PS.srrelid = C.oid OR
      C.oid IN (SELECT relid FROM pg_partition_ancestors(PS.srrelid) UNION
                SELECT relid FROM pg_partition_tree(PS.srrelid))) AND
      PT.pubname IN (<pub-names>);

๐ŸŒˆ EXAMPLES ๐ŸŒˆ

Let's see it in action, shall we? โœจ

Example one โ€” create a subscription to a remote server that replicates tables in the publications mypublication and insert_only, and starts replicating immediately on commit:

CREATE SUBSCRIPTION mysub
         CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
        PUBLICATION mypublication, insert_only;

Example two โ€” create a subscription to a remote server that replicates tables in the insert_only publication and does not start replicating until enabled at a later time:

CREATE SUBSCRIPTION mysub
         CONNECTION 'host=192.168.1.50 port=5432 user=foo dbname=foodb'
        PUBLICATION insert_only
               WITH (enabled = false);

See? Easy. Slay. ๐Ÿ’…


๐Ÿ’ซ COMPATIBILITY ๐Ÿ’ซ

CREATE SUBSCRIPTION is a PostgreSQL extension. That's it, that's the whole section. It's not standard SQL, it's our special little thing ๐ŸŽ€


๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

Go read these next, bestie, they're literally the friend group of this command:


And that's a wrap on the whole page, fr fr! ๐Ÿฆ‹ This one came from PostgreSQL 18.6, dated 2026 โ€” so if you're reading this, you're running with the crew that ships CREATE_SUBSCRIPTION(7). Go forth and replicate responsibly, you absolute icon ๐Ÿ‘‘๐Ÿ’–

๐Ÿ“ฆ where this page comes from