diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c
index cea84ee..4171213 100644
--- a/contrib/pg_stat_statements/pg_stat_statements.c
+++ b/contrib/pg_stat_statements/pg_stat_statements.c
@@ -404,7 +404,7 @@ _PG_init(void)
 	 * resources in pgss_shmem_startup().
 	 */
 	RequestAddinShmemSpace(pgss_memsize());
-	RequestAddinLWLocks(1);
+	RequestAddinLWLockTranche("pg_stat_statements locks", 1);
 
 	/*
 	 * Install hooks.
@@ -480,7 +480,7 @@ pgss_shmem_startup(void)
 	if (!found)
 	{
 		/* First time through ... */
-		pgss->lock = LWLockAssign();
+		pgss->lock = LWLockAssignFromTranche("pg_stat_statements locks");
 		pgss->cur_median_usage = ASSUMED_MEDIAN_INIT;
 		pgss->mean_query_len = ASSUMED_LENGTH_INIT;
 		SpinLockInit(&pgss->mutex);
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 3cba0e5..bc9d55f 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -481,6 +481,8 @@ typedef struct
 #ifndef HAVE_SPINLOCKS
 	PGSemaphore SpinlockSemaArray;
 #endif
+	int			LWLockTrancheRequestsCount;
+	LWLockLMTranche *LWLockLMTrancheArray;
 	LWLockPadded *MainLWLockArray;
 	slock_t    *ProcStructLock;
 	PROC_HDR   *ProcGlobal;
@@ -5772,6 +5774,8 @@ save_backend_variables(BackendParameters *param, Port *port,
 #ifndef HAVE_SPINLOCKS
 	param->SpinlockSemaArray = SpinlockSemaArray;
 #endif
+	param->LWLockTrancheRequestsCount = LWLockTrancheRequestsCount;
+	param->LWLockLMTrancheArray = LWLockLMTrancheArray;
 	param->MainLWLockArray = MainLWLockArray;
 	param->ProcStructLock = ProcStructLock;
 	param->ProcGlobal = ProcGlobal;
@@ -6003,6 +6007,8 @@ restore_backend_variables(BackendParameters *param, Port *port)
 #ifndef HAVE_SPINLOCKS
 	SpinlockSemaArray = param->SpinlockSemaArray;
 #endif
+	LWLockTrancheRequestsCount = param->LWLockTrancheRequestsCount;
+	LWLockLMTrancheArray = param->LWLockLMTrancheArray;
 	MainLWLockArray = param->MainLWLockArray;
 	ProcStructLock = param->ProcStructLock;
 	ProcGlobal = param->ProcGlobal;
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 32ac58f..d105c93 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -125,6 +125,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 		size = add_size(size, BackgroundWorkerShmemSize());
 		size = add_size(size, MultiXactShmemSize());
 		size = add_size(size, LWLockShmemSize());
+		size = add_size(size, LWLockLMTrancheShmemSize());
 		size = add_size(size, ProcArrayShmemSize());
 		size = add_size(size, BackendStatusShmemSize());
 		size = add_size(size, SInvalShmemSize());
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index d43fb61..4f264b0 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -144,7 +144,20 @@ typedef struct LWLockHandle
 static int	num_held_lwlocks = 0;
 static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS];
 
-static int	lock_addin_request = 0;
+/* struct representing the LWLock tranche request by loadable module */
+typedef struct LWLockTrancheRequest
+{
+	char		tranche_name[NAMEDATALEN];
+	int			num_lwlocks;
+	int			num_lwlocks_allocated;
+} LWLockTrancheRequest;
+
+LWLockTrancheRequest *LWLockTrancheRequestArray = NULL;
+static int	LWLockTrancheRequestsAllocated = 0;
+int			LWLockTrancheRequestsCount = 0;
+
+LWLockLMTranche *LWLockLMTrancheArray = NULL;
+
 static bool lock_addin_request_allowed = true;
 
 #ifdef LWLOCK_STATS
@@ -336,6 +349,22 @@ get_lwlock_stats_entry(LWLock *lock)
 
 
 /*
+ * Compute number of LWLocks required by loadable modules to be allocated
+ * in the main array.
+ */
+static int
+NumLWLocksByLoadableModules(void)
+{
+	int			numLocks = 0;
+	int			i;
+
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+		numLocks += LWLockTrancheRequestArray[i].num_lwlocks;
+
+	return numLocks;
+}
+
+/*
  * Compute number of LWLocks to allocate in the main array.
  */
 static int
