 src/backend/optimizer/util/pathnode.c | 65 +++++++++++++++++++++++++++++++----
 src/include/nodes/pathnodes.h         |  6 ++++
 src/include/optimizer/pathnode.h      |  9 +++++
 3 files changed, 73 insertions(+), 7 deletions(-)

diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index e6d08aede5..59d27a5885 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -57,6 +57,7 @@ static List *reparameterize_pathlist_by_child(PlannerInfo *root,
 											  List *pathlist,
 											  RelOptInfo *child_rel);
 
+path_removal_decision_hook_type path_removal_decision_hook = NULL;
 
 /*****************************************************************************
  *		MISC. PATH UTILITIES
@@ -586,12 +587,27 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
 		{
 			parent_rel->pathlist = foreach_delete_current(parent_rel->pathlist,
 														  p1);
-
-			/*
-			 * Delete the data pointed-to by the deleted cell, if possible
-			 */
-			if (!IsA(old_path, IndexPath))
-				pfree(old_path);
+			if (path_removal_decision_hook &&
+				path_removal_decision_hook(parent_rel,
+										   new_path,
+										   old_path,
+										   false))
+			{
+				/*
+				 * Old path is moved to the preserved_pathlist for future
+				 * usage, not remove right now.
+				 */
+				parent_rel->preserved_pathlist =
+					lappend(parent_rel->preserved_pathlist, old_path);
+			}
+			else
+			{
+				/*
+				 * Delete the data pointed-to by the deleted cell, if possible
+				 */
+				if (!IsA(old_path, IndexPath))
+					pfree(old_path);
+			}
 		}
 		else
 		{
@@ -615,6 +631,19 @@ add_path(RelOptInfo *parent_rel, Path *new_path)
 		parent_rel->pathlist =
 			list_insert_nth(parent_rel->pathlist, insert_at, new_path);
 	}
+	else if (path_removal_decision_hook &&
+			 path_removal_decision_hook(parent_rel,
+										new_path,
+										NULL,
+										false))
+	{
+		/*
+		 * New but rejected path is moved to the preserved_pathlist for
+		 * future usage, not remove right now.
+		 */
+		parent_rel->preserved_pathlist =
+			lappend(parent_rel->preserved_pathlist, new_path);
+	}
 	else
 	{
 		/* Reject and recycle the new path */
@@ -822,7 +851,20 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
 		{
 			parent_rel->partial_pathlist =
 				foreach_delete_current(parent_rel->partial_pathlist, p1);
-			pfree(old_path);
+			if (path_removal_decision_hook &&
+				path_removal_decision_hook(parent_rel,
+										   new_path,
+										   old_path,
+										   true))
+			{
+				/* Old path is preserved for future usage */
+				parent_rel->preserved_partial_pathlist =
+					lappend(parent_rel->preserved_partial_pathlist, old_path);
+			}
+			else
+			{
+				pfree(old_path);
+			}
 		}
 		else
 		{
@@ -846,6 +888,15 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
 		parent_rel->partial_pathlist =
 			list_insert_nth(parent_rel->partial_pathlist, insert_at, new_path);
 	}
+	else if (path_removal_decision_hook &&
+			 path_removal_decision_hook(parent_rel,
+										new_path,
+										NULL,
+										true))
+	{
+		parent_rel->preserved_partial_pathlist =
+			lappend(parent_rel->preserved_partial_pathlist, new_path);
+	}
 	else
 	{
 		/* Reject and recycle the new path */
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index 3d3be197e0..b31491350c 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -483,6 +483,10 @@ typedef struct PartitionSchemeData *PartitionScheme;
  *			(no duplicates) output from relation; NULL if not yet requested
  *		cheapest_parameterized_paths - best paths for their parameterizations;
  *			always includes cheapest_total_path, even if that's unparameterized
+ *		preserved_pathlist - List of lesser Path nodes; they are not used in
+ *			the Path consideration in usual, but extension may want to pick up
+ *			in case when a special combination of Path nodes can provide more
+ *			efficient execution plan.
  *		direct_lateral_relids - rels this rel has direct LATERAL references to
  *		lateral_relids - required outer rels for LATERAL, as a Relids set
  *			(includes both direct and indirect lateral references)
@@ -657,6 +661,8 @@ typedef struct RelOptInfo
 	List	   *pathlist;		/* Path structures */
 	List	   *ppilist;		/* ParamPathInfos used in pathlist */
 	List	   *partial_pathlist;	/* partial Paths */
+	List	   *preserved_pathlist;	/* preserved 'lesser' Paths */
+	List	   *preserved_partial_pathlist; /* preserved partial Paths */
 	struct Path *cheapest_startup_path;
 	struct Path *cheapest_total_path;
 	struct Path *cheapest_unique_path;
diff --git a/src/include/optimizer/pathnode.h b/src/include/optimizer/pathnode.h
index e450fe112a..a595920a48 100644
--- a/src/include/optimizer/pathnode.h
+++ b/src/include/optimizer/pathnode.h
@@ -17,6 +17,15 @@
 #include "nodes/bitmapset.h"
 #include "nodes/pathnodes.h"
 
+/*
+ * Plugins can provide extra decision whether the Path-node should be
+ * retained at the preserved_(partial_)pathlist.
+ */
+typedef bool (*path_removal_decision_hook_type)(RelOptInfo *parent_rel,
+												Path *new_path,
+												Path *old_path,
+												bool is_partial_pathlist);
+extern PGDLLIMPORT path_removal_decision_hook_type path_removal_decision_hook;
 
 /*
  * prototypes for pathnode.c
