diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index fa9ee716067..fdadfb06ef9 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -7121,6 +7121,33 @@ RESET enable_material;
 DROP FOREIGN TABLE remt2;
 DROP TABLE loct1;
 DROP TABLE loct2;
+-- Test non-pushed-down UPDATE/DELETE on partitioned/inherited foreign tables
+CREATE TABLE plt (a int, b int) PARTITION BY LIST(a);
+CREATE TABLE plt_p1 PARTITION OF plt FOR VALUES IN (1);
+CREATE TABLE plt_p2 PARTITION OF plt FOR VALUES IN (2);
+CREATE FOREIGN TABLE inh_ft (a int, b int) SERVER loopback OPTIONS (table_name 'plt', inherited 'true');
+INSERT INTO inh_ft VALUES (1, 1), (2, 2);
+SELECT tableoid::regclass, ctid, * FROM inh_ft;
+ tableoid | ctid  | a | b 
+----------+-------+---+---
+ inh_ft   | (0,1) | 1 | 1
+ inh_ft   | (0,1) | 2 | 2
+(2 rows)
+
+-- Use random() so that UPDATE/DELETE is not pushed down to the remote
+EXPLAIN (VERBOSE, COSTS OFF)
+UPDATE inh_ft SET b = (CASE WHEN random() <= 1 THEN 10 ELSE 100 END) WHERE a = 1; -- should fail
+ERROR:  cannot update foreign table "inh_ft"
+UPDATE inh_ft SET b = (CASE WHEN random() <= 1 THEN 10 ELSE 100 END) WHERE a = 1; -- should fail
+ERROR:  cannot update foreign table "inh_ft"
+EXPLAIN (VERBOSE, COSTS OFF)
+DELETE FROM inh_ft WHERE a = (CASE WHEN random() <= 1 THEN 1 ELSE 10 END); -- should fail
+ERROR:  cannot delete from foreign table "inh_ft"
+DELETE FROM inh_ft WHERE a = (CASE WHEN random() <= 1 THEN 1 ELSE 10 END); -- should fail
+ERROR:  cannot delete from foreign table "inh_ft"
+-- Cleanup
+DROP FOREIGN TABLE inh_ft;
+DROP TABLE plt;
 -- ===================================================================
 -- test check constraints
 -- ===================================================================
diff --git a/contrib/postgres_fdw/option.c b/contrib/postgres_fdw/option.c
index c2f936640bc..85b40b948c3 100644
--- a/contrib/postgres_fdw/option.c
+++ b/contrib/postgres_fdw/option.c
@@ -119,7 +119,8 @@ postgres_fdw_validator(PG_FUNCTION_ARGS)
 		/*
 		 * Validate option value, when we can do so without any context.
 		 */
