diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index b4b85fd681..e60b484f47 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -246,7 +246,6 @@ static bool group_by_has_partkey(RelOptInfo *input_rel,
 								 List *targetList,
 								 List *groupClause);
 static int	common_prefix_cmp(const void *a, const void *b);
-static bool query_has_modifying_cte(Query *parse);
 
 /*****************************************************************************
  *
@@ -314,22 +313,6 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions,
 	glob->transientPlan = false;
 	glob->dependsOnRole = false;
 
-	if (IsModifySupportedInParallelMode(parse->commandType) &&
-											 !parse->hasModifyingCTE)
-	{
-		/*
-		 * FIXME
-		 * There is a known bug in the query rewriter: re-written queries with
-		 * a modifying CTE may not have the "hasModifyingCTE" flag set. When
-		 * that bug is fixed, this temporary fix must be removed.
-		 *
-		 * Note that here we've made a fix for this problem only for a
-		 * supported-in-parallel-mode table-modification statement (i.e.
-		 * INSERT), but this bug exists for SELECT too.
-		 */
-		parse->hasModifyingCTE = query_has_modifying_cte(parse);
-	}
-
 	/*
 	 * Assess whether it's feasible to use parallel mode for this query. We
 	 * can't do this in a standalone backend, or if the command will try to
@@ -7788,53 +7771,3 @@ group_by_has_partkey(RelOptInfo *input_rel,
 
 	return true;
 }
-
-/*
- * Determine if the specified query has a modifying-CTE.
- *
- * There is a known bug in the query rewriter: re-written queries with
- * a modifying CTE may not have the "hasModifyingCTE" flag set. When
- * that bug is fixed, this function should be removed.
- *
- */
-static bool
-query_has_modifying_cte(Query *parsetree)
-{
-	int		rt_index;
-	bool	hasModifyingCTE = false;
-
-	/* Recursively check subqueries */
-	rt_index = 0;
-	while (rt_index < list_length(parsetree->rtable))
-	{
-		RangeTblEntry *rte;
-		++rt_index;
-		rte = rt_fetch(rt_index, parsetree->rtable);
-		if (rte->rtekind == RTE_SUBQUERY)
-		{
-			hasModifyingCTE = query_has_modifying_cte(rte->subquery);
-			if (hasModifyingCTE)
-				break;
-		}
-	}
-
-	if (!hasModifyingCTE)
-	{
-		ListCell	*lc;
-
-		/* Check for INSERT/UPDATE/DELETE CTEs */
-		foreach(lc, parsetree->cteList)
-		{
-			CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
-			Query	 *ctequery = castNode(Query, cte->ctequery);
-
-			if (ctequery->commandType != CMD_SELECT)
-			{
-				hasModifyingCTE = true;
-				break;
-			}
-		}
-	}
-
-	return hasModifyingCTE;
-}
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index af8b6d4437..4a918068e8 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -716,6 +716,25 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 			return true;
 	}
 
+	/*
+	 * ModifyingCTE expressions are treated as parallel-unsafe.
+	 *
+	 * XXX Normally, the Query tree has hasModifyingCTE flag that indicates
+	 * the statement is parallel-unsafe but in some cases where query with
+	 * modifying CTE is re-written that flag is not set.
+	 */
+	else if (IsA(node, CommonTableExpr))
+	{
+		CommonTableExpr *cte = (CommonTableExpr *) node;
+		Query *ctequery = castNode(Query, cte->ctequery);
+
+		if (ctequery->commandType != CMD_SELECT)
+		{
+			context->max_hazard = PROPARALLEL_UNSAFE;
+			return true;
+		}
+	}
+
 	/*
 	 * As a notational convenience for callers, look through RestrictInfo.
 	 */
@@ -796,6 +815,8 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 
 		if (rte == context->target_rte)
 			return target_rel_max_parallel_hazard(context);
+		else if (rte->rtekind == RTE_SUBQUERY)
+			return max_parallel_hazard_walker((Node *) rte->subquery, context);
 
 		return false;
 	}
