diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index c1128f8..c63e122 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1654,6 +1654,78 @@ include_dir 'conf.d'
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-max-age-prepared-xacts" xreflabel="max_age_prepared_xacts">
+      <term><varname>max_age_prepared_xacts</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>max_age_prepared_xacts</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Sets maximum age after which a prepared transaction is considered an
+        orphan. <varname>max_age_prepared_xacts</varname> only applies when
+        <quote>prepared transactions</quote> are enabled (see
+        <xref linkend="guc-max-prepared-transactions"/>). The age for a
+        transaction is calculated from the time it was created to current time.
+        If this value is specified without units, it is taken as milliseconds.
+        The default value is -1 which allows prepared transactions to live
+        forever. This parameter can only be set in the
+        <filename>postgresql.conf</filename> file or on the server command
+        line.
+       </para>
+
+       <para>
+        If you are planning to use prepared transactions, this parameter
+        may be set to a value that defines maximum age a prepared
+        transaction can take in your environment. This parameter must be
+        used in conjunction with <varname>prepared_xacts_vacuum_warn_timeout
+        </varname> (see
+        <xref linkend="guc-prepared-xacts-vacuum-warn-timeout"/>).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="guc-prepared-xacts-vacuum-warn-timeout" xreflabel="prepared_xacts_vacuum_warn_timeout">
+      <term><varname>prepared_xacts_vacuum_warn_timeout</varname> (<type>integer</type>)
+      <indexterm>
+       <primary><varname>prepared_xacts_vacuum_warn_timeout</varname> configuration parameter</primary>
+      </indexterm>
+      </term>
+      <listitem>
+       <para>
+        Sets timeout after which vacuum starts throwing warnings for every
+        prepared transactions that has exceeded maximum age defined by
+        <varname>max_age_prepared_xacts</varname> (see <xref
+        linkend="guc-max-age-prepared-xacts"/>).
+        If this value is specified without units, it is taken as milliseconds.
+        The default value of -1 will disable this warning mechanism. Setting
+        a too value could potentially fill up log with orphaned prepared
+        transaction warnings, so this parameter must be set to a value that
+        is reasonably large to not fill up log file, but small enough to
+        notify of long running and potential orphaned prepared transactions.
+        This parameter can only be set in the
+        <filename>postgresql.conf</filename> file or on the server command
+        line.
+       </para>
+
+       <para>
+        This guc along with <varname>max_age_prepared_xacts</varname>, if
+        enabled, help you better manage prepared transactions. Warnings are
+        emitted to log when an autovacuum worker encounters orphaned
+        prepared transactions, or to a client which has issued a vacuum
+        command. This parameter defines how frequently a vacuum process
+        should throw a warning when it encounters a prepared transaction
+        with an age exceeding <varname>max_age_prepared_xacts</varname>.
+       </para>
+
+       <para>
+        The warning are <quote>not</quote> thrown when vacuum command is run
+        with relations, or when vacuumdb command is executed.
+       </para>
+
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="guc-work-mem" xreflabel="work_mem">
       <term><varname>work_mem</varname> (<type>integer</type>)
       <indexterm>
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 5adf956..2bc3ee7 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -116,6 +116,10 @@
 /* GUC variable, can't be changed after startup */
 int			max_prepared_xacts = 0;
 
+/* GUC variables for checking for orphaned prepared transactions */
+int			max_age_prepared_xacts = 0;
+int			prepared_xacts_vacuum_warn_timeout = 0;
+
 /*
  * This struct describes one global transaction that is in prepared state
  * or attempting to become prepared.
@@ -184,6 +188,9 @@ typedef struct TwoPhaseStateData
 	/* Number of valid prepXacts entries. */
 	int			numPrepXacts;
 
+	/* Flag to tell if we throw a warning for over aged prepared xacts */
+	TimestampTz overage_warned_at;
+
 	/* There are max_prepared_xacts items in this array */
 	GlobalTransaction prepXacts[FLEXIBLE_ARRAY_MEMBER];
 } TwoPhaseStateData;
@@ -264,6 +271,7 @@ TwoPhaseShmemInit(void)
 		Assert(!found);
 		TwoPhaseState->freeGXacts = NULL;
 		TwoPhaseState->numPrepXacts = 0;
