diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index c464d054c942c8853c00c98026d8d3e6ebfbd38c..abd7b2d3cb819ddd4b1dba0e06c84b93d5ed9ede 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -230,6 +230,9 @@ create_plan_recurse(PlannerInfo *root, Path *best_path)
 {
 	Plan	   *plan;
 
+	/* Guard against stack overflow due to overly complex plans */
+	check_stack_depth();
+
 	switch (best_path->pathtype)
 	{
 		case T_SeqScan:
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 0c2bb5d51f374af0f9e6c31e0f33d950aa21f4a0..c54e3251dcc4b84a467a4a1e8f0d3e1fcef1874f 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -220,6 +220,9 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
 					   int flag, List *refnames_tlist,
 					   List **sortClauses, double *pNumGroups)
 {
+	/* Guard against stack overflow due to overly complex setop nests */
+	check_stack_depth();
+
 	if (IsA(setOp, RangeTblRef))
 	{
 		RangeTblRef *rtr = (RangeTblRef *) setOp;