diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 794aef4..19dc440 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1025,6 +1025,43 @@ SET ENABLE_SEQSCAN TO OFF;
      </variablelist>
      </sect2>
 
+     <sect2 id="runtime-config-resource-disk">
+     <title>Disk</title>
+     <variablelist>
+
+     <varlistentry id="guc-temp-file-limit" xreflabel="temp_file_limit">
+      <term><varname>temp_file_limit</varname> (<type>integer</type>)</term>
+      <indexterm>
+       <primary><varname>temp_file_limit</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Specifies the amount of disk space used by internal sort operations
+        and hash tables whist writing to temporary disk files. The value
+        defaults to unlimited (<literal>-1</>). Values larger than zero
+        constraint the temporary file space usage to be that number of
+        kilobytes.
+       </para>
+       <para>
+        A given sort or hash operation may write a number of temporary files,
+        the total space used by all the files produced by one backend is
+        constrained to be this value or less. If further bytes are written
+        the current query is canceled.  Only superusers can change this
+        setting.
+       </para>
+       <para>
+        It should be noted that this parameter does <emphasis>not</emphasis>
+        constrain disk space used for temporary table storage. However if
+        the temporary table is created from a query then the any sort
+        and hash files used in query execution will have their space
+        controlled as above.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     </variablelist>
+     </sect2>
+
      <sect2 id="runtime-config-resource-kernel">
      <title>Kernel Resource Usage</title>
      <variablelist>
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 820e6db..5c00889 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -131,6 +131,11 @@ static int	max_safe_fds = 32;	/* default if not changed */
 /* Flag to tell whether there are files to close/delete at end of transaction */
 static bool have_pending_fd_cleanup = false;
 
+/*
+ * Track the total size of all temporary files
+ */
+static double temporary_files_size = 0.0;
+
 typedef struct vfd
 {
 	int			fd;				/* current FD, or VFD_CLOSED if none */
@@ -140,6 +145,7 @@ typedef struct vfd
 	File		lruMoreRecently;	/* doubly linked recency-of-use list */
 	File		lruLessRecently;
 	off_t		seekPos;		/* current logical file position */
+	off_t		fileSize;		/* current size of file */
 	char	   *fileName;		/* name of file, or NULL for unused VFD */
 	/* NB: fileName is malloc'd, and must be free'd when closing the VFD */
 	int			fileFlags;		/* open(2) flags for (re)opening the file */
@@ -887,6 +893,7 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
 	vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL);
 	vfdP->fileMode = fileMode;
 	vfdP->seekPos = 0;
+	vfdP->fileSize = 0;
 	vfdP->fdstate = 0x0;
 	vfdP->resowner = NULL;
 
@@ -1123,6 +1130,13 @@ FileClose(File file)
 			if (unlink(vfdP->fileName))
 				elog(LOG, "could not unlink file \"%s\": %m", vfdP->fileName);
 		}
+
+		if (temp_file_limit >= 0)
+		{
+			/* subtract the unlinked file size from the total */
+			temporary_files_size -= (double)vfdP->fileSize;
+			vfdP->fileSize = 0;
+		}
 	}
 
 	/* Unregister it from the resource owner */
@@ -1251,7 +1265,27 @@ retry:
 		errno = ENOSPC;
 
 	if (returnCode >= 0)
+	{
 		VfdCache[file].seekPos += returnCode;
+
+		if (temp_file_limit >= 0 && VfdCache[file].fdstate & FD_TEMPORARY)
+		{
+			/*
+			 * if we increase the file size, add it to the total, then check it is
+			 * not too big
+			 */
+			if (VfdCache[file].seekPos >= VfdCache[file].fileSize )
+			{
+				temporary_files_size += (double)(VfdCache[file].seekPos - VfdCache[file].fileSize);
+				VfdCache[file].fileSize = VfdCache[file].seekPos;
+
+				if (temporary_files_size / 1024.0 > (double)temp_file_limit)
+					ereport(ERROR,
+							(errcode(ERRCODE_QUERY_CANCELED),
+							 errmsg("aborting due to exceeding temp file limit")));
+			}
+		}
+	}
 	else
 	{
 		/*
@@ -1887,6 +1921,7 @@ CleanupTempFiles(bool isProcExit)
 		}
 
 		have_pending_fd_cleanup = false;
+		temporary_files_size = 0.0;
 	}
 
 	/* Clean up "allocated" stdio files and dirs. */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 92391ed..8ba6dce 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -423,6 +423,7 @@ int			log_min_messages = WARNING;
 int			client_min_messages = NOTICE;
 int			log_min_duration_statement = -1;
 int			log_temp_files = -1;
+int			temp_file_limit = -1;
 int			trace_recovery_messages = LOG;
 
 int			num_temp_buffers = 1024;
@@ -535,6 +536,8 @@ const char *const config_group_names[] =
 	gettext_noop("Resource Usage"),
 	/* RESOURCES_MEM */
 	gettext_noop("Resource Usage / Memory"),
+	/* RESOURCES_DISK */
+	gettext_noop("Resource Usage / Disk"),
 	/* RESOURCES_KERNEL */
 	gettext_noop("Resource Usage / Kernel Resources"),
 	/* RESOURCES_VACUUM_DELAY */
@@ -2185,6 +2188,16 @@ static struct config_int ConfigureNamesInt[] =
 		RELSEG_SIZE, RELSEG_SIZE, RELSEG_SIZE,
 		NULL, NULL, NULL
 	},
