diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 72b5920..7c0ff10 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -2006,14 +2006,16 @@ include_dir 'conf.d'
        </term>
        <listitem>
         <para>
-         Sets the maximum number of workers that can be started for an
-         individual parallel operation.  Parallel workers are taken from the
-         pool of processes established by
-         <xref linkend="guc-max-worker-processes">.  Note that the requested
+         Sets the maximum number of processes that can be used to perform a
+         parallel operation.  The leader is included, so a value of 1 disables
+         parallel query execution, and any higher value will potentially
+         attempt to launch a number of parallel workers one less than the
+         configured value.  Parallel workers are taken from the pool of
+         processes established by
+         <xref linkend="guc-max-worker-processes">.  Note that the necessary
          number of workers may not actually be available at runtime.  If this
          occurs, the plan will run with fewer workers than expected, which may
-         be inefficient.  The default value is 2.  Setting this value to 0
-         disables parallel query execution.
+         be inefficient.  The default value is 3.
         </para>
        </listitem>
       </varlistentry>
diff --git a/doc/src/sgml/ref/create_table.sgml b/doc/src/sgml/ref/create_table.sgml
index d1807ed..832afef 100644
--- a/doc/src/sgml/ref/create_table.sgml
+++ b/doc/src/sgml/ref/create_table.sgml
@@ -912,11 +912,15 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI
     <term><literal>parallel_degree</> (<type>integer</>)</term>
     <listitem>
      <para>
-      The parallel degree for a table is the number of workers that should
-      be used to assist a parallel scan of that table.  If not set, the
+      The parallel degree for a table is the number of processes that should
+      be used for parallel scan of that table. If not set, the
       system will determine a value based on the relation size.  The actual
