diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 3c695c1..4cf5825 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1673,6 +1673,15 @@ static struct config_bool ConfigureNamesBool[] =
 static struct config_int ConfigureNamesInt[] =
 {
 	{
+		{"max_sort_tapes", PGC_USERSET, DEVELOPER_OPTIONS,
+			gettext_noop("Limits number of sort tapes."),
+			NULL
+		},
+		&max_sort_tapes,
+		0, 0, INT_MAX / 2,
+		NULL, NULL, NULL
+	},
+	{
 		{"archive_timeout", PGC_SIGHUP, WAL_ARCHIVING,
 			gettext_noop("Forces a switch to the next xlog file if a "
 						 "new file has not been started within N seconds."),
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 46512cf..d1869e2 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -152,6 +152,7 @@
 #ifdef TRACE_SORT
 bool		trace_sort = false;
 #endif
+int			max_sort_tapes = 0;
 
 #ifdef DEBUG_BOUNDED_SORT
 bool		optimize_bounded_sort = true;
@@ -2316,6 +2317,10 @@ tuplesort_merge_order(int64 allowedMem)
 	/* Even in minimum memory, use at least a MINORDER merge */
 	mOrder = Max(mOrder, MINORDER);
 
+	/* If max_sort_tapes is non-zero, limit sorts to that number of tapes. */
+	if (max_sort_tapes != 0 && mOrder > max_sort_tapes)
+		mOrder = max_sort_tapes;
+
 	return mOrder;
 }
 
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 78545da..13858f2 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -466,4 +466,6 @@ extern bool has_rolreplication(Oid roleid);
 extern bool BackupInProgress(void);
 extern void CancelBackup(void);
 
+extern int		max_sort_tapes;
+
 #endif   /* MISCADMIN_H */