@@ -360,37 +389,15 @@ NumLWLocks(void)
 	numLocks += max_replication_slots;
 
 	/*
-	 * Add any requested by loadable modules; for backwards-compatibility
-	 * reasons, allocate at least NUM_USER_DEFINED_LWLOCKS of them even if
-	 * there are no explicit requests.
+	 * for backwards-compatibility reasons, allocate NUM_USER_DEFINED_LWLOCKS
+	 * for use by extensions that want to get the LWLock after startup.
 	 */
 	lock_addin_request_allowed = false;
-	numLocks += Max(lock_addin_request, NUM_USER_DEFINED_LWLOCKS);
+	numLocks += NUM_USER_DEFINED_LWLOCKS;
 
 	return numLocks;
 }
 
-
-/*
- * RequestAddinLWLocks
- *		Request that extra LWLocks be allocated for use by
- *		a loadable module.
- *
- * This is only useful if called from the _PG_init hook of a library that
- * is loaded into the postmaster via shared_preload_libraries.  Once
- * shared memory has been allocated, calls will be ignored.  (We could
- * raise an error, but it seems better to make it a no-op, so that
- * libraries containing such calls can be reloaded if needed.)
- */
-void
-RequestAddinLWLocks(int n)
-{
-	if (IsUnderPostmaster || !lock_addin_request_allowed)
-		return;					/* too late */
-	lock_addin_request += n;
-}
-
-
 /*
  * Compute shmem space needed for LWLocks.
  */
@@ -400,6 +407,8 @@ LWLockShmemSize(void)
 	Size		size;
 	int			numLocks = NumLWLocks();
 
+	numLocks += NumLWLocksByLoadableModules();
+
 	/* Space for the LWLock array. */
 	size = mul_size(numLocks, sizeof(LWLockPadded));
 
@@ -409,6 +418,24 @@ LWLockShmemSize(void)
 	return size;
 }
 
+/*
+ * Compute shmem space needed for tranches requested by loadable modules.
+ */
+Size
+LWLockLMTrancheShmemSize(void)
+{
+	Size		size;
+	int			i;
+
+	/* space for tranches requested by extensions. */
+	size = mul_size(LWLockTrancheRequestsCount, sizeof(LWLockLMTranche));
+
+	/* space for name of each tranche. */
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+		size = add_size(size, strlen(LWLockTrancheRequestArray[i].tranche_name) + 1);
+
+	return size;
+}
 
 /*
  * Allocate shmem space for the main LWLock array and initialize it.  We also
@@ -417,6 +444,8 @@ LWLockShmemSize(void)
 void
 CreateLWLocks(void)
 {
+	int			i;
+
 	StaticAssertExpr(LW_VAL_EXCLUSIVE > (uint32) MAX_BACKENDS,
 					 "MAX_BACKENDS too big for lwlock.c");
 
@@ -432,6 +461,7 @@ CreateLWLocks(void)
 		int		   *LWLockCounter;
 		char	   *ptr;
 		int			id;
+		int			j;
 
 		/* Allocate space */
 		ptr = (char *) ShmemAlloc(spaceLocks);
@@ -444,7 +474,7 @@ CreateLWLocks(void)
 
 		MainLWLockArray = (LWLockPadded *) ptr;
 
-		/* Initialize all LWLocks in main array */
+		/* Initialize all fixed LWLocks in main array */
 		for (id = 0, lock = MainLWLockArray; id < numLocks; id++, lock++)
 			LWLockInitialize(&lock->lock, LWTRANCHE_MAIN);
 
@@ -459,6 +489,57 @@ CreateLWLocks(void)
 		LWLockCounter[0] = NUM_FIXED_LWLOCKS;
 		LWLockCounter[1] = numLocks;
 		LWLockCounter[2] = LWTRANCHE_FIRST_USER_DEFINED;
