diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 6395a9b240..8f1bc3431a 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -314,6 +314,9 @@ typedef struct SubXactCallbackItem
 static SubXactCallbackItem *SubXact_callbacks = NULL;
 
 
+/* Hook for plugins to get control of at end of AbortCurrentTransaction */
+AbortCurrentTransaction_hook_type abort_current_transaction_hook = NULL;
+
 /* local function prototypes */
 static void AssignTransactionId(TransactionState s);
 static void AbortTransaction(void);
@@ -3382,6 +3385,9 @@ AbortCurrentTransaction(void)
 			AbortCurrentTransaction();
 			break;
 	}
+
+	if (abort_current_transaction_hook)
+		(*abort_current_transaction_hook) ();
 }
 
 /*
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 2b1b68109f..1f7382d182 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -205,6 +205,12 @@ static void log_disconnections(int code, Datum arg);
 static void enable_statement_timeout(void);
 static void disable_statement_timeout(void);
 
+/*
+ * Hooks for plugins to get control at end/start of
+ * start_xact_command()/finish_xact_command().
+ */
+XactCommandStart_hook_type start_xact_command_hook = NULL;
+XactCommandFinish_hook_type finish_xact_command_hook = NULL;
 
 /* ----------------------------------------------------------------
  *		routines to obtain user input
@@ -2671,8 +2677,16 @@ start_xact_command(void)
 	 * not desired, the timeout has to be disabled explicitly.
 	 */
 	enable_statement_timeout();
+
+	/*
+	 * Now give loadable modules a chance to execute code before a transaction
+	 * command is processed.
+	 */
+	if (start_xact_command_hook)
+		(*start_xact_command_hook) ();
 }
 
+
 static void
 finish_xact_command(void)
 {
@@ -2681,6 +2695,13 @@ finish_xact_command(void)
 
 	if (xact_started)
 	{
+		/*
+		 * Now give loadable modules a chance to execute code just before a
+		 * transaction command is committed.
+		 */
+		if (finish_xact_command_hook)
+			(*finish_xact_command_hook) ();
+
 		CommitTransactionCommand();
 
 #ifdef MEMORY_CONTEXT_CHECKING
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 34cfaf542c..6c1273bb44 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -482,4 +482,8 @@ IsModifySupportedInParallelMode(CmdType commandType)
 	return (commandType == CMD_INSERT);
 }
 
+/* Hook for plugins to get control in start_xact_command() and finish_xact_command() */
+typedef void (*AbortCurrentTransaction_hook_type) (void);
+extern PGDLLIMPORT AbortCurrentTransaction_hook_type abort_current_transaction_hook;
+
 #endif							/* XACT_H */
diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h
index ed2c4d374b..91c663358a 100644
--- a/src/include/tcop/pquery.h
+++ b/src/include/tcop/pquery.h
@@ -42,4 +42,10 @@ extern uint64 PortalRunFetch(Portal portal,
 							 long count,
 							 DestReceiver *dest);
 
+/* Hook for plugins to get control in start_xact_command() and finish_xact_command() */
+typedef void (*XactCommandStart_hook_type) (void);
+extern PGDLLIMPORT XactCommandStart_hook_type start_xact_command_hook;
+typedef void (*XactCommandFinish_hook_type) (void);
+extern PGDLLIMPORT XactCommandFinish_hook_type finish_xact_command_hook;
+
 #endif							/* PQUERY_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 1d1d5d2f0e..29cd5acbff 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -13,6 +13,7 @@ A_Expr_Kind
 A_Indices
 A_Indirection
 A_Star
+AbortCurrentTransaction_hook_type
 AbsoluteTime
 AccessMethodInfo
 AccessPriv
@@ -2821,6 +2822,8 @@ XPVIV
 XPVMG
 XactCallback
 XactCallbackItem
+XactCommandStart_hook_type
+XactCommandFinish_hook_type
 XactEvent
 XactLockTableWaitInfo
 XidBoundsViolation