+		TwoPhaseState->overage_warned_at = 0;
 
 		/*
 		 * Initialize the linked list of free GlobalTransactionData structs
@@ -428,6 +436,14 @@ MarkAsPreparing(TransactionId xid, const char *gid,
 	Assert(TwoPhaseState->numPrepXacts < max_prepared_xacts);
 	TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts++] = gxact;
 
+	/*
+	 * Is this the first prepared transaction? If so, then let's set
+	 * last warned date at curret timestamp, so that we can warn
+	 * about this if it becomes orphaned.
+	 */
+	if (TwoPhaseState->numPrepXacts == 1)
+		TwoPhaseState->overage_warned_at = GetCurrentTimestamp();
+
 	LWLockRelease(TwoPhaseStateLock);
 
 	return gxact;
@@ -697,6 +713,81 @@ GetPreparedTransactionList(GlobalTransaction *gxacts)
 	return num;
 }
 
+/*
+ * To be called from within a vacuum process whether initiated through
+ * autovacuum or via client initiated vacuum command.
+ *
+ * Returns total number of orphaned prepared transactions and throws
+ * one warning message for every orphaned prepared transactions found.
+ * Return -1 if timeout period hasn't completed.
+ *
+ * force_warning skips the timeout check for throwing warnings. This
+ * ensures that manually executed vacuum command is notified of any
+ * orphaned prepared transactions.
+ */
+int
+WarnOverAgedPreparedTransactions(bool force_warning)
+{
+	bool		should_warn = force_warning;
+	int			num = 0;
+	int			num_overage = 0;
+	int			i;
+	TimestampTz	current_time = GetCurrentTimestamp();
+
+	if (prepared_xacts_vacuum_warn_timeout == -1 || max_age_prepared_xacts == -1)
+		return -1;
+
+	/* Get exclusive lock so that we can update data in TwoPhaseState
+	 * global structure.
+	 */
+	LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
+
+	should_warn |= TimestampDifferenceExceeds(TwoPhaseState->overage_warned_at, current_time, prepared_xacts_vacuum_warn_timeout);
+
+	if (should_warn)
+	{
+		TwoPhaseState->overage_warned_at = current_time;
+	}
+
+	LWLockRelease(TwoPhaseStateLock);
+
+	if (!should_warn)
+		return -1;
+
+	/* Get shared lock to count orphaned transactions */
+	LWLockAcquire(TwoPhaseStateLock, LW_SHARED);
+
+	if (TwoPhaseState->numPrepXacts == 0)
+	{
+		LWLockRelease(TwoPhaseStateLock);
+		return 0;
+	}
+
+	num = TwoPhaseState->numPrepXacts;
+
+	for (i = 0; i < num; i++)
+	{
+		if (TimestampDifferenceExceeds(TwoPhaseState->prepXacts[i]->prepared_at, current_time, max_age_prepared_xacts))
+		{
+			num_overage += 1;
+
+			ereport(WARNING,
+					(errcode(ERRCODE_WARNING),
+					 errmsg("prepared transaction with identifier \"%s\" created on \"%s\" is overage.",
+						TwoPhaseState->prepXacts[i]->gid, timestamptz_to_str(TwoPhaseState->prepXacts[i]->prepared_at))));
+		}
+	}
+
+	if (num_overage > 0)
+		ereport(WARNING,
+				(errcode(ERRCODE_WARNING),
+				 errmsg("%d orphaned prepared transactions found.", num_overage),
+				 errhint("Overage transaction(s) may require manual administrative action(s).")));
+
+	LWLockRelease(TwoPhaseStateLock);
+
+	return num_overage;
+}
 
 /* Working status for pg_prepared_xact */
 typedef struct
