diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index 72ecc45520c8704b14a5fb70b320c99e657b8352..93e83320cc60fabbcae9ffc67555a56815333923 100644
--- a/doc/src/sgml/ref/grant.sgml
+++ b/doc/src/sgml/ref/grant.sgml
@@ -80,8 +80,8 @@ GRANT <replaceable class="PARAMETER">role_name</replaceable> [, ...] TO <replace
 
   <para>
    The <command>GRANT</command> command has two basic variants: one
-   that grants privileges on a database object (table, column, view, sequence,
-   database, foreign-data wrapper, foreign server, function,
+   that grants privileges on a database object (table, column, view, foreign
+   table, sequence, database, foreign-data wrapper, foreign server, function,
    procedural language, schema, or tablespace), and one that grants
    membership in a role.  These variants are similar in many ways, but
    they are different enough to be described separately.
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index db58ec29f6776d73be5d8ee5018adce7d3e9fe71..df32731b874fc36414dc889d3403d7d5f1aca690 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -274,9 +274,6 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
 		case ACL_KIND_FOREIGN_SERVER:
 			whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
 			break;
-		case ACL_KIND_FOREIGN_TABLE:
-			whole_mask = ACL_ALL_RIGHTS_FOREIGN_TABLE;
-			break;
 		default:
 			elog(ERROR, "unrecognized object kind: %d", objkind);
 			/* not reached, but keep compiler quiet */
@@ -480,10 +477,6 @@ ExecuteGrantStmt(GrantStmt *stmt)
 			all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
 			errormsg = gettext_noop("invalid privilege type %s for foreign server");
 			break;
-		case ACL_OBJECT_FOREIGN_TABLE:
-			all_privileges = ACL_ALL_RIGHTS_FOREIGN_TABLE;
-			errormsg = gettext_noop("invalid privilege type %s for foreign table");
-			break;
 		default:
 			elog(ERROR, "unrecognized GrantStmt.objtype: %d",
 				 (int) stmt->objtype);
@@ -554,7 +547,6 @@ ExecGrantStmt_oids(InternalGrant *istmt)
 	{
 		case ACL_OBJECT_RELATION:
 		case ACL_OBJECT_SEQUENCE:
-		case ACL_OBJECT_FOREIGN_TABLE:
 			ExecGrant_Relation(istmt);
 			break;
 		case ACL_OBJECT_DATABASE:
@@ -604,7 +596,6 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
 	{
 		case ACL_OBJECT_RELATION:
 		case ACL_OBJECT_SEQUENCE:
-		case ACL_OBJECT_FOREIGN_TABLE:
 			foreach(cell, objnames)
 			{
 				RangeVar   *relvar = (RangeVar *) lfirst(cell);
@@ -1702,21 +1693,11 @@ ExecGrant_Relation(InternalGrant *istmt)
 					 errmsg("\"%s\" is not a sequence",
 							NameStr(pg_class_tuple->relname))));
 
-		/* Used GRANT FOREIGN TABLE on a non-foreign-table? */
-		if (istmt->objtype == ACL_OBJECT_FOREIGN_TABLE &&
-			pg_class_tuple->relkind != RELKIND_FOREIGN_TABLE)
-			ereport(ERROR,
-					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-					 errmsg("\"%s\" is not a foreign table",
-							NameStr(pg_class_tuple->relname))));
-
 		/* Adjust the default permissions based on object type */
 		if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
 		{
 			if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
 				this_privileges = ACL_ALL_RIGHTS_SEQUENCE;
-			else if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE)
-				this_privileges = ACL_ALL_RIGHTS_FOREIGN_TABLE;
 			else
 				this_privileges = ACL_ALL_RIGHTS_RELATION;
 		}
@@ -1752,16 +1733,6 @@ ExecGrant_Relation(InternalGrant *istmt)
 					this_privileges &= (AclMode) ACL_ALL_RIGHTS_SEQUENCE;
 				}
 			}
-			else if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE)
-			{
-				if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_FOREIGN_TABLE))
-				{
-					ereport(ERROR,
-							(errcode(ERRCODE_INVALID_GRANT_OPERATION),
-							 errmsg("foreign table \"%s\" only supports SELECT privileges",
-									NameStr(pg_class_tuple->relname))));
-				}
-			}
 			else
 			{
 				if (this_privileges & ~((AclMode) ACL_ALL_RIGHTS_RELATION))
@@ -1819,9 +1790,6 @@ ExecGrant_Relation(InternalGrant *istmt)
 				case RELKIND_SEQUENCE:
 					old_acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
 					break;
-				case RELKIND_FOREIGN_TABLE:
-					old_acl = acldefault(ACL_OBJECT_FOREIGN_TABLE, ownerId);
-					break;
 				default:
 					old_acl = acldefault(ACL_OBJECT_RELATION, ownerId);
 					break;
@@ -1866,9 +1834,6 @@ ExecGrant_Relation(InternalGrant *istmt)
 				case RELKIND_SEQUENCE:
 					aclkind = ACL_KIND_SEQUENCE;
 					break;
-				case RELKIND_FOREIGN_TABLE:
-					aclkind = ACL_KIND_FOREIGN_TABLE;
-					break;
 				default:
 					aclkind = ACL_KIND_CLASS;
 					break;
@@ -1963,16 +1928,6 @@ ExecGrant_Relation(InternalGrant *istmt)
 
 				this_privileges &= (AclMode) ACL_SELECT;
 			}