+
+		/* Allocate and initialize separate tranche for each loadable module. */
+		if (LWLockTrancheRequestsCount > 0)
+		{
+			Size		spaceTranche = LWLockLMTrancheShmemSize();
+			char	   *ptr;
+			char	   *trancheNames;
+
+			ptr = (char *) ShmemAlloc(spaceTranche);
+
+			LWLockLMTrancheArray = (LWLockLMTranche *) ptr;
+
+			trancheNames = (char *) LWLockLMTrancheArray + (LWLockTrancheRequestsCount * sizeof(LWLockLMTranche));
+
+			/*
+			 * Ensure tranche names point to the shared memory location
+			 * allocated for them.
+			 */
+			i = 0;
+			do
+			{
+				LWLockLMTrancheArray[i].lwlockTranche.name = (char *) trancheNames;
+				trancheNames += strlen(LWLockTrancheRequestArray[i].tranche_name) + 1;
+			} while (++i < LWLockTrancheRequestsCount);
+
+			/* Initialize the tranches requested by loadable modules. */
+			i = 0;
+			lock = MainLWLockArray + numLocks;
+			do
+			{
+				LWLockLMTrancheArray[i].trancheId = LWLockNewTrancheId();
+				StrNCpy((char *) LWLockLMTrancheArray[i].lwlockTranche.name,
+						LWLockTrancheRequestArray[i].tranche_name,
+					  strlen(LWLockTrancheRequestArray[i].tranche_name) + 1);
+				LWLockLMTrancheArray[i].lwlockTranche.array_base = lock;
+				LWLockLMTrancheArray[i].lwlockTranche.array_stride = sizeof(LWLockPadded);
+
+				lock += LWLockTrancheRequestArray[i].num_lwlocks;
+			} while (++i < LWLockTrancheRequestsCount);
+
+			/*
+			 * Initialize the LWLocks in the main array that belong to
+			 * loadable modules.
+			 */
+			lock = MainLWLockArray + numLocks;
+			for (i = 0; i < LWLockTrancheRequestsCount; i++)
+			{
+				for (j = 0; j < LWLockTrancheRequestArray[i].num_lwlocks; j++, lock++)
+					LWLockInitialize(&lock->lock, LWLockLMTrancheArray[i].trancheId);
+			}
+		}
 	}
 
 	if (LWLockTrancheArray == NULL)
@@ -474,6 +555,11 @@ CreateLWLocks(void)
 	MainLWLockTranche.array_base = MainLWLockArray;
 	MainLWLockTranche.array_stride = sizeof(LWLockPadded);
 	LWLockRegisterTranche(LWTRANCHE_MAIN, &MainLWLockTranche);
+
+	/* Register separate tranche for loadable modules. */
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+		LWLockRegisterTranche(LWLockLMTrancheArray[i].trancheId,
+							  &LWLockLMTrancheArray[i].lwlockTranche);
 }
 
 /*
@@ -514,6 +600,57 @@ LWLockAssign(void)
 }
 
 /*
+ * LWLockAssignFromTranche - assign a LWLock from the specified tranche
+ *
+ * This can be used for tranches that are requested by using
+ * RequestAddinLWLockTranche() API and it ensures that no more than
+ * requested number of LWLocks can be assigned from a specified tranche.
+ */
+LWLock *
+LWLockAssignFromTranche(const char *tranche_name)
+{
+	int			lock_pos;
+	int			i,
+				j;
+	LWLock	   *result;
+	LWLockTrancheRequest *request_tranche;
+	int		   *LWLockCounter;
+
+	LWLockCounter = (int *) ((char *) MainLWLockArray - 3 * sizeof(int));
+
+	for (i = 0; i < LWLockTrancheRequestsCount; i++)
+	{
+		if (strcmp(tranche_name, LWLockTrancheRequestArray[i].tranche_name) == 0)
+		{
+			request_tranche = &LWLockTrancheRequestArray[i];
+			break;
+		}
+	}
+
+	if (i >= LWLockTrancheRequestsCount)
+		elog(ERROR, "requested tranche is not registered");
+
+	if (request_tranche->num_lwlocks_allocated >= request_tranche->num_lwlocks)
+		elog(ERROR, "no more LWLocks available in tranche %s",
+			 request_tranche->tranche_name);
+
+	/*
+	 * Obtain the position of lock belonging to this tranche in
+	 * MainLWLockArray.  Locks for loadable modules tranche are placed in
+	 * MainLWLockArray after locks specified by LWLockCounter[1].
+	 */
+	lock_pos = LWLockCounter[1];
+	for (j = 0; j < i; j++)
+		lock_pos += LWLockTrancheRequestArray[j].num_lwlocks;
+	lock_pos += request_tranche->num_lwlocks_allocated;
+
+	result = &MainLWLockArray[lock_pos].lock;
+	request_tranche->num_lwlocks_allocated++;
+
+	return result;
+}
+
+/*
  * Allocate a new tranche ID.
  */
 int
