diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index fe8500d..14ab99e 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -636,6 +636,23 @@ pgfdw_report_error(int elevel, PGresult *res, PGconn *conn,
  * here and UUID extension which provides the function to generate UUID is
  * not part of the core.
  */
+extern char *
+postgresGetPrepareId(Oid serverid, Oid userid, int *prep_info_len)
+{
+/* Maximum length of the prepared transaction id, borrowed from twophase.c */
+#define PREP_XACT_ID_MAX_LEN 200
+#define RANDOM_LARGE_MULTIPLIER 1000
+	char	*prep_info;
+
+	/* Allocate the memory in the same context as the hash entry */
+	prep_info = (char *)palloc(PREP_XACT_ID_MAX_LEN * sizeof(char));
+	snprintf(prep_info, PREP_XACT_ID_MAX_LEN, "%s_%4d_%d_%d",
+								"px", abs(random() * RANDOM_LARGE_MULTIPLIER),
+								serverid, userid);
+	/* Account for the last NULL byte */
+	*prep_info_len = strlen(prep_info);
+	return prep_info;
+}
 
 /*
  * postgresPrepareForeignTransaction
@@ -644,7 +661,7 @@ pgfdw_report_error(int elevel, PGresult *res, PGconn *conn,
  */
 bool
 postgresPrepareForeignTransaction(Oid serverid, Oid userid, Oid umid,
-								  char *prep_info)
+								  int prep_info_len, char *prep_info)
 {
 	StringInfo		command;
 	PGresult		*res;
@@ -664,7 +681,8 @@ postgresPrepareForeignTransaction(Oid serverid, Oid userid, Oid umid,
 		PGconn	*conn = entry->conn;
 
 		command = makeStringInfo();
-		appendStringInfo(command, "PREPARE TRANSACTION '%s'", prep_info);
+		appendStringInfo(command, "PREPARE TRANSACTION '%.*s'", prep_info_len,
+																	prep_info);
 		res = PQexec(conn, command->data);
 		result = (PQresultStatus(res) == PGRES_COMMAND_OK);
 
@@ -738,7 +756,8 @@ postgresEndForeignTransaction(Oid serverid, Oid userid, Oid umid, bool is_commit
  */
 bool
 postgresResolvePreparedForeignTransaction(Oid serverid, Oid userid, Oid umid,
-										  bool is_commit, char *prep_info)
+										  bool is_commit,
+										  int prep_info_len, char *prep_info)
 {
 	PGconn			*conn = NULL;
 
@@ -777,9 +796,9 @@ postgresResolvePreparedForeignTransaction(Oid serverid, Oid userid, Oid umid,
 		bool			result;
 
 		command = makeStringInfo();
-		appendStringInfo(command, "%s PREPARED '%s'",
-						 is_commit ? "COMMIT" : "ROLLBACK",
-						 prep_info);
+		appendStringInfo(command, "%s PREPARED '%.*s'",
+							is_commit ? "COMMIT" : "ROLLBACK",
+							prep_info_len, prep_info);
 		res = PQexec(conn, command->data);
 
 		if (PQresultStatus(res) != PGRES_COMMAND_OK)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index ba6795a..88789a4 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -469,6 +469,7 @@ postgres_fdw_handler(PG_FUNCTION_ARGS)
 	routine->GetForeignJoinPaths = postgresGetForeignJoinPaths;
 
 	/* Support functions for foreign transactions */
+	routine->GetPrepareId = postgresGetPrepareId;
 	routine->PrepareForeignTransaction = postgresPrepareForeignTransaction;
 	routine->ResolvePreparedForeignTransaction = postgresResolvePreparedForeignTransaction;
 	routine->EndForeignTransaction = postgresEndForeignTransaction;
diff --git a/contrib/postgres_fdw/postgres_fdw.h b/contrib/postgres_fdw/postgres_fdw.h
index f256a92..721858e 100644
--- a/contrib/postgres_fdw/postgres_fdw.h
+++ b/contrib/postgres_fdw/postgres_fdw.h
@@ -179,11 +179,13 @@ extern void deparseSelectStmtForRel(StringInfo buf, PlannerInfo *root,
 						RelOptInfo *foreignrel, List *tlist,
 						List *remote_conds, List *pathkeys, bool is_subquery,
 						List **retrieved_attrs, List **params_list);
+extern char	*postgresGetPrepareId(Oid serveroid, Oid userid, int *prep_info_len);
 extern bool postgresPrepareForeignTransaction(Oid serverid, Oid userid,
-											  Oid umid, char *prep_info);
+											  Oid umid, int prep_info_len,
+											  char *prep_info);
 extern bool postgresResolvePreparedForeignTransaction(Oid serverid, Oid userid,
 													  Oid umid, bool is_commit,
-													  char *prep_info);
+													  int prep_info_len, char *prep_info);
 extern bool postgresEndForeignTransaction(Oid serverid, Oid userid, Oid umid, bool is_commit);
 
 /* in shippable.c */
diff --git a/src/backend/access/rmgrdesc/fdw_xactdesc.c b/src/backend/access/rmgrdesc/fdw_xactdesc.c
index 869faf7..fd4957c 100644
--- a/src/backend/access/rmgrdesc/fdw_xactdesc.c
+++ b/src/backend/access/rmgrdesc/fdw_xactdesc.c
@@ -38,7 +38,8 @@ fdw_xact_desc(StringInfo buf, XLogReaderState *record)
 		 * TODO: we also need to assess whether we want to add this
 		 * information
 		 */
-		appendStringInfo(buf, " foreign transaction info: %s",
+		appendStringInfo(buf, " foreign transaction info: ");
+		appendStringInfo(buf, "%.*s", fdw_insert_xlog->fdw_xact_id_len,
 						 fdw_insert_xlog->fdw_xact_id);
 	}
 	else
diff --git a/src/backend/access/transam/fdw_xact.c b/src/backend/access/transam/fdw_xact.c
index 90d11df..2b35f5f 100644
--- a/src/backend/access/transam/fdw_xact.c
+++ b/src/backend/access/transam/fdw_xact.c
@@ -109,6 +109,7 @@ typedef struct
 										 * protocol while committing
 										 * transaction on this server,
 										 * whenever necessary. */
+	GetPrepareId_function get_prepare_id;
 	EndForeignTransaction_function end_foreign_xact;
 	PrepareForeignTransaction_function prepare_foreign_xact;
 	ResolvePreparedForeignTransaction_function resolve_prepared_foreign_xact;
@@ -176,6 +177,11 @@ RegisterXactForeignServer(Oid serverid, Oid userid, bool two_phase_commit)
 					 errmsg("prepread foreign transactions are disabled"),
 					 errhint("Set max_prepared_foreign_transactions to a nonzero value.")));
 