-      number of workers chosen by the planner may be less, for example due to
-      the setting of <xref linkend="guc-max-parallel-degree">.
+      degree of parallelism chosen by the planner may be less, for example due
+      to the setting of <xref linkend="guc-max-parallel-degree">.  Note that
+      the leader is included, so a value of 1 indicates that a parallel scan
+      should never be used on this table.  Any larger number indicates that
+      the leader and a number of workers up to one less that the configured
+      value should be used.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 7448c7f..0163f29 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -271,11 +271,11 @@ static relopt_int intRelOpts[] =
 	{
 		{
 			"parallel_degree",
-			"Number of parallel processes that can be used per executor node for this relation.",
+			"Number of processes that should be used for a parallel scan of this relation.",
 			RELOPT_KIND_HEAP,
 			AccessExclusiveLock
 		},
-		-1, 0, 1024
+		-1, 1, 1024
 	},
 
 	/* list terminator */
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 873a764..0cee58a 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -669,7 +669,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
 static void
 create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel)
 {
-	int			parallel_degree = 1;
+	int			parallel_degree = 2;
 
 	/*
 	 * If the user has set the parallel_degree reloption, we decide what to do
@@ -678,10 +678,10 @@ create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel)
 	if (rel->rel_parallel_degree != -1)
 	{
 		/*
-		 * If parallel_degree = 0 is set for this relation, bail out.  The
-		 * user does not want a parallel path for this relation.
+		 * If we don't have permission to use at least two processes, then
+		 * we can't generate a parallel path.
 		 */
-		if (rel->rel_parallel_degree == 0)
+		if (rel->rel_parallel_degree < 2)
 			return;
 
 		/*
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index 4c9d8d9..ac26974 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -113,7 +113,7 @@ int			effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
 
 Cost		disable_cost = 1.0e10;
 
-int			max_parallel_degree = 2;
+int			max_parallel_degree = 3;
 
 bool		enable_seqscan = true;
 bool		enable_indexscan = true;
@@ -230,7 +230,7 @@ cost_seqscan(Path *path, PlannerInfo *root,
 	cpu_run_cost += path->pathtarget->cost.per_tuple * path->rows;
 
 	/* Adjust costing for parallelism, if used. */
-	if (path->parallel_degree > 0)
+	if (path->parallel_degree > 1)
 	{
 		double		parallel_divisor = path->parallel_degree;
 		double		leader_contribution;
@@ -246,7 +246,7 @@ cost_seqscan(Path *path, PlannerInfo *root,
 		 * estimate that the leader spends 30% of its time servicing each
 		 * worker, and the remainder executing the parallel plan.
 		 */
-		leader_contribution = 1.0 - (0.3 * path->parallel_degree);
+		leader_contribution = 1.0 - (0.3 * (path->parallel_degree - 1));
 		if (leader_contribution > 0)
 			parallel_divisor += leader_contribution;
 
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 185f062..abafc46 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -1383,7 +1383,7 @@ create_gather_plan(PlannerInfo *root, GatherPath *best_path)
 
 	gather_plan = make_gather(tlist,
 							  NIL,
-							  best_path->path.parallel_degree,
+							  best_path->path.parallel_degree - 1,
 							  best_path->single_copy,
 							  subplan);
 
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 75d93c0..1195e58 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -245,7 +245,7 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
 	glob->parallelModeOK = (cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
 		IsUnderPostmaster && dynamic_shared_memory_type != DSM_IMPL_NONE &&
 		parse->commandType == CMD_SELECT && !parse->hasModifyingCTE &&
-		parse->utilityStmt == NULL && max_parallel_degree > 0 &&
+		parse->utilityStmt == NULL && max_parallel_degree > 1 &&
 		!IsParallelWorker() && !IsolationIsSerializable() &&
 		!has_parallel_hazard((Node *) parse, true);
 
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 6182b36..07f5e23 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -950,7 +950,7 @@ create_seqscan_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->pathtarget = rel->reltarget;
 	pathnode->param_info = get_baserel_parampathinfo(root, rel,
 													 required_outer);
-	pathnode->parallel_aware = parallel_degree > 0 ? true : false;
+	pathnode->parallel_aware = parallel_degree > 1 ? true : false;
 	pathnode->parallel_safe = rel->consider_parallel;
 	pathnode->parallel_degree = parallel_degree;
 	pathnode->pathkeys = NIL;	/* seqscan has unordered result */
@@ -976,7 +976,7 @@ create_samplescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer
 													 required_outer);
 	pathnode->parallel_aware = false;
 	pathnode->parallel_safe = rel->consider_parallel;
-	pathnode->parallel_degree = 0;
+	pathnode->parallel_degree = 1;
 	pathnode->pathkeys = NIL;	/* samplescan has unordered result */
 
 	cost_samplescan(pathnode, root, rel, pathnode->param_info);
@@ -1033,7 +1033,7 @@ create_index_path(PlannerInfo *root,
 														  required_outer);
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.pathkeys = pathkeys;
 
 	/* Convert clauses to indexquals the executor can handle */
@@ -1082,7 +1082,7 @@ create_bitmap_heap_path(PlannerInfo *root,
 														  required_outer);
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.pathkeys = NIL;		/* always unordered */
 
 	pathnode->bitmapqual = bitmapqual;
@@ -1118,7 +1118,7 @@ create_bitmap_and_path(PlannerInfo *root,
 	 */
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 
 	pathnode->path.pathkeys = NIL;		/* always unordered */
 
@@ -1154,7 +1154,7 @@ create_bitmap_or_path(PlannerInfo *root,
 	 */
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 
 	pathnode->path.pathkeys = NIL;		/* always unordered */
 
@@ -1183,7 +1183,7 @@ create_tidscan_path(PlannerInfo *root, RelOptInfo *rel, List *tidquals,
 														  required_outer);
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.pathkeys = NIL;		/* always unordered */
 
 	pathnode->tidquals = tidquals;
@@ -1274,7 +1274,7 @@ create_merge_append_path(PlannerInfo *root,
 															required_outer);
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.pathkeys = pathkeys;
 	pathnode->subpaths = subpaths;
 
@@ -1357,7 +1357,7 @@ create_result_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.param_info = NULL;	/* there are no other rels... */
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.pathkeys = NIL;
 	pathnode->quals = resconstantqual;
 
@@ -1687,9 +1687,8 @@ create_gather_path(PlannerInfo *root, RelOptInfo *rel, Path *subpath,
 	pathnode->subpath = subpath;
 	pathnode->single_copy = false;
 
-	if (pathnode->path.parallel_degree == 0)
+	if (pathnode->path.parallel_degree == 1)
 	{
-		pathnode->path.parallel_degree = 1;
 		pathnode->path.pathkeys = subpath->pathkeys;
 		pathnode->single_copy = true;
 	}
@@ -1745,7 +1744,7 @@ create_functionscan_path(PlannerInfo *root, RelOptInfo *rel,
 													 required_outer);
 	pathnode->parallel_aware = false;
 	pathnode->parallel_safe = rel->consider_parallel;
-	pathnode->parallel_degree = 0;
+	pathnode->parallel_degree = 1;
 	pathnode->pathkeys = pathkeys;
 
 	cost_functionscan(pathnode, root, rel, pathnode->param_info);
@@ -1771,7 +1770,7 @@ create_valuesscan_path(PlannerInfo *root, RelOptInfo *rel,
 													 required_outer);
 	pathnode->parallel_aware = false;
 	pathnode->parallel_safe = rel->consider_parallel;
-	pathnode->parallel_degree = 0;
+	pathnode->parallel_degree = 1;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
 
 	cost_valuesscan(pathnode, root, rel, pathnode->param_info);
@@ -1796,7 +1795,7 @@ create_ctescan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer)
 													 required_outer);
 	pathnode->parallel_aware = false;
 	pathnode->parallel_safe = rel->consider_parallel;
-	pathnode->parallel_degree = 0;
+	pathnode->parallel_degree = 1;
 	pathnode->pathkeys = NIL;	/* XXX for now, result is always unordered */
 
 	cost_ctescan(pathnode, root, rel, pathnode->param_info);
@@ -1822,7 +1821,7 @@ create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel,
 													 required_outer);
 	pathnode->parallel_aware = false;
 	pathnode->parallel_safe = rel->consider_parallel;
-	pathnode->parallel_degree = 0;
+	pathnode->parallel_degree = 1;
 	pathnode->pathkeys = NIL;	/* result is always unordered */
 
 	/* Cost is the same as for a regular CTE scan */
@@ -1861,7 +1860,7 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel,
 														  required_outer);
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = rel->consider_parallel;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.rows = rows;
 	pathnode->path.startup_cost = startup_cost;
 	pathnode->path.total_cost = total_cost;
@@ -2647,7 +2646,7 @@ create_minmaxagg_path(PlannerInfo *root,
 	pathnode->path.parallel_aware = false;
 	/* A MinMaxAggPath implies use of subplans, so cannot be parallel-safe */
 	pathnode->path.parallel_safe = false;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	/* Result is one unordered row */
 	pathnode->path.rows = 1;
 	pathnode->path.pathkeys = NIL;
@@ -2871,7 +2870,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.param_info = NULL;
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = false;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.rows = subpath->rows;
 
 	/*
@@ -2942,7 +2941,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
 	pathnode->path.param_info = NULL;
 	pathnode->path.parallel_aware = false;
 	pathnode->path.parallel_safe = false;
-	pathnode->path.parallel_degree = 0;
+	pathnode->path.parallel_degree = 1;
 	pathnode->path.pathkeys = NIL;
 
 	/*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index e246a9c..1cb9879 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2662,7 +2662,7 @@ static struct config_int ConfigureNamesInt[] =
 			NULL
 		},
 		&max_parallel_degree,
-		2, 0, 1024,
+		3, 1, 1024,
 		NULL, NULL, NULL
 	},
 
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 2d2db7e..0fae058 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -167,7 +167,7 @@
 
 #effective_io_concurrency = 1		# 1-1000; 0 disables prefetching
 #max_worker_processes = 8		# (change requires restart)
-#max_parallel_degree = 2		# max number of worker processes per node
+#max_parallel_degree = 3		# max number of processes per node (inc. leader)
 #old_snapshot_threshold = -1		# 1min-60d; -1 disables; 0 is immediate
 									# (change requires restart)
 #backend_flush_after = 0		# 0 disables,
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 45739c3..2f4bcc6 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -522,7 +522,7 @@ typedef struct RelOptInfo
 	double		allvisfrac;
 	PlannerInfo *subroot;		/* if subquery */
 	List	   *subplan_params; /* if subquery */
-	int			rel_parallel_degree;	/* wanted number of parallel workers */
+	int			rel_parallel_degree;	/* wanted degree of parallelism */
 
 	/* Information about foreign tables and foreign joins */
 	Oid			serverid;		/* identifies server for the table or join */
@@ -872,7 +872,7 @@ typedef struct Path
 
 	bool		parallel_aware; /* engage parallel-aware logic? */
 	bool		parallel_safe;	/* OK to use as part of parallel plan? */
-	int			parallel_degree;	/* desired parallel degree; 0 = not parallel */
+	int			parallel_degree;	/* desired parallel degree; 1 = not parallel */
 
 	/* estimated size/costs for path (see costsize.c for more info) */
 	double		rows;			/* estimated number of result tuples */
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a0ba417..2e7db34 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -207,7 +207,7 @@ typedef struct StdRdOptions
 	AutoVacOpts autovacuum;		/* autovacuum-related options */
 	bool		user_catalog_table;		/* use as an additional catalog
 										 * relation */
-	int			parallel_degree;	/* max number of parallel workers */
+	int			parallel_degree;	/* desired parallel degree */
 } StdRdOptions;
 
 #define HEAP_MIN_FILLFACTOR			10