@@ -558,6 +695,49 @@ LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
 }
 
 /*
+ * RequestAddinLWLockTranche
+ *		Request that extra LWLocks be allocated for use by
+ *		a loadable module.
+ *
+ * This is only useful if called from the _PG_init hook of a library that
+ * is loaded into the postmaster via shared_preload_libraries.  Once
+ * shared memory has been allocated, calls will be ignored.  (We could
+ * raise an error, but it seems better to make it a no-op, so that
+ * libraries containing such calls can be reloaded if needed.)
+ */
+void
+RequestAddinLWLockTranche(const char *tranche_name, int num_lwlocks)
+{
+	if (IsUnderPostmaster || !lock_addin_request_allowed)
+		return;					/* too late */
+
+	if (LWLockTrancheRequestArray == NULL)
+	{
+		LWLockTrancheRequestsAllocated = 16;
+		LWLockTrancheRequestArray = (LWLockTrancheRequest *)
+			MemoryContextAlloc(TopMemoryContext,
+			  LWLockTrancheRequestsAllocated * sizeof(LWLockTrancheRequest));
+	}
+
+	if (LWLockTrancheRequestsCount >= LWLockTrancheRequestsAllocated)
+	{
+		int			i = LWLockTrancheRequestsAllocated;
+
+		while (i <= LWLockTrancheRequestsCount)
+			i *= 2;
+
+		LWLockTrancheRequestArray = (LWLockTrancheRequest *)
+			repalloc(LWLockTrancheRequestArray,
+					 i * sizeof(LWLockTrancheRequest));
+		LWLockTrancheRequestsAllocated = i;
+	}
+
+	StrNCpy(LWLockTrancheRequestArray[LWLockTrancheRequestsCount].tranche_name, tranche_name, strlen(tranche_name) + 1);
+	LWLockTrancheRequestArray[LWLockTrancheRequestsCount].num_lwlocks_allocated = 0;
+	LWLockTrancheRequestArray[LWLockTrancheRequestsCount++].num_lwlocks = num_lwlocks;
+}
+
+/*
  * LWLockInitialize - initialize a new lwlock; it's initially unlocked
  */
 void
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index ff34529..9c6f465 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -119,6 +119,16 @@ typedef union LWLockMinimallyPadded
 extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
 extern char *MainLWLockNames[];
 
+/* struct for storing tranche information of loadable modules (extensions) */
+typedef struct LWLockLMTranche
+{
+	LWLockTranche lwlockTranche;
+	int			trancheId;
+} LWLockLMTranche;
+
+extern PGDLLIMPORT LWLockLMTranche *LWLockLMTrancheArray;
+extern PGDLLIMPORT int LWLockTrancheRequestsCount;
+
 /* Names for fixed lwlocks */
 #include "storage/lwlocknames.h"
 
@@ -178,12 +188,22 @@ extern void CreateLWLocks(void);
 extern void InitLWLockAccess(void);
 
 /*
- * The traditional method for obtaining an lwlock for use by an extension is
- * to call RequestAddinLWLocks() during postmaster startup; this will reserve
+ * The method for obtaining an lwlock for use by an extension is to call
+ * RequestAddinLWLockTranche() during postmaster startup; this will reserve
  * space for the indicated number of locks in MainLWLockArray.  Subsequently,
- * a lock can be allocated using LWLockAssign.
+ * a lock can be allocated using LWLockAssignFromTranche.  This method ensures
+ * that no more than requested number of LWLocks can be assigned from a
+ * particular tranche.
+ */
+extern void RequestAddinLWLockTranche(const char *tranche_name, int num_lwlocks);
+extern LWLock *LWLockAssignFromTranche(const char *tranche_name);
+extern Size LWLockLMTrancheShmemSize(void);
+
+/*
+ * During postmaster startup, we reserve space for NUM_USER_DEFINED_LWLOCKS
+ * LWLocks in MainLWLockArray. Users can use allocate these locks after
+ * startup using LWLockAssign.
  */
-extern void RequestAddinLWLocks(int n);
 extern LWLock *LWLockAssign(void);
 
 /*
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 963d865..2faa1b8 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1008,10 +1008,12 @@ LSEG
 LVRelStats
 LWLock
 LWLockHandle
+LWLockLMTranche
 LWLockMinimallyPadded
 LWLockMode
 LWLockPadded
 LWLockTranche
+LWLockTrancheRequest
 LabelProvider
 LargeObjectDesc
 Latch