+		if (!fdw_routine->GetPrepareId)
+			ereport(ERROR,
+					(errmsg("no prepared transaction identifier providing function for FDW %s",
+							fdw->fdwname)));
+
 		if (!fdw_routine->PrepareForeignTransaction)
 			ereport(ERROR,
 					(errmsg("no function provided for preparing foreign transaction for FDW %s",
@@ -196,6 +202,7 @@ RegisterXactForeignServer(Oid serverid, Oid userid, bool two_phase_commit)
 	 * system caches are not available. So save it before hand.
 	 */
 	fdw_conn->servername = foreign_server->servername;
+	fdw_conn->get_prepare_id = fdw_routine->GetPrepareId;
 	fdw_conn->prepare_foreign_xact = fdw_routine->PrepareForeignTransaction;
 	fdw_conn->resolve_prepared_foreign_xact = fdw_routine->ResolvePreparedForeignTransaction;
 	fdw_conn->end_foreign_xact = fdw_routine->EndForeignTransaction;
@@ -208,6 +215,9 @@ RegisterXactForeignServer(Oid serverid, Oid userid, bool two_phase_commit)
 	return;
 }
 
+/* Prepared transaction identifier can be maximum 256 bytes long */
+#define MAX_FDW_XACT_ID_LEN 256
+
 /* Enum to track the status of prepared foreign transaction */
 typedef enum
 {
@@ -250,8 +260,8 @@ typedef struct FDWXactData
 	BackendId	locking_backend;	/* Backend working on this entry */
 	bool		ondisk;			/* TRUE if prepare state file is on disk */
 	bool		inredo;			/* TRUE if entry was added via xlog_redo */
-	char		fdw_xact_id[FDW_XACT_ID_LEN];		/* prepared transaction
-														 * identifier */
+	int			fdw_xact_id_len;	/* Length of prepared transaction identifier */
+	char		fdw_xact_id[MAX_FDW_XACT_ID_LEN];	/* prepared transaction id */
 }	FDWXactData;
 
 /* Directory where the foreign prepared transaction files will reside */
@@ -264,7 +274,7 @@ typedef struct FDWXactData
 #define FDW_XACT_FILE_NAME_LEN (8 + 1 + 8 + 1 + 8)
 #define FDWXactFilePath(path, xid, serverid, userid)	\
 	snprintf(path, MAXPGPATH, FDW_XACTS_DIR "/%08X_%08X_%08X", xid, \
-			 serverid, userid)
+							serverid, userid)
 
 /* Shared memory layout for maintaining foreign prepared transaction entries. */
 typedef struct
@@ -283,12 +293,12 @@ static void AtProcExit_FDWXact(int code, Datum arg);
 static bool resolve_fdw_xact(FDWXact fdw_xact,
   ResolvePreparedForeignTransaction_function prepared_foreign_xact_resolver);
 static FDWXact insert_fdw_xact(Oid dboid, TransactionId xid, Oid serverid, Oid userid,
-							   Oid umid, char *fdw_xact_id);
+							   Oid umid, int fdw_xact_id_len, char *fdw_xact_id);
 static void unlock_fdw_xact(FDWXact fdw_xact);
 static void unlock_fdw_xact_entries();
 static void remove_fdw_xact(FDWXact fdw_xact);
 static FDWXact register_fdw_xact(Oid dbid, TransactionId xid, Oid serverid, Oid userid,
-				  Oid umid, char *fdw_xact_info);
+								 Oid umid, int fdw_xact_info_len, char *fdw_xact_info);
 static int	GetFDWXactList(FDWXact * fdw_xacts);
 static ResolvePreparedForeignTransaction_function get_prepared_foreign_xact_resolver(FDWXact fdw_xact);
 static FDWXactOnDiskData *ReadFDWXactFile(TransactionId xid, Oid serverid,
@@ -486,15 +496,17 @@ prepare_foreign_transactions(void)
 	foreach(lcell, MyFDWConnections)
 	{
 		FDWConnection *fdw_conn = (FDWConnection *) lfirst(lcell);
-		char	    fdw_xact_id[FDW_XACT_ID_LEN];
+		char	   *fdw_xact_id;
+		int			fdw_xact_id_len;
 		FDWXact		fdw_xact;
 
 		if (!fdw_conn->two_phase_commit)
 			continue;
 
-		/* Generate prepare transaction id for foreign server */
-		FDWXactId(fdw_xact_id, "px", GetTopTransactionId(),
-				  fdw_conn->serverid, fdw_conn->userid);
+		Assert(fdw_conn->get_prepare_id);
+		fdw_xact_id = fdw_conn->get_prepare_id(fdw_conn->serverid,
+											   fdw_conn->userid,
+											   &fdw_xact_id_len);
 
 		/*
 		 * Register the foreign transaction with the identifier used to
@@ -518,7 +530,8 @@ prepare_foreign_transactions(void)
 		 */
 		fdw_xact = register_fdw_xact(MyDatabaseId, GetTopTransactionId(),
 									 fdw_conn->serverid, fdw_conn->userid,
-									 fdw_conn->umid, fdw_xact_id);
+									 fdw_conn->umid, fdw_xact_id_len,
+									 fdw_xact_id);
 
 		/*
 		 * Between register_fdw_xact call above till this backend hears back
@@ -531,7 +544,8 @@ prepare_foreign_transactions(void)
 		 * resolved by the foreign transaction resolver.
 		 */
 		if (!fdw_conn->prepare_foreign_xact(fdw_conn->serverid, fdw_conn->userid,
-											fdw_conn->umid, fdw_xact_id))
+											fdw_conn->umid, fdw_xact_id_len,
+											fdw_xact_id))
 		{
 			/*
 			 * An error occurred, and we didn't prepare the transaction.
@@ -573,7 +587,7 @@ prepare_foreign_transactions(void)
  */
 static FDWXact
 register_fdw_xact(Oid dbid, TransactionId xid, Oid serverid, Oid userid,
-				  Oid umid, char *fdw_xact_id)
+				  Oid umid, int fdw_xact_id_len, char *fdw_xact_id)
 {
 	FDWXact		fdw_xact;
 	FDWXactOnDiskData *fdw_xact_file_data;
@@ -582,7 +596,7 @@ register_fdw_xact(Oid dbid, TransactionId xid, Oid serverid, Oid userid,
 	/* Enter the foreign transaction in the shared memory structure */
 	LWLockAcquire(FDWXactLock, LW_EXCLUSIVE);
 	fdw_xact = insert_fdw_xact(dbid, xid, serverid, userid, umid,
-							   fdw_xact_id);
+							   fdw_xact_id_len, fdw_xact_id);
 	fdw_xact->status = FDW_XACT_PREPARING;
 	fdw_xact->locking_backend = MyBackendId;
 	LWLockRelease(FDWXactLock);
@@ -595,7 +609,7 @@ register_fdw_xact(Oid dbid, TransactionId xid, Oid serverid, Oid userid,
 	 * of the xlog record are same as what is written to the file.
 	 */
 	data_len = offsetof(FDWXactOnDiskData, fdw_xact_id);
-	data_len = data_len + FDW_XACT_ID_LEN;
+	data_len = data_len + fdw_xact->fdw_xact_id_len;
 	data_len = MAXALIGN(data_len);
 	fdw_xact_file_data = (FDWXactOnDiskData *) palloc0(data_len);
 	fdw_xact_file_data->dboid = fdw_xact->dboid;
@@ -603,8 +617,9 @@ register_fdw_xact(Oid dbid, TransactionId xid, Oid serverid, Oid userid,
 	fdw_xact_file_data->serverid = fdw_xact->serverid;
 	fdw_xact_file_data->userid = fdw_xact->userid;
 	fdw_xact_file_data->umid = fdw_xact->umid;
+	fdw_xact_file_data->fdw_xact_id_len = fdw_xact->fdw_xact_id_len;
 	memcpy(fdw_xact_file_data->fdw_xact_id, fdw_xact->fdw_xact_id,
-		   FDW_XACT_ID_LEN);
+		   fdw_xact->fdw_xact_id_len);
 
 	START_CRIT_SECTION();
 
@@ -637,7 +652,7 @@ register_fdw_xact(Oid dbid, TransactionId xid, Oid serverid, Oid userid,
  */
 static FDWXact
 insert_fdw_xact(Oid dboid, TransactionId xid, Oid serverid, Oid userid, Oid umid,
-				char *fdw_xact_id)
+				int fdw_xact_id_len, char *fdw_xact_id)
 {
 	int i;
 	FDWXact fdw_xact;
@@ -648,6 +663,10 @@ insert_fdw_xact(Oid dboid, TransactionId xid, Oid serverid, Oid userid, Oid umid
 		fdwXactExitRegistered = true;
 	}
 
+	if (fdw_xact_id_len > MAX_FDW_XACT_ID_LEN)
+		elog(ERROR, "foreign transaction identifier longer (%d) than allowed (%d)",
+			 fdw_xact_id_len, MAX_FDW_XACT_ID_LEN);
+
 	/* Check for duplicating foreign transaction entry */
 	for (i = 0; i < FDWXactGlobal->numFDWXacts; i++)
 	{
@@ -691,7 +710,8 @@ insert_fdw_xact(Oid dboid, TransactionId xid, Oid serverid, Oid userid, Oid umid
 	fdw_xact->valid = false;
 	fdw_xact->ondisk = false;
 	fdw_xact->inredo = false;
-	memcpy(fdw_xact->fdw_xact_id, fdw_xact_id, FDW_XACT_ID_LEN);
+	fdw_xact->fdw_xact_id_len = fdw_xact_id_len;
+	memcpy(fdw_xact->fdw_xact_id, fdw_xact_id, fdw_xact_id_len);
 
 	return fdw_xact;
 }
@@ -1030,6 +1050,7 @@ resolve_fdw_xact(FDWXact fdw_xact,
 
 	resolved = fdw_xact_handler(fdw_xact->serverid, fdw_xact->userid,
 								fdw_xact->umid, is_commit,
+								fdw_xact->fdw_xact_id_len,
 								fdw_xact->fdw_xact_id);
 
 	/* If we succeeded in resolving the transaction, remove the entry */
@@ -1560,7 +1581,7 @@ pg_fdw_xacts(PG_FUNCTION_ARGS)
 		values[4] = CStringGetTextDatum(xact_status);
 		/* should this be really interpreted by FDW */
 		values[5] = PointerGetDatum(cstring_to_text_with_len(fdw_xact->fdw_xact_id,
-												 FDW_XACT_ID_LEN));
+												 fdw_xact->fdw_xact_id_len));
 
 		tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
 		result = HeapTupleGetDatum(tuple);
@@ -1786,7 +1807,7 @@ pg_fdw_xact_resolve(PG_FUNCTION_ARGS)
 		values[4] = CStringGetTextDatum(xact_status);
 		/* should this be really interpreted by FDW? */
 		values[5] = PointerGetDatum(cstring_to_text_with_len(fdw_xact->fdw_xact_id,
-															 FDW_XACT_ID_LEN));
+												 fdw_xact->fdw_xact_id_len));
 
 		tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
 		result = HeapTupleGetDatum(tuple);
@@ -2083,6 +2104,7 @@ RecoverFDWXacts(void)
 				fdw_xact = insert_fdw_xact(fdw_xact_file_data->dboid, local_xid,
 										   serverid, userid,
 										   fdw_xact_file_data->umid,
+										   fdw_xact_file_data->fdw_xact_id_len,
 										   fdw_xact_file_data->fdw_xact_id);
 				fdw_xact->locking_backend = MyBackendId;
 				fdw_xact->status = FDW_XACT_PREPARING;
@@ -2142,7 +2164,8 @@ FDWXactRedoAdd(XLogReaderState *record)
 	LWLockAcquire(FDWXactLock, LW_EXCLUSIVE);
 	fdw_xact = insert_fdw_xact(fdw_xact_data->dboid, fdw_xact_data->local_xid,
 							   fdw_xact_data->serverid, fdw_xact_data->userid,
-							   fdw_xact_data->umid, fdw_xact_data->fdw_xact_id);
+							   fdw_xact_data->umid, fdw_xact_data->fdw_xact_id_len,
+							   fdw_xact_data->fdw_xact_id);
 	fdw_xact->status = FDW_XACT_PREPARING;
 	fdw_xact->fdw_xact_start_lsn = record->ReadRecPtr;
 	fdw_xact->fdw_xact_end_lsn = record->EndRecPtr;