-			else if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE &&
-					 this_privileges & ~((AclMode) ACL_SELECT))
-			{
-				/* Foreign tables have the same restriction as sequences. */
-				ereport(WARNING,
-						(errcode(ERRCODE_INVALID_GRANT_OPERATION),
-						 errmsg("foreign table \"%s\" only supports SELECT column privileges",
-								NameStr(pg_class_tuple->relname))));
-				this_privileges &= (AclMode) ACL_SELECT;
-			}
 
 			expand_col_privileges(col_privs->cols, relOid,
 								  this_privileges,
@@ -3147,8 +3102,6 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
 	gettext_noop("permission denied for foreign-data wrapper %s"),
 	/* ACL_KIND_FOREIGN_SERVER */
 	gettext_noop("permission denied for foreign server %s"),
-	/* ACL_KIND_FOREIGN_TABLE */
-	gettext_noop("permission denied for foreign table %s"),
 	/* ACL_KIND_EXTENSION */
 	gettext_noop("permission denied for extension %s"),
 };
@@ -3193,8 +3146,6 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
 	gettext_noop("must be owner of foreign-data wrapper %s"),
 	/* ACL_KIND_FOREIGN_SERVER */
 	gettext_noop("must be owner of foreign server %s"),
-	/* ACL_KIND_FOREIGN_TABLE */
-	gettext_noop("must be owner of foreign table %s"),
 	/* ACL_KIND_EXTENSION */
 	gettext_noop("must be owner of extension %s"),
 };
@@ -3491,9 +3442,6 @@ pg_class_aclmask(Oid table_oid, Oid roleid,
 			case RELKIND_SEQUENCE:
 				acl = acldefault(ACL_OBJECT_SEQUENCE, ownerId);
 				break;
-			case RELKIND_FOREIGN_TABLE:
-				acl = acldefault(ACL_OBJECT_FOREIGN_TABLE, ownerId);
-				break;
 			default:
 				acl = acldefault(ACL_OBJECT_RELATION, ownerId);
 				break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 1e4f8f698b368d09df07afc32d6e996a3e1fc876..933a1a2ff9f3739529154e6e07aca4f1a06b95ab 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -5408,14 +5408,6 @@ privilege_target:
 					n->objs = $3;
 					$$ = n;
 				}
-			| FOREIGN TABLE qualified_name_list
-				{
-					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
-					n->targtype = ACL_TARGET_OBJECT;
-					n->objtype = ACL_OBJECT_FOREIGN_TABLE;
-					n->objs = $3;
-					$$ = n;
-				}
 			| FUNCTION function_with_argtypes_list
 				{
 					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index dc75ad86ce2666e651a63649189e191bd465dec9..4a3e241c415fa8bdcfefdf2ffdb9bbbb2c60c377 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -782,10 +782,6 @@ acldefault(GrantObjectType objtype, Oid ownerId)
 			world_default = ACL_NO_RIGHTS;
 			owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER;
 			break;
-		case ACL_OBJECT_FOREIGN_TABLE:
-			world_default = ACL_NO_RIGHTS;
-			owner_default = ACL_ALL_RIGHTS_FOREIGN_TABLE;
-			break;
 		default:
 			elog(ERROR, "unrecognized objtype: %d", (int) objtype);
 			world_default = ACL_NO_RIGHTS;		/* keep compiler quiet */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 24b4f7233395055443ce52e68e37d770d234b360..ee1881b630fbe5f60dd1dbd0ee16d42af71ec7b5 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1282,7 +1282,6 @@ typedef enum GrantObjectType
 	ACL_OBJECT_DATABASE,		/* database */
 	ACL_OBJECT_FDW,				/* foreign-data wrapper */
 	ACL_OBJECT_FOREIGN_SERVER,	/* foreign server */
-	ACL_OBJECT_FOREIGN_TABLE,	/* foreign table */
 	ACL_OBJECT_FUNCTION,		/* function */
 	ACL_OBJECT_LANGUAGE,		/* procedural language */
 	ACL_OBJECT_LARGEOBJECT,		/* largeobject */
diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h
index 75bdaa5343ebbba855c948f5cd7bd9de65b43e47..6b80039f972318eb70a5dbe03bfbdb274d8b152b 100644
--- a/src/include/utils/acl.h
+++ b/src/include/utils/acl.h
@@ -150,7 +150,6 @@ typedef ArrayType Acl;
 #define ACL_ALL_RIGHTS_DATABASE		(ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
 #define ACL_ALL_RIGHTS_FDW			(ACL_USAGE)
 #define ACL_ALL_RIGHTS_FOREIGN_SERVER (ACL_USAGE)
-#define ACL_ALL_RIGHTS_FOREIGN_TABLE (ACL_SELECT)
 #define ACL_ALL_RIGHTS_FUNCTION		(ACL_EXECUTE)
 #define ACL_ALL_RIGHTS_LANGUAGE		(ACL_USAGE)
 #define ACL_ALL_RIGHTS_LARGEOBJECT	(ACL_SELECT|ACL_UPDATE)
@@ -195,7 +194,6 @@ typedef enum AclObjectKind
 	ACL_KIND_TSCONFIGURATION,	/* pg_ts_config */
 	ACL_KIND_FDW,				/* pg_foreign_data_wrapper */
 	ACL_KIND_FOREIGN_SERVER,	/* pg_foreign_server */
-	ACL_KIND_FOREIGN_TABLE,		/* pg_foreign_table */
 	ACL_KIND_EXTENSION,			/* pg_extension */
 	MAX_ACL_KIND				/* MUST BE LAST */
 } AclObjectKind;