@@ -2383,6 +2474,14 @@ PrepareRedoAdd(char *buf, XLogRecPtr start_lsn,
 	Assert(TwoPhaseState->numPrepXacts < max_prepared_xacts);
 	TwoPhaseState->prepXacts[TwoPhaseState->numPrepXacts++] = gxact;
 
+	/*
+	 * Is this the first prepared transaction? If so, then let's set
+	 * last warned date at curret timestamp, so that we can warn
+	 * about this if it becomes orphaned.
+	 */
+	if (TwoPhaseState->numPrepXacts == 1)
+		TwoPhaseState->overage_warned_at = GetCurrentTimestamp();
+
 	if (origin_id != InvalidRepOriginId)
 	{
 		/* recover apply progress */
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index d625d17..cb8bca5 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -30,6 +30,7 @@
 #include "access/multixact.h"
 #include "access/tableam.h"
 #include "access/transam.h"
+#include "access/twophase.h"
 #include "access/xact.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_database.h"
@@ -373,7 +374,17 @@ vacuum(List *relations, VacuumParams *params,
 		relations = newrels;
 	}
 	else
+	{
+		/*
+		 * We need to throw a warning to a client running a vacuum process if
+		 * there are any orphaned prepared transactions so that an administrator
+		 * may take requisite action. Since this is a manually initiated commmand,
+		 * we need to force generation of warnings.
+		 */
+		WarnOverAgedPreparedTransactions(true);
+
 		relations = get_all_vacuum_rels(params->options);
+	}
 
 	/*
 	 * Decide whether we need to start/commit our own transactions.
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index e3a43d3..2417b4f 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -71,6 +71,7 @@
 #include "access/reloptions.h"
 #include "access/tableam.h"
 #include "access/transam.h"
+#include "access/twophase.h"
 #include "access/xact.h"
 #include "catalog/dependency.h"
 #include "catalog/namespace.h"
@@ -2004,6 +2005,11 @@ do_autovacuum(void)
 		default_multixact_freeze_table_age = vacuum_multixact_freeze_table_age;
 	}
 
+	/*
+	 * Let's throw warnings for any orphaned prepared transactions.
+	 */
+	WarnOverAgedPreparedTransactions(false);
+
 	ReleaseSysCache(tuple);
 
 	/* StartTransactionCommand changed elsewhere */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 464f264..06410bd 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2448,6 +2448,28 @@ static struct config_int ConfigureNamesInt[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"max_age_prepared_xacts", PGC_SIGHUP, LOGGING_WHEN,
+			gettext_noop("Sets the maximum age for a prepared transaciton after which vacuum starts complaining."),
+			NULL,
+			GUC_UNIT_MS
+		},
+		&max_age_prepared_xacts,
+		-1, -1, INT_MAX,
+		NULL, NULL, NULL
+	},
+
+	{
+		{"prepared_xacts_vacuum_warn_timeout", PGC_SIGHUP, LOGGING_WHEN,
+			gettext_noop("Timeout before vacuum throws a warning about overage prepared transactions."),
+			NULL,
+			GUC_UNIT_MS
+		},
+		&prepared_xacts_vacuum_warn_timeout,
+		-1, -1, INT_MAX,
+		NULL, NULL, NULL
+	},
+
 #ifdef LOCK_DEBUG
 	{
 		{"trace_lock_oidmin", PGC_SUSET, DEVELOPER_OPTIONS,
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index e58e478..7f2d71a 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -184,6 +184,11 @@
 					# (change requires restart)
 #backend_flush_after = 0		# measured in pages, 0 disables
 
+# - Prepared Transactions -
+
+#max_age_prepared_xacts = 6h			# 0ms - INT_MAX; default is -1 (disabled)
+#prepared_xacts_vacuum_warn_timeout = 6h	# 0ms - INT_MAX; default is -1 (disabled)
+
 
 #------------------------------------------------------------------------------
 # WRITE-AHEAD LOG
diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h
index 2ca71c3..5c685fd 100644
--- a/src/include/access/twophase.h
+++ b/src/include/access/twophase.h
@@ -27,6 +27,8 @@ typedef struct GlobalTransactionData *GlobalTransaction;
 
 /* GUC variable */
 extern PGDLLIMPORT int max_prepared_xacts;
+extern PGDLLIMPORT int max_age_prepared_xacts;
+extern PGDLLIMPORT int prepared_xacts_vacuum_warn_timeout;
 
 extern Size TwoPhaseShmemSize(void);
 extern void TwoPhaseShmemInit(void);
@@ -58,4 +60,6 @@ extern void PrepareRedoAdd(char *buf, XLogRecPtr start_lsn,
 						   XLogRecPtr end_lsn, RepOriginId origin_id);
 extern void PrepareRedoRemove(TransactionId xid, bool giveWarning);
 extern void restoreTwoPhaseData(void);
+
+extern int WarnOverAgedPreparedTransactions(bool force_warning);
 #endif							/* TWOPHASE_H */
