diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index f8b939853e9..f4ad7b98400 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -129,6 +129,7 @@ bool		EnableHotStandby = false;
 bool		fullPageWrites = true;
 bool		wal_log_hints = false;
 int			wal_compression = WAL_COMPRESSION_NONE;
+int			wal_compression_level = -1;
 char	   *wal_consistency_checking_string = NULL;
 bool	   *wal_consistency_checking = NULL;
 bool		wal_init_zero = true;
diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c
index f2e10b82b7d..fb42f9684e2 100644
--- a/src/backend/access/transam/xloginsert.c
+++ b/src/backend/access/transam/xloginsert.c
@@ -1053,8 +1053,20 @@ XLogCompressBackupBlock(const PageData *page, uint16 hole_offset, uint16 hole_le
 
 		case WAL_COMPRESSION_LZ4:
 #ifdef USE_LZ4
-			len = LZ4_compress_default(source, dest, orig_len,
-									   COMPRESS_BUFSIZE);
+
+			/* LZ4 default compression level is 1 */
+			if (wal_compression_level == -1)
+				wal_compression_level = 1;
+
+			/*
+			 * LZ4 has compression level 1-65537, but we cap it as 22, same
+			 * as zstd (good enough for our testing)
+			 */
+			wal_compression_level = Max(1, Min(100, wal_compression_level));
+
+			len = LZ4_compress_fast(source, dest, orig_len,
+									COMPRESS_BUFSIZE,
+									wal_compression_level);
 			if (len <= 0)
 				len = -1;		/* failure */
 #else
@@ -1064,8 +1076,15 @@ XLogCompressBackupBlock(const PageData *page, uint16 hole_offset, uint16 hole_le
 
 		case WAL_COMPRESSION_ZSTD:
 #ifdef USE_ZSTD
+			/* ZSTD default compression level is 3 */
+			if (wal_compression_level == -1)
+				wal_compression_level = 3;
+
+			/* ZSTD has compression level 1-22 */
+			wal_compression_level = Max(1, Min(22, wal_compression_level));
+
 			len = ZSTD_compress(dest, COMPRESS_BUFSIZE, source, orig_len,
-								ZSTD_CLEVEL_DEFAULT);
+								wal_compression_level);
 			if (ZSTD_isError(len))
 				len = -1;		/* failure */
 #else
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index adb72361ce0..505c7d1627b 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -3464,6 +3464,14 @@
   options => 'wal_compression_options',
 },
 
+{ name => 'wal_compression_level', type => 'int', context => 'PGC_SUSET', group => 'WAL_SETTINGS',
+  short_desc => 'compression level for wal_compression zstd/lz4',
+  variable => 'wal_compression_level',
+  boot_val => '-1',
+  min => '-1',
+  max => '100',
+},
+
 { name => 'wal_consistency_checking', type => 'string', context => 'PGC_SUSET', group => 'DEVELOPER_OPTIONS',
   short_desc => 'Sets the WAL resource managers for which WAL consistency checks are done.',
   long_desc => 'Full-page images will be logged for all data blocks and cross-checked against the results of WAL replay.',
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index 4dd98624204..3949bf3fa8c 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -48,6 +48,7 @@ extern PGDLLIMPORT bool EnableHotStandby;
 extern PGDLLIMPORT bool fullPageWrites;
 extern PGDLLIMPORT bool wal_log_hints;
 extern PGDLLIMPORT int wal_compression;
+extern PGDLLIMPORT int wal_compression_level;
 extern PGDLLIMPORT bool wal_init_zero;
 extern PGDLLIMPORT bool wal_recycle;
 extern PGDLLIMPORT bool *wal_consistency_checking;