-		if (strcmp(def->defname, "use_remote_estimate") == 0 ||
+		if (strcmp(def->defname, "inherited") == 0 ||
+			strcmp(def->defname, "use_remote_estimate") == 0 ||
 			strcmp(def->defname, "updatable") == 0 ||
 			strcmp(def->defname, "truncatable") == 0 ||
 			strcmp(def->defname, "async_capable") == 0 ||
@@ -247,6 +248,7 @@ InitPgFdwOptions(void)
 		{"schema_name", ForeignTableRelationId, false},
 		{"table_name", ForeignTableRelationId, false},
 		{"column_name", AttributeRelationId, false},
+		{"inherited", ForeignTableRelationId, false},
 		/* use_remote_estimate is available on both server and table */
 		{"use_remote_estimate", ForeignServerRelationId, false},
 		{"use_remote_estimate", ForeignTableRelationId, false},
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index e0a34b27c7c..e5d186dc62c 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -649,6 +649,7 @@ postgresGetForeignRelSize(PlannerInfo *root,
 	 * use_remote_estimate, fetch_size and async_capable override per-server
 	 * settings of them, respectively.
 	 */
+	fpinfo->inherited = false;
 	fpinfo->use_remote_estimate = false;
 	fpinfo->fdw_startup_cost = DEFAULT_FDW_STARTUP_COST;
 	fpinfo->fdw_tuple_cost = DEFAULT_FDW_TUPLE_COST;
@@ -1794,6 +1795,28 @@ postgresPlanForeignModify(PlannerInfo *root,
 	bool		doNothing = false;
 	int			values_end_len = -1;
 
+	/*
+	 * We don't currently support update/delete on partitioned/inherited
+	 * foreign tables via ExecForeignUpdate()/ExecForeignDelete(); if the
+	 * operation is update/delete, check whether the foreign table is
+	 * partitioned/inherited or not, and if so, throw an error.  Note that
+	 * we would have already determined that the operation on the foreign
+	 * table cannot be executed via DirectModify before we get here.
+	 */
+	if (operation == CMD_UPDATE || operation == CMD_DELETE)
+	{
+		RelOptInfo *rel = find_base_rel(root, resultRelation);
+		PgFdwRelationInfo *fpinfo = (PgFdwRelationInfo *) rel->fdw_private;
+
+		if (fpinfo && fpinfo->inherited)
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg((operation == CMD_UPDATE) ?
+							"cannot update foreign table \"%s\"" :
+							"cannot delete from foreign table \"%s\"",
+							get_rel_name(rte->relid))));
+	}
+
 	initStringInfo(&sql);
 
 	/*
@@ -6292,7 +6315,9 @@ apply_table_options(PgFdwRelationInfo *fpinfo)
 	{
 		DefElem    *def = (DefElem *) lfirst(lc);
 
-		if (strcmp(def->defname, "use_remote_estimate") == 0)
+		if (strcmp(def->defname, "inherited") == 0)
+			fpinfo->inherited = defGetBoolean(def);
+		else if (strcmp(def->defname, "use_remote_estimate") == 0)
 			fpinfo->use_remote_estimate = defGetBoolean(def);
 		else if (strcmp(def->defname, "fetch_size") == 0)
 			(void) parse_int(defGetString(def), &fpinfo->fetch_size, 0, NULL);
@@ -6414,6 +6439,8 @@ postgresGetForeignJoinPaths(PlannerInfo *root,
 	joinrel->fdw_private = fpinfo;
 	/* attrs_used is only for base relations. */
 	fpinfo->attrs_used = NULL;
+	/* inherited is only for base relations. */
+	fpinfo->inherited = false;
 
 	/*
 	 * If there is a possibility that EvalPlanQual will be executed, we need
@@ -6780,6 +6807,8 @@ postgresGetForeignUpperPaths(PlannerInfo *root, UpperRelationKind stage,
 
 	fpinfo = (PgFdwRelationInfo *) palloc0(sizeof(PgFdwRelationInfo));
 	fpinfo->pushdown_safe = false;
+	/* inherited is only for base relations. */
+	fpinfo->inherited = false;
 	fpinfo->stage = stage;
 	output_rel->fdw_private = fpinfo;
 
diff --git a/contrib/postgres_fdw/postgres_fdw.h b/contrib/postgres_fdw/postgres_fdw.h
index 81358f3bde7..7163b2966dd 100644
--- a/contrib/postgres_fdw/postgres_fdw.h
+++ b/contrib/postgres_fdw/postgres_fdw.h
@@ -76,10 +76,12 @@ typedef struct PgFdwRelationInfo
 	Cost		rel_total_cost;
 
 	/* Options extracted from catalogs. */
+	bool		inherited;
 	bool		use_remote_estimate;
 	Cost		fdw_startup_cost;
 	Cost		fdw_tuple_cost;
 	List	   *shippable_extensions;	/* OIDs of shippable extensions */
+	int			fetch_size;		/* fetch size for this remote table */
 	bool		async_capable;
 
 	/* Cached catalog information. */
@@ -87,8 +89,6 @@ typedef struct PgFdwRelationInfo
 	ForeignServer *server;
 	UserMapping *user;			/* only set in use_remote_estimate mode */
 
-	int			fetch_size;		/* fetch size for this remote table */
-
 	/*
 	 * Name of the relation, for use while EXPLAINing ForeignScan.  It is used
 	 * for join and upper relations but is set for all relations.  For a base
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index b449e122abe..f447eba29dd 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -1725,6 +1725,28 @@ DROP FOREIGN TABLE remt2;
 DROP TABLE loct1;
 DROP TABLE loct2;
 
+-- Test non-pushed-down UPDATE/DELETE on partitioned/inherited foreign tables
+CREATE TABLE plt (a int, b int) PARTITION BY LIST(a);
+CREATE TABLE plt_p1 PARTITION OF plt FOR VALUES IN (1);
+CREATE TABLE plt_p2 PARTITION OF plt FOR VALUES IN (2);
+CREATE FOREIGN TABLE inh_ft (a int, b int) SERVER loopback OPTIONS (table_name 'plt', inherited 'true');
+
+INSERT INTO inh_ft VALUES (1, 1), (2, 2);
+SELECT tableoid::regclass, ctid, * FROM inh_ft;
+
+-- Use random() so that UPDATE/DELETE is not pushed down to the remote
+EXPLAIN (VERBOSE, COSTS OFF)
+UPDATE inh_ft SET b = (CASE WHEN random() <= 1 THEN 10 ELSE 100 END) WHERE a = 1; -- should fail
+UPDATE inh_ft SET b = (CASE WHEN random() <= 1 THEN 10 ELSE 100 END) WHERE a = 1; -- should fail
+
+EXPLAIN (VERBOSE, COSTS OFF)
+DELETE FROM inh_ft WHERE a = (CASE WHEN random() <= 1 THEN 1 ELSE 10 END); -- should fail
+DELETE FROM inh_ft WHERE a = (CASE WHEN random() <= 1 THEN 1 ELSE 10 END); -- should fail
+
+-- Cleanup
+DROP FOREIGN TABLE inh_ft;
+DROP TABLE plt;
+
 -- ===================================================================
 -- test check constraints
 -- ===================================================================