+	{
+		{"temp_file_limit", PGC_SUSET, RESOURCES_DISK,
+			gettext_noop("Sets the maximum size of all temp files used by each session."),
+			gettext_noop("-1 turns this feature off."),
+			GUC_UNIT_KB
+		},
+		&temp_file_limit,
+		-1, -1, MAX_KILOBYTES,
+		NULL, NULL, NULL
+	},
 
 	{
 		{"wal_block_size", PGC_INTERNAL, PRESET_OPTIONS,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 655dad4..cc468c7 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -118,6 +118,7 @@
 #work_mem = 1MB				# min 64kB
 #maintenance_work_mem = 16MB		# min 1MB
 #max_stack_depth = 2MB			# min 100kB
+#temp_file_limit = -1    	# limit backend temp file space
 
 # - Kernel Resource Usage -
 
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index ee52cd7..35321ee 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -208,6 +208,7 @@ extern int	log_min_messages;
 extern int	client_min_messages;
 extern int	log_min_duration_statement;
 extern int	log_temp_files;
+extern int	temp_file_limit;
 
 extern int	num_temp_buffers;
 
diff --git a/src/include/utils/guc_tables.h b/src/include/utils/guc_tables.h
index a1ca012..3d9ab37 100644
--- a/src/include/utils/guc_tables.h
+++ b/src/include/utils/guc_tables.h
@@ -59,6 +59,7 @@ enum config_group
 	CONN_AUTH_SECURITY,
 	RESOURCES,
 	RESOURCES_MEM,
+	RESOURCES_DISK,
 	RESOURCES_KERNEL,
 	RESOURCES_VACUUM_DELAY,
 	RESOURCES_BGWRITER,
diff --git a/src/test/regress/expected/resource.out b/src/test/regress/expected/resource.out
new file mode 100644
index 0000000..571fa8f
--- /dev/null
+++ b/src/test/regress/expected/resource.out
@@ -0,0 +1,18 @@
+--
+-- RESOURCE
+-- Test resource management capabilities
+--
+-- temp_file_limit
+CREATE TEMPORARY TABLE resourcetemp1 AS SELECT generate_series(1,100000);
+-- Should succeed
+SET temp_file_limit = 10000;
+SELECT count(*) FROM (select * FROM resourcetemp1  ORDER BY 1) AS a;
+ count
+--------
+ 100000
+(1 row)
+
+-- Should fail
+SET temp_file_limit = 1000;
+SELECT count(*) FROM (select * FROM resourcetemp1  ORDER BY 1) AS a;
+ERROR:  aborting due to exceeding temp file limit
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index bb654f9..325cb3d 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -127,3 +127,4 @@ test: largeobject
 test: with
 test: xml
 test: stats
+test: resource
diff --git a/src/test/regress/sql/resource.sql b/src/test/regress/sql/resource.sql
new file mode 100644
index 0000000..c593a58
--- /dev/null
+++ b/src/test/regress/sql/resource.sql
@@ -0,0 +1,17 @@
+--
+-- RESOURCE
+-- Test resource management capabilities
+--
+
+-- temp_file_limit
+CREATE TEMPORARY TABLE resourcetemp1 AS SELECT generate_series(1,100000);
+
+-- Should succeed
+SET temp_file_limit = 10000;
+
+SELECT count(*) FROM (select * FROM resourcetemp1  ORDER BY 1) AS a;
+
+-- Should fail
+SET temp_file_limit = 1000;
+
+SELECT count(*) FROM (select * FROM resourcetemp1  ORDER BY 1) AS a;