diff --git a/src/include/access/fdw_xact.h b/src/include/access/fdw_xact.h
index 0b470b4..69b74af 100644
--- a/src/include/access/fdw_xact.h
+++ b/src/include/access/fdw_xact.h
@@ -16,11 +16,6 @@
 #include "lib/stringinfo.h"
 #include "nodes/pg_list.h"
 
-#define FDW_XACT_ID_LEN (2 + 1 + 8 + 1 + 8 + 1 + 8)
-#define FDWXactId(path, prefix, xid, serverid, userid)	\
-	snprintf((path), FDW_XACT_ID_LEN + 1, "%s_%08X_%08X_%08X", (prefix), \
-			 (xid), (serverid), (userid))
-
 /*
  * On disk file structure
  */
@@ -33,7 +28,13 @@ typedef struct
 								 * place */
 	Oid			userid;			/* user who initiated the foreign transaction */
 	Oid			umid;
-	char		fdw_xact_id[FDW_XACT_ID_LEN]; /* foreign txn prepare id */
+	uint32		fdw_xact_id_len;/* Length of the value stored in the next
+								 * field */
+	/* This should always be the last member */
+	char		fdw_xact_id[FLEXIBLE_ARRAY_MEMBER];		/* variable length array
+														 * to store foreign
+														 * transaction
+														 * information. */
 }	FDWXactOnDiskData;
 
 typedef struct
