diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 470db5b..61333d3 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -427,6 +427,7 @@ sql_fn_make_param(SQLFunctionParseInfoPtr pinfo,
 	param->paramtypmod = -1;
 	param->paramcollid = get_typcollation(param->paramtype);
 	param->location = location;
+	param->parallel_safe = false;
 
 	/*
 	 * If we have a function input collation, allow it to override the
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 5e52d9d..b65927f 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1220,6 +1220,7 @@ _copyParam(const Param *from)
 	COPY_SCALAR_FIELD(paramtypmod);
 	COPY_SCALAR_FIELD(paramcollid);
 	COPY_LOCATION_FIELD(location);
+	COPY_SCALAR_FIELD(parallel_safe);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 548a2aa..f806ad5 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -183,6 +183,7 @@ _equalParam(const Param *a, const Param *b)
 	COMPARE_SCALAR_FIELD(paramtypmod);
 	COMPARE_SCALAR_FIELD(paramcollid);
 	COMPARE_LOCATION_FIELD(location);
+	COMPARE_LOCATION_FIELD(parallel_safe);
 
 	return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 381034f..633d767 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1007,6 +1007,7 @@ _outParam(StringInfo str, const Param *node)
 	WRITE_INT_FIELD(paramtypmod);
 	WRITE_OID_FIELD(paramcollid);
 	WRITE_LOCATION_FIELD(location);
+	WRITE_BOOL_FIELD(parallel_safe);
 }
 
 static void
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 418bd6b..3c4dbf5 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -533,6 +533,7 @@ _readParam(void)
 	READ_INT_FIELD(paramtypmod);
 	READ_OID_FIELD(paramcollid);
 	READ_LOCATION_FIELD(location);
+	READ_BOOL_FIELD(parallel_safe);
 
 	READ_DONE();
 }
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 3171743..9fe9286 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -160,6 +160,9 @@ replace_outer_var(PlannerInfo *root, Var *var)
 	retval->paramcollid = var->varcollid;
 	retval->location = var->location;
 
+	/* mark vars from same or immediate outer level as parallel safe */
+	retval->parallel_safe = (var->varlevelsup <= 1) ? true : false;
+
 	return retval;
 }
 
@@ -188,6 +191,9 @@ assign_nestloop_param_var(PlannerInfo *root, Var *var)
 	retval->paramcollid = var->varcollid;
 	retval->location = var->location;
 
+	/* mark vars from same or immediate outer level as parallel safe */
+	retval->parallel_safe = (var->varlevelsup <= 1) ? true : false;
+
 	return retval;
 }
 
@@ -265,6 +271,9 @@ replace_outer_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
 	retval->paramcollid = exprCollation((Node *) phv->phexpr);
 	retval->location = -1;
 
+	/* mark phvs from same or immediate outer level as parallel safe */
+	retval->parallel_safe = (phv->phlevelsup <= 1) ? true : false;
+
 	return retval;
 }
 
@@ -292,6 +301,9 @@ assign_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
 	retval->paramcollid = exprCollation((Node *) phv->phexpr);
 	retval->location = -1;
 
+	/* mark phvs from same or immediate outer level as parallel safe */
+	retval->parallel_safe = (phv->phlevelsup <= 1) ? true : false;
+
 	return retval;
 }
 
@@ -334,6 +346,9 @@ replace_outer_agg(PlannerInfo *root, Aggref *agg)
 	retval->paramcollid = agg->aggcollid;
 	retval->location = agg->location;
 
+	/* mark aggrefs from same or immediate outer level as parallel safe */
+	retval->parallel_safe = (agg->agglevelsup <= 1) ? true : false;
+
 	return retval;
 }
 
@@ -376,6 +391,9 @@ replace_outer_grouping(PlannerInfo *root, GroupingFunc *grp)
 	retval->paramcollid = InvalidOid;
 	retval->location = grp->location;
 
+	/* mark aggs from same or immediate outer level as parallel safe */
+	retval->parallel_safe = (grp->agglevelsup <= 1) ? true : false;
+
 	return retval;
 }
 
@@ -399,6 +417,7 @@ generate_new_param(PlannerInfo *root, Oid paramtype, int32 paramtypmod,
 	retval->paramtypmod = paramtypmod;
 	retval->paramcollid = paramcollation;
 	retval->location = -1;
+	retval->parallel_safe = false;
 
 	return retval;
 }
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index eabdc15..c84c0c7 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -1276,13 +1276,10 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
 		}
 	}
 
-	/*
-	 * We can't pass Params to workers at the moment either, so they are also
-	 * parallel-restricted.
-	 */
+	/* only parallel-safe params can be passed to workers */
 	else if (IsA(node, Param))
 	{
-		if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
+		if (!((Param *) node)->parallel_safe)
 			return true;
 	}
 
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 92d1577..1ea7475 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -2051,5 +2051,6 @@ make_agg_arg(Oid argtype, Oid argcollation)
 	argp->paramtypmod = -1;
 	argp->paramcollid = argcollation;
 	argp->location = -1;
+	argp->parallel_safe = false;
 	return (Node *) argp;
 }
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index 8a2bdf0..59bebce 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -1613,6 +1613,7 @@ transformMultiAssignRef(ParseState *pstate, MultiAssignRef *maref)
 		param->paramtypmod = exprTypmod((Node *) tle->expr);
 		param->paramcollid = exprCollation((Node *) tle->expr);
 		param->location = exprLocation((Node *) tle->expr);
+		param->parallel_safe = false;
 
 		return (Node *) param;
 	}
@@ -1970,6 +1971,7 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
 			param->paramtypmod = exprTypmod((Node *) tent->expr);
 			param->paramcollid = exprCollation((Node *) tent->expr);
 			param->location = -1;
+			param->parallel_safe = false;
 
 			right_list = lappend(right_list, param);
 		}
diff --git a/src/backend/parser/parse_param.c b/src/backend/parser/parse_param.c
index b402843..4dd8e76 100644
--- a/src/backend/parser/parse_param.c
+++ b/src/backend/parser/parse_param.c
@@ -117,6 +117,7 @@ fixed_paramref_hook(ParseState *pstate, ParamRef *pref)
 	param->paramtypmod = -1;
 	param->paramcollid = get_typcollation(param->paramtype);
 	param->location = pref->location;
+	param->parallel_safe = false;
 
 	return (Node *) param;
 }
@@ -170,6 +171,7 @@ variable_paramref_hook(ParseState *pstate, ParamRef *pref)
 	param->paramtypmod = -1;
 	param->paramcollid = get_typcollation(param->paramtype);
 	param->location = pref->location;
+	param->parallel_safe = false;
 
 	return (Node *) param;
 }
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 717d822..4aad9ee 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -225,6 +225,7 @@ typedef struct Param
 	int32		paramtypmod;	/* typmod value, if known */
 	Oid			paramcollid;	/* OID of collation, or InvalidOid if none */
 	int			location;		/* token location, or -1 if unknown */
+	bool		parallel_safe;	/* OK to use as part of parallel plan? */
 } Param;
 
 /*
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 18948c8..96ab7b0 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -1327,6 +1327,7 @@ make_datum_param(PLpgSQL_expr *expr, int dno, int location)
 									 &param->paramtypmod,
 									 &param->paramcollid);
 	param->location = location;
+	param->parallel_safe = false;
 
 	return (Node *) param;
 }
