diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 8a8d3b4481..c50e86c6a1 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -61,6 +61,8 @@ typedef struct ConnCacheEntry
 	bool		have_prep_stmt; /* have we prepared any stmts in this xact? */
 	bool		have_error;		/* have any subxacts aborted in this xact? */
 	bool		changing_xact_state;	/* xact state change in process */
+	bool		inherit_read_only;	/* do we open xacts in read-only mode? */
+	bool		inherit_deferrable;	/* do we open xacts in dederrable mode? */
 	bool		parallel_commit;	/* do we commit (sub)xacts in parallel? */
 	bool		parallel_abort; /* do we abort (sub)xacts in parallel? */
 	bool		invalidated;	/* true if reconnect is pending */
@@ -391,6 +393,9 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user)
 	 *
 	 * By default, all the connections to any foreign servers are kept open.
 	 *
+	 * Also determine whether to open transactions in read-only and/or
+	 * deferrable modes on the remote server, which is disabled by default.
+	 *
 	 * Also determine whether to commit/abort (sub)transactions opened on the
 	 * remote server in parallel at (sub)transaction end, which is disabled by
 	 * default.
@@ -400,6 +405,8 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user)
 	 * re-made later.
 	 */
 	entry->keep_connections = true;
+	entry->inherit_read_only = false;
+	entry->inherit_deferrable = false;
 	entry->parallel_commit = false;
 	entry->parallel_abort = false;
 	foreach(lc, server->options)
@@ -408,6 +415,10 @@ make_new_connection(ConnCacheEntry *entry, UserMapping *user)
 
 		if (strcmp(def->defname, "keep_connections") == 0)
 			entry->keep_connections = defGetBoolean(def);
+		else if (strcmp(def->defname, "inherit_read_only") == 0)
+			entry->inherit_read_only = defGetBoolean(def);
+		else if (strcmp(def->defname, "inherit_deferrable") == 0)
+			entry->inherit_deferrable = defGetBoolean(def);
 		else if (strcmp(def->defname, "parallel_commit") == 0)
 			entry->parallel_commit = defGetBoolean(def);
 		else if (strcmp(def->defname, "parallel_abort") == 0)
@@ -831,17 +842,26 @@ begin_remote_xact(ConnCacheEntry *entry)
 	/* Start main transaction if we haven't yet */
 	if (entry->xact_depth <= 0)
 	{
-		const char *sql;
+		StringInfoData sql;
 
 		elog(DEBUG3, "starting remote transaction on connection %p",
 			 entry->conn);
 
+		initStringInfo(&sql);
+		appendStringInfoString(&sql, "START TRANSACTION ISOLATION LEVEL ");
 		if (IsolationIsSerializable())
-			sql = "START TRANSACTION ISOLATION LEVEL SERIALIZABLE";
+			appendStringInfoString(&sql, "SERIALIZABLE");
 		else
-			sql = "START TRANSACTION ISOLATION LEVEL REPEATABLE READ";
+			appendStringInfoString(&sql, "REPEATABLE READ");
+
+		/* Append access/deferrable modes if needed */
+		if (entry->inherit_read_only && XactReadOnly)
+			appendStringInfoString(&sql, " READ ONLY");
+		if (entry->inherit_deferrable && XactDeferrable)
+			appendStringInfoString(&sql, " DEFERRABLE");
+
 		entry->changing_xact_state = true;
-		do_sql_command(entry->conn, sql);
+		do_sql_command(entry->conn, sql.data);
 		entry->xact_depth = 1;
 		entry->changing_xact_state = false;
 	}
diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c
index d0766f007d..e411150318 100644
--- a/contrib/postgres_fdw/option.c
+++ b/contrib/postgres_fdw/option.c
@@ -123,6 +123,8 @@ postgres_fdw_validator(PG_FUNCTION_ARGS)
 			strcmp(def->defname, "updatable") == 0 ||
 			strcmp(def->defname, "truncatable") == 0 ||
 			strcmp(def->defname, "async_capable") == 0 ||
+			strcmp(def->defname, "inherit_read_only") == 0 ||
+			strcmp(def->defname, "inherit_deferrable") == 0 ||
 			strcmp(def->defname, "parallel_commit") == 0 ||
 			strcmp(def->defname, "parallel_abort") == 0 ||
 			strcmp(def->defname, "keep_connections") == 0)
@@ -270,6 +272,8 @@ InitPgFdwOptions(void)
 		/* async_capable is available on both server and table */
 		{"async_capable", ForeignServerRelationId, false},
 		{"async_capable", ForeignTableRelationId, false},
+		{"inherit_read_only", ForeignServerRelationId, false},
+		{"inherit_deferrable", ForeignServerRelationId, false},
 		{"parallel_commit", ForeignServerRelationId, false},
 		{"parallel_abort", ForeignServerRelationId, false},
 		{"keep_connections", ForeignServerRelationId, false},
diff --git a/doc/src/sgml/postgres-fdw.sgml b/doc/src/sgml/postgres-fdw.sgml
index d2998c13d5..337a2d6252 100644
--- a/doc/src/sgml/postgres-fdw.sgml
+++ b/doc/src/sgml/postgres-fdw.sgml
@@ -524,6 +524,32 @@ OPTIONS (ADD password_required 'false');
 
    <variablelist>
 
+    <varlistentry>
+     <term><literal>inherit_read_only</literal> (<type>boolean</type>)</term>
+     <listitem>
+      <para>
+       This option controls whether <filename>postgres_fdw</filename> opens
+       remote transactions in read-only mode on a foreign server in a local
+       transaction if the local transaction is read-only.
+       This option can only be specified for foreign servers, not per-table.
+       The default is <literal>false</literal>.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><literal>inherit_deferrable</literal> (<type>boolean</type>)</term>
+     <listitem>
+      <para>
+       This option controls whether <filename>postgres_fdw</filename> opens
+       remote transactions in deferrable mode on a foreign server in a local
+       transaction if the local transaction is deferrable.
+       This option can only be specified for foreign servers, not per-table.
+       The default is <literal>false</literal>.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><literal>parallel_commit</literal> (<type>boolean</type>)</term>
      <listitem>