diff --git a/src/include/foreign/fdwapi.h b/src/include/foreign/fdwapi.h
index 7b95f77..fdb7b19 100644
--- a/src/include/foreign/fdwapi.h
+++ b/src/include/foreign/fdwapi.h
@@ -148,14 +148,20 @@ typedef bool (*EndForeignTransaction_function) (Oid serverid, Oid userid,
 												Oid umid, bool is_commit);
 
 typedef bool (*PrepareForeignTransaction_function) (Oid serverid, Oid userid,
-													Oid umid, char *prep_info);
+													Oid umid, int prep_info_len,
+													char *prep_info);
 
 typedef bool (*ResolvePreparedForeignTransaction_function) (Oid serverid,
 															Oid userid,
 															Oid umid,
 															bool is_commit,
+															int prep_info_len,
 															char *prep_info);
 
+typedef char *(*GetPrepareId_function) (Oid serverid, Oid userid,
+														int *prep_info_len);
+
+
 typedef Size (*EstimateDSMForeignScan_function) (ForeignScanState *node,
 													  ParallelContext *pcxt);
 typedef void (*InitializeDSMForeignScan_function) (ForeignScanState *node,
@@ -234,6 +240,7 @@ typedef struct FdwRoutine
 	ImportForeignSchema_function ImportForeignSchema;
 
 	/* Support functions for foreign transactions */
+	GetPrepareId_function GetPrepareId;
 	EndForeignTransaction_function EndForeignTransaction;
 	PrepareForeignTransaction_function PrepareForeignTransaction;
 	ResolvePreparedForeignTransaction_function ResolvePreparedForeignTransaction;
