From a00ae3c2634b2d53d8d3181cc5f047eb6f356927 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Mon, 24 Feb 2025 19:30:39 +1300
Subject: [PATCH v2 5/5] Remove historical slashes from LSN format.

Ancient versions had a two-part XLogRecPtr where the parts had a
semantic meaning, and that was reflected in the display format.  Now
it's just a 64 bit number, so lets display it that way and remove most
remaining conversions to and from two-part form.

Unfortunately we can't defined a macro like LSN_FORMAT if we want
messages to be translatable.  Open-code formatting using <inttypes.h>
macros that the localization software understands.

XXX pg_upgrade probably needs to understand old format LSNs
---
 contrib/amcheck/verify_nbtree.c               |  88 +++---
 contrib/pageinspect/expected/gist.out         |  18 +-
 contrib/pageinspect/expected/page.out         |   6 +-
 contrib/pageinspect/rawpage.c                 |   2 +-
 .../pg_walinspect/expected/pg_walinspect.out  |   8 +-
 contrib/pg_walinspect/pg_walinspect.c         |  38 +--
 contrib/test_decoding/expected/replorigin.out |  14 +-
 doc/src/sgml/catalogs.sgml                    |   2 +-
 doc/src/sgml/datatype.sgml                    |  17 +-
 doc/src/sgml/logical-replication.sgml         |  26 +-
 doc/src/sgml/logicaldecoding.sgml             |  94 +++----
 doc/src/sgml/pageinspect.sgml                 |  12 +-
 doc/src/sgml/pglogicalinspect.sgml            |  16 +-
 doc/src/sgml/pgwalinspect.sgml                |  26 +-
 doc/src/sgml/protocol.sgml                    |  10 +-
 doc/src/sgml/test-decoding.sgml               |  44 +--
 src/backend/access/heap/rewriteheap.c         |  12 +-
 src/backend/access/rmgrdesc/replorigindesc.c  |   4 +-
 src/backend/access/rmgrdesc/xactdesc.c        |  12 +-
 src/backend/access/rmgrdesc/xlogdesc.c        |  10 +-
 src/backend/access/transam/timeline.c         |  13 +-
 src/backend/access/transam/twophase.c         |  16 +-
 src/backend/access/transam/xlog.c             | 109 ++++----
 src/backend/access/transam/xlogbackup.c       |  16 +-
 src/backend/access/transam/xlogprefetcher.c   |  35 +--
 src/backend/access/transam/xlogreader.c       | 139 +++++-----
 src/backend/access/transam/xlogrecovery.c     | 172 ++++++------
 src/backend/access/transam/xlogutils.c        |   4 +-
 src/backend/backup/backup_manifest.c          |   6 +-
 src/backend/backup/basebackup_copy.c          |   2 +-
 src/backend/backup/basebackup_incremental.c   |  40 +--
 src/backend/backup/walsummary.c               |  12 +-
 src/backend/commands/subscriptioncmds.c       |   6 +-
 src/backend/postmaster/walsummarizer.c        |  75 ++---
 .../libpqwalreceiver/libpqwalreceiver.c       |   2 +-
 src/backend/replication/logical/logical.c     |  46 +--
 src/backend/replication/logical/origin.c      |   4 +-
 .../replication/logical/reorderbuffer.c       |  14 +-
 src/backend/replication/logical/slotsync.c    |  28 +-
 src/backend/replication/logical/snapbuild.c   |  44 +--
 src/backend/replication/logical/tablesync.c   |   4 +-
 src/backend/replication/logical/worker.c      |  46 +--
 src/backend/replication/repl_gram.y           |   4 +-
 src/backend/replication/repl_scanner.l        |   9 +-
 src/backend/replication/slot.c                |   6 +-
 src/backend/replication/slotfuncs.c           |   4 +-
 src/backend/replication/syncrep.c             |  10 +-
 src/backend/replication/walreceiver.c         |  28 +-
 src/backend/replication/walsender.c           |  47 ++--
 src/backend/storage/ipc/standby.c             |   8 +-
 src/backend/utils/activity/pgstat.c           |  12 +-
 src/backend/utils/adt/pg_lsn.c                |  10 +-
 src/bin/pg_basebackup/pg_basebackup.c         |  15 +-
 src/bin/pg_basebackup/pg_createsubscriber.c   |   6 +-
 src/bin/pg_basebackup/pg_receivewal.c         |  21 +-
 src/bin/pg_basebackup/pg_recvlogical.c        |  30 +-
 src/bin/pg_basebackup/receivelog.c            |  19 +-
 src/bin/pg_basebackup/streamutil.c            |  11 +-
 src/bin/pg_basebackup/t/010_pg_basebackup.pl  |   2 +-
 src/bin/pg_combinebackup/backup_label.c       |   7 +-
 src/bin/pg_combinebackup/pg_combinebackup.c   |   6 +-
 src/bin/pg_combinebackup/write_manifest.c     |   6 +-
 src/bin/pg_controldata/pg_controldata.c       |  24 +-
 src/bin/pg_rewind/libpq_source.c              |   6 +-
 src/bin/pg_rewind/parsexlog.c                 |  32 +--
 src/bin/pg_rewind/pg_rewind.c                 |  22 +-
 src/bin/pg_rewind/timeline.c                  |   9 +-
 src/bin/pg_verifybackup/pg_verifybackup.c     |   6 +-
 src/bin/pg_waldump/pg_waldump.c               |  47 ++--
 src/bin/pg_waldump/t/001_basic.pl             |   9 +-
 src/bin/pg_waldump/t/002_save_fullpage.pl     |   8 +-
 src/bin/pg_walsummary/t/002_blocks.pl         |   6 +-
 src/bin/psql/t/001_basic.pl                   |   2 +-
 src/common/parse_manifest.c                   |   8 +-
 src/include/access/rewriteheap.h              |  10 +-
 src/include/access/xlogdefs.h                 |   9 +-
 src/test/recovery/t/006_logical_decoding.pl   |   4 +-
 src/test/recovery/t/016_min_consistency.pl    |   2 +-
 .../t/038_save_logical_slots_shutdown.pl      |   4 +-
 src/test/recovery/t/039_end_of_wal.pl         |   6 +-
 src/test/regress/expected/numeric.out         |  18 +-
 src/test/regress/expected/pg_lsn.out          | 262 +++++++++---------
 src/test/regress/expected/subscription.out    | 152 +++++-----
 src/test/regress/sql/pg_lsn.sql               |   4 +-
 src/test/subscription/t/029_on_error.pl       |   4 +-
 85 files changed, 1098 insertions(+), 1109 deletions(-)

diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c
index aac8c74f546..349e7bbfd7e 100644
--- a/contrib/amcheck/verify_nbtree.c
+++ b/contrib/amcheck/verify_nbtree.c
@@ -1037,9 +1037,9 @@ bt_report_duplicate(BtreeCheckState *state,
 			(errcode(ERRCODE_INDEX_CORRUPTED),
 			 errmsg("index uniqueness is violated for index \"%s\"",
 					RelationGetRelationName(state->rel)),
-			 errdetail("Index %s%s and%s%s (point to heap %s and %s) page lsn=%X/%X.",
+			 errdetail("Index %s%s and%s%s (point to heap %s and %s) page lsn=%016" PRIX64 ".",
 					   itid, pposting, nitid, pnposting, htid, nhtid,
-					   LSN_FORMAT_ARGS(state->targetlsn))));
+					   state->targetlsn)));
 }
 
 /* Check if current nbtree leaf entry complies with UNIQUE constraint */
@@ -1182,9 +1182,9 @@ bt_leftmost_ignoring_half_dead(BtreeCheckState *state,
 					(errcode(ERRCODE_NO_DATA),
 					 errmsg_internal("harmless interrupted page deletion detected in index \"%s\"",
 									 RelationGetRelationName(state->rel)),
-					 errdetail_internal("Block=%u right block=%u page lsn=%X/%X.",
+					 errdetail_internal("Block=%u right block=%u page lsn=%016" PRIX64 ".",
 										reached, reached_from,
-										LSN_FORMAT_ARGS(pagelsn))));
+										pagelsn)));
 
 			reached_from = reached;
 			reached = reached_opaque->btpo_prev;
@@ -1407,11 +1407,11 @@ bt_target_page_check(BtreeCheckState *state)
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("wrong number of high key index tuple attributes in index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Index block=%u natts=%u block type=%s page lsn=%X/%X.",
+					 errdetail_internal("Index block=%u natts=%u block type=%s page lsn=%016" PRIX64 ".",
 										state->targetblock,
 										BTreeTupleGetNAtts(itup, state->rel),
 										P_ISLEAF(topaque) ? "heap" : "index",
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 		}
 	}
 
@@ -1456,10 +1456,10 @@ bt_target_page_check(BtreeCheckState *state)
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("index tuple size does not equal lp_len in index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Index tid=(%u,%u) tuple size=%zu lp_len=%u page lsn=%X/%X.",
+					 errdetail_internal("Index tid=(%u,%u) tuple size=%zu lp_len=%u page lsn=%016" PRIX64 ".",
 										state->targetblock, offset,
 										tupsize, ItemIdGetLength(itemid),
-										LSN_FORMAT_ARGS(state->targetlsn)),
+										state->targetlsn),
 					 errhint("This could be a torn page problem.")));
 
 		/* Check the number of index tuple attributes */
@@ -1480,12 +1480,12 @@ bt_target_page_check(BtreeCheckState *state)
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("wrong number of index tuple attributes in index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Index tid=%s natts=%u points to %s tid=%s page lsn=%X/%X.",
+					 errdetail_internal("Index tid=%s natts=%u points to %s tid=%s page lsn=%016" PRIX64 ".",
 										itid,
 										BTreeTupleGetNAtts(itup, state->rel),
 										P_ISLEAF(topaque) ? "heap" : "index",
 										htid,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 		}
 
 		/*
@@ -1530,9 +1530,9 @@ bt_target_page_check(BtreeCheckState *state)
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("could not find tuple using search from root page in index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Index tid=%s points to heap tid=%s page lsn=%X/%X.",
+					 errdetail_internal("Index tid=%s points to heap tid=%s page lsn=%016" PRIX64 ".",
 										itid, htid,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 		}
 
 		/*
@@ -1559,9 +1559,9 @@ bt_target_page_check(BtreeCheckState *state)
 							(errcode(ERRCODE_INDEX_CORRUPTED),
 							 errmsg_internal("posting list contains misplaced TID in index \"%s\"",
 											 RelationGetRelationName(state->rel)),
-							 errdetail_internal("Index tid=%s posting list offset=%d page lsn=%X/%X.",
+							 errdetail_internal("Index tid=%s posting list offset=%d page lsn=%016" PRIX64 ".",
 												itid, i,
-												LSN_FORMAT_ARGS(state->targetlsn))));
+												state->targetlsn)));
 				}
 
 				ItemPointerCopy(current, &last);
@@ -1613,11 +1613,11 @@ bt_target_page_check(BtreeCheckState *state)
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("index row size %zu exceeds maximum for index \"%s\"",
 							tupsize, RelationGetRelationName(state->rel)),
-					 errdetail_internal("Index tid=%s points to %s tid=%s page lsn=%X/%X.",
+					 errdetail_internal("Index tid=%s points to %s tid=%s page lsn=%016" PRIX64 ".",
 										itid,
 										P_ISLEAF(topaque) ? "heap" : "index",
 										htid,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 		}
 
 		/* Fingerprint leaf page tuples (those that point to the heap) */
@@ -1720,11 +1720,11 @@ bt_target_page_check(BtreeCheckState *state)
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("high key invariant violated for index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Index tid=%s points to %s tid=%s page lsn=%X/%X.",
+					 errdetail_internal("Index tid=%s points to %s tid=%s page lsn=%016" PRIX64 ".",
 										itid,
 										P_ISLEAF(topaque) ? "heap" : "index",
 										htid,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 		}
 		/* Reset, in case scantid was set to (itup) posting tuple's max TID */
 		skey->scantid = scantid;
@@ -1768,14 +1768,14 @@ bt_target_page_check(BtreeCheckState *state)
 							RelationGetRelationName(state->rel)),
 					 errdetail_internal("Lower index tid=%s (points to %s tid=%s) "
 										"higher index tid=%s (points to %s tid=%s) "
-										"page lsn=%X/%X.",
+										"page lsn=%016" PRIX64 ".",
 										itid,
 										P_ISLEAF(topaque) ? "heap" : "index",
 										htid,
 										nitid,
 										P_ISLEAF(topaque) ? "heap" : "index",
 										nhtid,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 		}
 
 		/*
@@ -1885,9 +1885,9 @@ bt_target_page_check(BtreeCheckState *state)
 						(errcode(ERRCODE_INDEX_CORRUPTED),
 						 errmsg("cross page item order invariant violated for index \"%s\"",
 								RelationGetRelationName(state->rel)),
-						 errdetail_internal("Last item on page tid=(%u,%u) page lsn=%X/%X.",
+						 errdetail_internal("Last item on page tid=(%u,%u) page lsn=%016" PRIX64 ".",
 											state->targetblock, offset,
-											LSN_FORMAT_ARGS(state->targetlsn))));
+											state->targetlsn)));
 			}
 
 			/*
@@ -1938,9 +1938,9 @@ bt_target_page_check(BtreeCheckState *state)
 								(errcode(ERRCODE_INDEX_CORRUPTED),
 								 errmsg("right block of leaf block is non-leaf for index \"%s\"",
 										RelationGetRelationName(state->rel)),
-								 errdetail_internal("Block=%u page lsn=%X/%X.",
+								 errdetail_internal("Block=%u page lsn=%016" PRIX64 ".",
 													state->targetblock,
-													LSN_FORMAT_ARGS(state->targetlsn))));
+													state->targetlsn)));
 
 					itemid = PageGetItemIdCareful(state, rightblock_number,
 												  rightpage,
@@ -2362,9 +2362,9 @@ bt_child_highkey_check(BtreeCheckState *state,
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("the first child of leftmost target page is not leftmost of its level in index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Target block=%u child block=%u target page lsn=%X/%X.",
+					 errdetail_internal("Target block=%u child block=%u target page lsn=%016" PRIX64 ".",
 										state->targetblock, blkno,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 
 		/* Do level sanity check */
 		if ((!P_ISDELETED(opaque) || P_HAS_FULLXID(opaque)) &&
@@ -2448,9 +2448,9 @@ bt_child_highkey_check(BtreeCheckState *state,
 								(errcode(ERRCODE_INDEX_CORRUPTED),
 								 errmsg("child high key is greater than rightmost pivot key on target level in index \"%s\"",
 										RelationGetRelationName(state->rel)),
-								 errdetail_internal("Target block=%u child block=%u target page lsn=%X/%X.",
+								 errdetail_internal("Target block=%u child block=%u target page lsn=%016" PRIX64 ".",
 													state->targetblock, blkno,
-													LSN_FORMAT_ARGS(state->targetlsn))));
+													state->targetlsn)));
 					pivotkey_offset = P_HIKEY;
 				}
 				itemid = PageGetItemIdCareful(state, state->targetblock,
@@ -2478,9 +2478,9 @@ bt_child_highkey_check(BtreeCheckState *state,
 							(errcode(ERRCODE_INDEX_CORRUPTED),
 							 errmsg("can't find left sibling high key in index \"%s\"",
 									RelationGetRelationName(state->rel)),
-							 errdetail_internal("Target block=%u child block=%u target page lsn=%X/%X.",
+							 errdetail_internal("Target block=%u child block=%u target page lsn=%016" PRIX64 ".",
 												state->targetblock, blkno,
-												LSN_FORMAT_ARGS(state->targetlsn))));
+												state->targetlsn)));
 				itup = state->lowkey;
 			}
 
@@ -2490,9 +2490,9 @@ bt_child_highkey_check(BtreeCheckState *state,
 						(errcode(ERRCODE_INDEX_CORRUPTED),
 						 errmsg("mismatch between parent key and child high key in index \"%s\"",
 								RelationGetRelationName(state->rel)),
-						 errdetail_internal("Target block=%u child block=%u target page lsn=%X/%X.",
+						 errdetail_internal("Target block=%u child block=%u target page lsn=%016" PRIX64 ".",
 											state->targetblock, blkno,
-											LSN_FORMAT_ARGS(state->targetlsn))));
+											state->targetlsn)));
 			}
 		}
 
@@ -2630,9 +2630,9 @@ bt_child_check(BtreeCheckState *state, BTScanInsert targetkey,
 				(errcode(ERRCODE_INDEX_CORRUPTED),
 				 errmsg("downlink to deleted page found in index \"%s\"",
 						RelationGetRelationName(state->rel)),
-				 errdetail_internal("Parent block=%u child block=%u parent page lsn=%X/%X.",
+				 errdetail_internal("Parent block=%u child block=%u parent page lsn=%016" PRIX64 ".",
 									state->targetblock, childblock,
-									LSN_FORMAT_ARGS(state->targetlsn))));
+									state->targetlsn)));
 
 	for (offset = P_FIRSTDATAKEY(copaque);
 		 offset <= maxoffset;
@@ -2671,9 +2671,9 @@ bt_child_check(BtreeCheckState *state, BTScanInsert targetkey,
 					(errcode(ERRCODE_INDEX_CORRUPTED),
 					 errmsg("down-link lower bound invariant violated for index \"%s\"",
 							RelationGetRelationName(state->rel)),
-					 errdetail_internal("Parent block=%u child index tid=(%u,%u) parent page lsn=%X/%X.",
+					 errdetail_internal("Parent block=%u child index tid=(%u,%u) parent page lsn=%016" PRIX64 ".",
 										state->targetblock, childblock, offset,
-										LSN_FORMAT_ARGS(state->targetlsn))));
+										state->targetlsn)));
 	}
 
 	pfree(child);
@@ -2741,10 +2741,10 @@ bt_downlink_missing_check(BtreeCheckState *state, bool rightsplit,
 				(errcode(ERRCODE_NO_DATA),
 				 errmsg_internal("harmless interrupted page split detected in index \"%s\"",
 								 RelationGetRelationName(state->rel)),
-				 errdetail_internal("Block=%u level=%u left sibling=%u page lsn=%X/%X.",
+				 errdetail_internal("Block=%u level=%u left sibling=%u page lsn=%016" PRIX64 ".",
 									blkno, opaque->btpo_level,
 									opaque->btpo_prev,
-									LSN_FORMAT_ARGS(pagelsn))));
+									pagelsn)));
 		return;
 	}
 
@@ -2763,9 +2763,9 @@ bt_downlink_missing_check(BtreeCheckState *state, bool rightsplit,
 				(errcode(ERRCODE_INDEX_CORRUPTED),
 				 errmsg("leaf index block lacks downlink in index \"%s\"",
 						RelationGetRelationName(state->rel)),
-				 errdetail_internal("Block=%u page lsn=%X/%X.",
+				 errdetail_internal("Block=%u page lsn=%016" PRIX64 ".",
 									blkno,
-									LSN_FORMAT_ARGS(pagelsn))));
+									pagelsn)));
 
 	/* Descend from the given page, which is an internal page */
 	elog(DEBUG1, "checking for interrupted multi-level deletion due to missing downlink in index \"%s\"",
@@ -2829,9 +2829,9 @@ bt_downlink_missing_check(BtreeCheckState *state, bool rightsplit,
 				(errcode(ERRCODE_INDEX_CORRUPTED),
 				 errmsg_internal("downlink to deleted leaf page found in index \"%s\"",
 								 RelationGetRelationName(state->rel)),
-				 errdetail_internal("Top parent/target block=%u leaf block=%u top parent/under check lsn=%X/%X.",
+				 errdetail_internal("Top parent/target block=%u leaf block=%u top parent/under check lsn=%016" PRIX64 ".",
 									blkno, childblk,
-									LSN_FORMAT_ARGS(pagelsn))));
+									pagelsn)));
 
 	/*
 	 * Iff leaf page is half-dead, its high key top parent link should point
@@ -2855,9 +2855,9 @@ bt_downlink_missing_check(BtreeCheckState *state, bool rightsplit,
 			(errcode(ERRCODE_INDEX_CORRUPTED),
 			 errmsg("internal index block lacks downlink in index \"%s\"",
 					RelationGetRelationName(state->rel)),
-			 errdetail_internal("Block=%u level=%u page lsn=%X/%X.",
+			 errdetail_internal("Block=%u level=%u page lsn=%016" PRIX64 ".",
 								blkno, opaque->btpo_level,
-								LSN_FORMAT_ARGS(pagelsn))));
+								pagelsn)));
 }
 
 /*
diff --git a/contrib/pageinspect/expected/gist.out b/contrib/pageinspect/expected/gist.out
index 2b1d54a6279..a5169f4cae7 100644
--- a/contrib/pageinspect/expected/gist.out
+++ b/contrib/pageinspect/expected/gist.out
@@ -5,21 +5,21 @@ CREATE UNLOGGED TABLE test_gist AS SELECT point(i,i) p, i::text t FROM
 CREATE INDEX test_gist_idx ON test_gist USING gist (p);
 -- Page 0 is the root, the rest are leaf pages
 SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 0));
- lsn | nsn | rightlink  | flags 
------+-----+------------+-------
- 0/1 | 0/0 | 4294967295 | {}
+       lsn        |       nsn        | rightlink  | flags 
+------------------+------------------+------------+-------
+ 0000000000000001 | 0000000000000000 | 4294967295 | {}
 (1 row)
 
 SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 1));
- lsn | nsn | rightlink  | flags  
------+-----+------------+--------
- 0/1 | 0/0 | 4294967295 | {leaf}
+       lsn        |       nsn        | rightlink  | flags  
+------------------+------------------+------------+--------
+ 0000000000000001 | 0000000000000000 | 4294967295 | {leaf}
 (1 row)
 
 SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 2));
- lsn | nsn | rightlink | flags  
------+-----+-----------+--------
- 0/1 | 0/0 |         1 | {leaf}
+       lsn        |       nsn        | rightlink | flags  
+------------------+------------------+-----------+--------
+ 0000000000000001 | 0000000000000000 |         1 | {leaf}
 (1 row)
 
 SELECT * FROM gist_page_items(get_raw_page('test_gist_idx', 0), 'test_gist_idx');
diff --git a/contrib/pageinspect/expected/page.out b/contrib/pageinspect/expected/page.out
index e42fd9747fd..86c57917365 100644
--- a/contrib/pageinspect/expected/page.out
+++ b/contrib/pageinspect/expected/page.out
@@ -265,9 +265,9 @@ SELECT fsm_page_contents(decode(repeat('00', :block_size), 'hex'));
 (1 row)
 
 SELECT page_header(decode(repeat('00', :block_size), 'hex'));
-      page_header      
------------------------
- (0/0,0,0,0,0,0,0,0,0)
+            page_header             
+------------------------------------
+ (0000000000000000,0,0,0,0,0,0,0,0)
 (1 row)
 
 SELECT page_checksum(decode(repeat('00', :block_size), 'hex'), 1);
diff --git a/contrib/pageinspect/rawpage.c b/contrib/pageinspect/rawpage.c
index 617dff821a6..0336ccb4ab6 100644
--- a/contrib/pageinspect/rawpage.c
+++ b/contrib/pageinspect/rawpage.c
@@ -279,7 +279,7 @@ page_header(PG_FUNCTION_ARGS)
 	{
 		char		lsnchar[64];
 
-		snprintf(lsnchar, sizeof(lsnchar), "%X/%X", LSN_FORMAT_ARGS(lsn));
+		snprintf(lsnchar, sizeof(lsnchar), "%016" PRIX64, lsn);
 		values[0] = CStringGetTextDatum(lsnchar);
 	}
 	else
diff --git a/contrib/pg_walinspect/expected/pg_walinspect.out b/contrib/pg_walinspect/expected/pg_walinspect.out
index c010eed8c5d..037cd363c46 100644
--- a/contrib/pg_walinspect/expected/pg_walinspect.out
+++ b/contrib/pg_walinspect/expected/pg_walinspect.out
@@ -19,14 +19,14 @@ INSERT INTO sample_tbl SELECT * FROM generate_series(3, 4);
 -- ===================================================================
 -- Invalid input LSN.
 SELECT * FROM pg_get_wal_record_info('0/0');
-ERROR:  could not read WAL at LSN 0/0
+ERROR:  could not read WAL at LSN 0000000000000000
 -- Invalid start LSN.
 SELECT * FROM pg_get_wal_records_info('0/0', :'wal_lsn1');
-ERROR:  could not read WAL at LSN 0/0
+ERROR:  could not read WAL at LSN 0000000000000000
 SELECT * FROM pg_get_wal_stats('0/0', :'wal_lsn1');
-ERROR:  could not read WAL at LSN 0/0
+ERROR:  could not read WAL at LSN 0000000000000000
 SELECT * FROM pg_get_wal_block_info('0/0', :'wal_lsn1');
-ERROR:  could not read WAL at LSN 0/0
+ERROR:  could not read WAL at LSN 0000000000000000
 -- Start LSN > End LSN.
 SELECT * FROM pg_get_wal_records_info(:'wal_lsn2', :'wal_lsn1');
 ERROR:  WAL start LSN must be less than end LSN
diff --git a/contrib/pg_walinspect/pg_walinspect.c b/contrib/pg_walinspect/pg_walinspect.c
index 9e609415789..7dbfe4d8e79 100644
--- a/contrib/pg_walinspect/pg_walinspect.c
+++ b/contrib/pg_walinspect/pg_walinspect.c
@@ -102,8 +102,7 @@ InitXLogReaderState(XLogRecPtr lsn)
 	if (lsn < XLOG_BLCKSZ)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("could not read WAL at LSN %X/%X",
-						LSN_FORMAT_ARGS(lsn))));
+				 errmsg("could not read WAL at LSN %016" PRIX64, lsn)));
 
 	private_data = (ReadLocalXLogPageNoWaitPrivate *)
 		palloc0(sizeof(ReadLocalXLogPageNoWaitPrivate));
@@ -125,8 +124,8 @@ InitXLogReaderState(XLogRecPtr lsn)
 
 	if (XLogRecPtrIsInvalid(first_valid_record))
 		ereport(ERROR,
-				(errmsg("could not find a valid record after %X/%X",
-						LSN_FORMAT_ARGS(lsn))));
+				(errmsg("could not find a valid record after %016" PRIX64,
+						lsn)));
 
 	return xlogreader;
 }
@@ -165,13 +164,13 @@ ReadNextXLogRecord(XLogReaderState *xlogreader)
 		if (errormsg)
 			ereport(ERROR,
 					(errcode_for_file_access(),
-					 errmsg("could not read WAL at %X/%X: %s",
-							LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
+					 errmsg("could not read WAL at %016" PRIX64 ": %s",
+							xlogreader->EndRecPtr, errormsg)));
 		else
 			ereport(ERROR,
 					(errcode_for_file_access(),
-					 errmsg("could not read WAL at %X/%X",
-							LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
+					 errmsg("could not read WAL at %016" PRIX64,
+							xlogreader->EndRecPtr)));
 	}
 
 	return record;
@@ -476,8 +475,9 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("WAL input LSN must be less than current LSN"),
-				 errdetail("Current WAL LSN on the database system is at %X/%X.",
-						   LSN_FORMAT_ARGS(curr_lsn))));
+				 errdetail("Current WAL LSN on the database system is at %016"
+						   PRIX64 ".",
+						   curr_lsn)));
 
 	/* Build a tuple descriptor for our result type. */
 	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
@@ -488,8 +488,8 @@ pg_get_wal_record_info(PG_FUNCTION_ARGS)
 	if (!ReadNextXLogRecord(xlogreader))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-				 errmsg("could not read WAL at %X/%X",
-						LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
+				 errmsg("could not read WAL at %016" PRIX64,
+						xlogreader->EndRecPtr)));
 
 	GetWALRecordInfo(xlogreader, values, nulls, PG_GET_WAL_RECORD_INFO_COLS);
 
@@ -518,8 +518,9 @@ ValidateInputLSNs(XLogRecPtr start_lsn, XLogRecPtr *end_lsn)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("WAL start LSN must be less than current LSN"),
-				 errdetail("Current WAL LSN on the database system is at %X/%X.",
-						   LSN_FORMAT_ARGS(curr_lsn))));
+				 errdetail("Current WAL LSN on the database system is at %016"
+						   PRIX64 ".",
+						   curr_lsn)));
 
 	if (start_lsn > *end_lsn)
 		ereport(ERROR,
@@ -824,8 +825,8 @@ pg_get_wal_records_info_till_end_of_wal(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("WAL start LSN must be less than current LSN"),
-				 errdetail("Current WAL LSN on the database system is at %X/%X.",
-						   LSN_FORMAT_ARGS(end_lsn))));
+				 errdetail("Current WAL LSN on the database system is at %016" PRIX64,
+						   end_lsn)));
 
 	GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
 
@@ -843,8 +844,9 @@ pg_get_wal_stats_till_end_of_wal(PG_FUNCTION_ARGS)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("WAL start LSN must be less than current LSN"),
-				 errdetail("Current WAL LSN on the database system is at %X/%X.",
-						   LSN_FORMAT_ARGS(end_lsn))));
+				 errdetail("Current WAL LSN on the database system is at %016"
+						   PRIX64 ".",
+						   end_lsn)));
 
 	GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
 
diff --git a/contrib/test_decoding/expected/replorigin.out b/contrib/test_decoding/expected/replorigin.out
index c85e1a01b23..453fd9c8f95 100644
--- a/contrib/test_decoding/expected/replorigin.out
+++ b/contrib/test_decoding/expected/replorigin.out
@@ -126,13 +126,13 @@ COMMIT;
 SELECT pg_replication_origin_session_progress(false);
  pg_replication_origin_session_progress 
 ----------------------------------------
- 0/AABBCCDD
+ 00000000AABBCCDD
 (1 row)
 
 SELECT pg_replication_origin_session_progress(true);
  pg_replication_origin_session_progress 
 ----------------------------------------
- 0/AABBCCDD
+ 00000000AABBCCDD
 (1 row)
 
 SELECT pg_replication_origin_session_reset();
@@ -142,22 +142,22 @@ SELECT pg_replication_origin_session_reset();
 (1 row)
 
 SELECT local_id, external_id, remote_lsn, local_lsn <> '0/0' FROM pg_replication_origin_status;
- local_id |              external_id               | remote_lsn | ?column? 
-----------+----------------------------------------+------------+----------
-        1 | regress_test_decoding: regression_slot | 0/AABBCCDD | t
+ local_id |              external_id               |    remote_lsn    | ?column? 
+----------+----------------------------------------+------------------+----------
+        1 | regress_test_decoding: regression_slot | 00000000AABBCCDD | t
 (1 row)
 
 -- check replication progress identified by name is correct
 SELECT pg_replication_origin_progress('regress_test_decoding: regression_slot', false);
  pg_replication_origin_progress 
 --------------------------------
- 0/AABBCCDD
+ 00000000AABBCCDD
 (1 row)
 
 SELECT pg_replication_origin_progress('regress_test_decoding: regression_slot', true);
  pg_replication_origin_progress 
 --------------------------------
- 0/AABBCCDD
+ 00000000AABBCCDD
 (1 row)
 
 -- ensure reset requires previously setup state
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index ee59a7e15d0..9b575f55bda 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -7956,7 +7956,7 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
       </para>
       <para>
        Finish LSN of the transaction whose changes are to be skipped, if a valid
-       LSN; otherwise <literal>0/0</literal>.
+       LSN; otherwise <literal>0000000000000000</literal>.
       </para></entry>
      </row>
 
diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 87679dc4a11..45366bfe578 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -5090,19 +5090,22 @@ WHERE ...
 
    <para>
     Internally, an LSN is a 64-bit integer, representing a byte position in
-    the write-ahead log stream.  It is printed as two hexadecimal numbers of
-    up to 8 digits each, separated by a slash; for example,
-    <literal>16/B374D848</literal>.  The <type>pg_lsn</type> type supports the
-    standard comparison operators, like <literal>=</literal> and
-    <literal>&gt;</literal>.  Two LSNs can be subtracted using the
+    the write-ahead log stream.  It is printed as 16 hexadecimal digits; for
+    example <literal>00000016B374D848</literal>.  (Historically it was printed
+    as two 32-bit hexadecimal numbers separated by a slash, for example
+    <literal>16/B374D848</literal>.  This format is
+    still accepted as the <type>pg_lsn</type> as an input string.)
+    The <type>pg_lsn</type> type supports the standard comparison operators,
+    like <literal>=</literal> and <literal>&gt;</literal>.  Two LSNs can be
+    subtracted using the
     <literal>-</literal> operator; the result is the number of bytes separating
     those write-ahead log locations.  Also the number of bytes can be
     added into and subtracted from LSN using the
     <literal>+(pg_lsn,numeric)</literal> and
     <literal>-(pg_lsn,numeric)</literal> operators, respectively. Note that
     the calculated LSN should be in the range of <type>pg_lsn</type> type,
-    i.e., between <literal>0/0</literal> and
-    <literal>FFFFFFFF/FFFFFFFF</literal>.
+    i.e., between <literal>0000000000000000</literal> and
+    <literal>FFFFFFFFFFFFFFFF</literal>.
    </para>
   </sect1>
 
diff --git a/doc/src/sgml/logical-replication.sgml b/doc/src/sgml/logical-replication.sgml
index 3d18e507bbc..457a324487a 100644
--- a/doc/src/sgml/logical-replication.sgml
+++ b/doc/src/sgml/logical-replication.sgml
@@ -595,9 +595,9 @@ CREATE SUBSCRIPTION
        slot to create is same as the subscription name, e.g. "sub1".
 <programlisting>
 test_pub=# SELECT * FROM pg_create_logical_replication_slot('sub1', 'pgoutput');
- slot_name |    lsn
------------+-----------
- sub1      | 0/19404D0
+ slot_name |       lsn
+-----------+------------------
+ sub1      | 00000000019404D0
 (1 row)
 </programlisting></para>
      </listitem>
@@ -640,9 +640,9 @@ CREATE SUBSCRIPTION
        specified during <literal>CREATE SUBSCRIPTION</literal>, e.g. "myslot".
 <programlisting>
 test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput');
- slot_name |    lsn
------------+-----------
- myslot    | 0/19059A0
+ slot_name |       lsn
+-----------+------------------
+ myslot    | 00000000019059A0
 (1 row)
 </programlisting></para>
      </listitem>
@@ -681,9 +681,9 @@ CREATE SUBSCRIPTION
        On the publisher, manually create a slot using any name, e.g. "myslot".
 <programlisting>
 test_pub=# SELECT * FROM pg_create_logical_replication_slot('myslot', 'pgoutput');
- slot_name |    lsn
------------+-----------
- myslot    | 0/1905930
+ slot_name |       lsn
+-----------+------------------
+ myslot    | 0000000001905930
 (1 row)
 </programlisting></para>
      </listitem>
@@ -2017,15 +2017,15 @@ DETAIL:  <replaceable class="parameter">detailed_explanation</replaceable>.
 ERROR:  conflict detected on relation "public.test": conflict=insert_exists
 DETAIL:  Key already exists in unique index "t_pkey", which was modified locally in transaction 740 at 2024-06-26 10:47:04.727375+08.
 Key (c)=(1); existing local tuple (1, 'local'); remote tuple (1, 'remote').
-CONTEXT:  processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 0/14C0378
+CONTEXT:  processing remote data for replication origin "pg_16395" during "INSERT" for replication target relation "public.test" in transaction 725 finished at 00000000014C0378
 </screen>
    The LSN of the transaction that contains the change violating the constraint and
-   the replication origin name can be found from the server log (LSN 0/14C0378 and
+   the replication origin name can be found from the server log (LSN 00000000014C0378 and
    replication origin <literal>pg_16395</literal> in the above case).  The
    transaction that produced the conflict can be skipped by using
    <link linkend="sql-altersubscription-params-skip"><command>ALTER SUBSCRIPTION ... SKIP</command></link>
    with the finish LSN
-   (i.e., LSN 0/14C0378).  The finish LSN could be an LSN at which the transaction
+   (i.e., LSN 00000000014C0378).  The finish LSN could be an LSN at which the transaction
    is committed or prepared on the publisher.  Alternatively, the transaction can
    also be skipped by calling the <link linkend="pg-replication-origin-advance">
    <function>pg_replication_origin_advance()</function></link> function.
@@ -2036,7 +2036,7 @@ CONTEXT:  processing remote data for replication origin "pg_16395" during "INSER
    <link linkend="sql-createsubscription-params-with-disable-on-error"><literal>disable_on_error</literal></link>
    option. Then, you can use <function>pg_replication_origin_advance()</function>
    function with the <parameter>node_name</parameter> (i.e., <literal>pg_16395</literal>)
-   and the next LSN of the finish LSN (i.e., 0/14C0379).  The current position of
+   and the next LSN of the finish LSN (i.e., 00000000014C0379).  The current position of
    origins can be seen in the <link linkend="view-pg-replication-origin-status">
    <structname>pg_replication_origin_status</structname></link> system view.
    Please note that skipping the whole transaction includes skipping changes that
diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml
index 1c4ae38f1b9..8a38930afe2 100644
--- a/doc/src/sgml/logicaldecoding.sgml
+++ b/doc/src/sgml/logicaldecoding.sgml
@@ -56,15 +56,15 @@
 <programlisting>
 postgres=# -- Create a slot named 'regression_slot' using the output plugin 'test_decoding'
 postgres=# SELECT * FROM pg_create_logical_replication_slot('regression_slot', 'test_decoding', false, true);
-    slot_name    |    lsn
------------------+-----------
- regression_slot | 0/16B1970
+    slot_name    |       lsn
+-----------------+------------------
+ regression_slot | 00000000016B1970
 (1 row)
 
 postgres=# SELECT slot_name, plugin, slot_type, database, active, restart_lsn, confirmed_flush_lsn FROM pg_replication_slots;
-    slot_name    |    plugin     | slot_type | database | active | restart_lsn | confirmed_flush_lsn
------------------+---------------+-----------+----------+--------+-------------+-----------------
- regression_slot | test_decoding | logical   | postgres | f      | 0/16A4408   | 0/16A4440
+    slot_name    |    plugin     | slot_type | database | active |   restart_lsn    | confirmed_flush_lsn
+-----------------+---------------+-----------+----------+--------+------------------+---------------------
+ regression_slot | test_decoding | logical   | postgres | f      | 00000000016A4408 | 00000000016A4440
 (1 row)
 
 postgres=# -- There are no changes to see yet
@@ -78,10 +78,10 @@ CREATE TABLE
 
 postgres=# -- DDL isn't replicated, so all you'll see is the transaction
 postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
-    lsn    |  xid  |     data
------------+-------+--------------
- 0/BA2DA58 | 10297 | BEGIN 10297
- 0/BA5A5A0 | 10297 | COMMIT 10297
+       lsn        |  xid  |     data
+------------------+-------+--------------
+ 000000000BA2DA58 | 10297 | BEGIN 10297
+ 000000000BA5A5A0 | 10297 | COMMIT 10297
 (2 rows)
 
 postgres=# -- Once changes are read, they're consumed and not emitted
@@ -97,41 +97,41 @@ postgres=*# INSERT INTO data(data) VALUES('2');
 postgres=*# COMMIT;
 
 postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
-    lsn    |  xid  |                          data
------------+-------+---------------------------------------------------------
- 0/BA5A688 | 10298 | BEGIN 10298
- 0/BA5A6F0 | 10298 | table public.data: INSERT: id[integer]:1 data[text]:'1'
- 0/BA5A7F8 | 10298 | table public.data: INSERT: id[integer]:2 data[text]:'2'
- 0/BA5A8A8 | 10298 | COMMIT 10298
+       lsn        |  xid  |                          data
+------------------+-------+---------------------------------------------------------
+ 000000000BA5A688 | 10298 | BEGIN 10298
+ 000000000BA5A6F0 | 10298 | table public.data: INSERT: id[integer]:1 data[text]:'1'
+ 000000000BA5A7F8 | 10298 | table public.data: INSERT: id[integer]:2 data[text]:'2'
+ 000000000BA5A8A8 | 10298 | COMMIT 10298
 (4 rows)
 
 postgres=# INSERT INTO data(data) VALUES('3');
 
 postgres=# -- You can also peek ahead in the change stream without consuming changes
 postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
-    lsn    |  xid  |                          data
------------+-------+---------------------------------------------------------
- 0/BA5A8E0 | 10299 | BEGIN 10299
- 0/BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
- 0/BA5A990 | 10299 | COMMIT 10299
+       lsn        |  xid  |                          data
+------------------+-------+---------------------------------------------------------
+ 000000000BA5A8E0 | 10299 | BEGIN 10299
+ 000000000BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
+ 000000000BA5A990 | 10299 | COMMIT 10299
 (3 rows)
 
 postgres=# -- The next call to pg_logical_slot_peek_changes() returns the same changes again
 postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL);
-    lsn    |  xid  |                          data
------------+-------+---------------------------------------------------------
- 0/BA5A8E0 | 10299 | BEGIN 10299
- 0/BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
- 0/BA5A990 | 10299 | COMMIT 10299
+       lsn        |  xid  |                          data
+------------------+-------+---------------------------------------------------------
+ 000000000BA5A8E0 | 10299 | BEGIN 10299
+ 000000000BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
+ 000000000BA5A990 | 10299 | COMMIT 10299
 (3 rows)
 
 postgres=# -- options can be passed to output plugin, to influence the formatting
 postgres=# SELECT * FROM pg_logical_slot_peek_changes('regression_slot', NULL, NULL, 'include-timestamp', 'on');
-    lsn    |  xid  |                          data
------------+-------+---------------------------------------------------------
- 0/BA5A8E0 | 10299 | BEGIN 10299
- 0/BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
- 0/BA5A990 | 10299 | COMMIT 10299 (at 2017-05-10 12:07:21.272494-04)
+       lsn        |  xid  |                          data
+------------------+-------+---------------------------------------------------------
+ 000000000BA5A8E0 | 10299 | BEGIN 10299
+ 000000000BA5A8E0 | 10299 | table public.data: INSERT: id[integer]:3 data[text]:'3'
+ 000000000BA5A990 | 10299 | COMMIT 10299 (at 2017-05-10 12:07:21.272494-04)
 (3 rows)
 
 postgres=# -- Remember to destroy a slot you no longer need to stop it consuming
@@ -200,18 +200,18 @@ postgres=*# INSERT INTO data(data) VALUES('5');
 postgres=*# PREPARE TRANSACTION 'test_prepared1';
 
 postgres=# SELECT * FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL);
-    lsn    | xid |                          data
------------+-----+---------------------------------------------------------
- 0/1689DC0 | 529 | BEGIN 529
- 0/1689DC0 | 529 | table public.data: INSERT: id[integer]:3 data[text]:'5'
- 0/1689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1', txid 529
+       lsn        | xid |                          data
+------------------+-----+---------------------------------------------------------
+ 0000000001689DC0 | 529 | BEGIN 529
+ 0000000001689DC0 | 529 | table public.data: INSERT: id[integer]:3 data[text]:'5'
+ 0000000001689FC0 | 529 | PREPARE TRANSACTION 'test_prepared1', txid 529
 (3 rows)
 
 postgres=# COMMIT PREPARED 'test_prepared1';
 postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
-    lsn    | xid |                    data
------------+-----+--------------------------------------------
- 0/168A060 | 529 | COMMIT PREPARED 'test_prepared1', txid 529
+       lsn        | xid |                    data
+------------------+-----+--------------------------------------------
+ 000000000168A060 | 529 | COMMIT PREPARED 'test_prepared1', txid 529
 (4 row)
 
 postgres=#-- you can also rollback a prepared transaction
@@ -219,18 +219,18 @@ postgres=# BEGIN;
 postgres=*# INSERT INTO data(data) VALUES('6');
 postgres=*# PREPARE TRANSACTION 'test_prepared2';
 postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
-    lsn    | xid |                          data
------------+-----+---------------------------------------------------------
- 0/168A180 | 530 | BEGIN 530
- 0/168A1E8 | 530 | table public.data: INSERT: id[integer]:4 data[text]:'6'
- 0/168A430 | 530 | PREPARE TRANSACTION 'test_prepared2', txid 530
+       lsn        | xid |                          data
+------------------+-----+---------------------------------------------------------
+ 000000000168A180 | 530 | BEGIN 530
+ 000000000168A1E8 | 530 | table public.data: INSERT: id[integer]:4 data[text]:'6'
+ 000000000168A430 | 530 | PREPARE TRANSACTION 'test_prepared2', txid 530
 (3 rows)
 
 postgres=# ROLLBACK PREPARED 'test_prepared2';
 postgres=# select * from pg_logical_slot_get_changes('regression_slot', NULL, NULL);
-    lsn    | xid |                     data
------------+-----+----------------------------------------------
- 0/168A4B8 | 530 | ROLLBACK PREPARED 'test_prepared2', txid 530
+       lsn        | xid |                     data
+------------------+-----+----------------------------------------------
+ 000000000168A4B8 | 530 | ROLLBACK PREPARED 'test_prepared2', txid 530
 (1 row)
 </programlisting>
 </sect1>
diff --git a/doc/src/sgml/pageinspect.sgml b/doc/src/sgml/pageinspect.sgml
index 487c5d758ff..11b715b804c 100644
--- a/doc/src/sgml/pageinspect.sgml
+++ b/doc/src/sgml/pageinspect.sgml
@@ -73,9 +73,9 @@
       passed as argument.  For example:
 <screen>
 test=# SELECT * FROM page_header(get_raw_page('pg_class', 0));
-    lsn    | checksum | flags  | lower | upper | special | pagesize | version | prune_xid
------------+----------+--------+-------+-------+---------+----------+---------+-----------
- 0/24A1B50 |        0 |      1 |   232 |   368 |    8192 |     8192 |       4 |         0
+       lsn        | checksum | flags  | lower | upper | special | pagesize | version | prune_xid
+------------------+----------+--------+-------+-------+---------+----------+---------+-----------
+ 00000000024A1B50 |        0 |      1 |   232 |   368 |    8192 |     8192 |       4 |         0
 </screen>
       The returned columns correspond to the fields in the
       <structname>PageHeaderData</structname> struct.
@@ -741,9 +741,9 @@ test=# SELECT first_tid, nbytes, tids[0:5] AS some_tids
       For example:
 <screen>
 test=# SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 2));
- lsn | nsn | rightlink | flags
------+-----+-----------+--------
- 0/1 | 0/0 |         1 | {leaf}
+       lsn        |       nsn        | rightlink | flags
+------------------+------------------+-----------+--------
+ 0000000000000001 | 0000000000000000 |         1 | {leaf}
 (1 row)
 </screen>
      </para>
diff --git a/doc/src/sgml/pglogicalinspect.sgml b/doc/src/sgml/pglogicalinspect.sgml
index 4b111f96113..c319429750f 100644
--- a/doc/src/sgml/pglogicalinspect.sgml
+++ b/doc/src/sgml/pglogicalinspect.sgml
@@ -86,16 +86,16 @@ size         | 152
 modification | 2024-08-14 16:36:32+00
 
 postgres=# SELECT * FROM pg_get_logical_snapshot_info('0-40796E18.snap');
--[ RECORD 1 ]------------+-----------
+-[ RECORD 1 ]------------+-----------------
 state                    | consistent
 xmin                     | 751
 xmax                     | 751
-start_decoding_at        | 0/40796AF8
-two_phase_at             | 0/40796AF8
+start_decoding_at        | 0000000040796AF8
+two_phase_at             | 0000000040796AF8
 initial_xmin_horizon     | 0
 building_full_snapshot   | f
 in_slot_creation         | f
-last_serialized_snapshot | 0/0
+last_serialized_snapshot | 0000000000000000
 next_phase_at            | 0
 committed_count          | 0
 committed_xip            |
@@ -104,17 +104,17 @@ catchange_xip            | {751,752}
 
 postgres=# SELECT ss.name, info.* FROM pg_ls_logicalsnapdir() AS ss,
 pg_get_logical_snapshot_info(ss.name) AS info;
--[ RECORD 1 ]------------+----------------
+-[ RECORD 1 ]------------+-----------------
 name                     | 0-40796E18.snap
 state                    | consistent
 xmin                     | 751
 xmax                     | 751
-start_decoding_at        | 0/40796AF8
-two_phase_at             | 0/40796AF8
+start_decoding_at        | 0000000040796AF8
+two_phase_at             | 0000000040796AF8
 initial_xmin_horizon     | 0
 building_full_snapshot   | f
 in_slot_creation         | f
-last_serialized_snapshot | 0/0
+last_serialized_snapshot | 0000000000000000
 next_phase_at            | 0
 committed_count          | 0
 committed_xip            |
diff --git a/doc/src/sgml/pgwalinspect.sgml b/doc/src/sgml/pgwalinspect.sgml
index 3a8121c70f1..c3b4a596228 100644
--- a/doc/src/sgml/pgwalinspect.sgml
+++ b/doc/src/sgml/pgwalinspect.sgml
@@ -71,11 +71,11 @@
       after the <replaceable>in_lsn</replaceable> argument.  For
       example:
 <screen>
-postgres=# SELECT * FROM pg_get_wal_record_info('0/E419E28');
+postgres=# SELECT * FROM pg_get_wal_record_info('000000000E419E28');
 -[ RECORD 1 ]----+-------------------------------------------------
-start_lsn        | 0/E419E28
-end_lsn          | 0/E419E68
-prev_lsn         | 0/E419D78
+start_lsn        | 000000000E419E28
+end_lsn          | 000000000E419E68
+prev_lsn         | 000000000E419D78
 xid              | 0
 resource_manager | Heap2
 record_type      | VACUUM
@@ -109,11 +109,11 @@ block_ref        | blkref #0: rel 1663/16385/1249 fork main blk 364
       <replaceable>start_lsn</replaceable> and <replaceable>end_lsn</replaceable>.
       Returns one row per WAL record.  For example:
 <screen>
-postgres=# SELECT * FROM pg_get_wal_records_info('0/1E913618', '0/1E913740') LIMIT 1;
+postgres=# SELECT * FROM pg_get_wal_records_info('1E913618', '1E913740') LIMIT 1;
 -[ RECORD 1 ]----+--------------------------------------------------------------
-start_lsn        | 0/1E913618
-end_lsn          | 0/1E913650
-prev_lsn         | 0/1E9135A0
+start_lsn        | 000000001E913618
+end_lsn          | 000000001E913650
+prev_lsn         | 000000001E9135A0
 xid              | 0
 resource_manager | Standby
 record_type      | RUNNING_XACTS
@@ -144,11 +144,11 @@ block_ref        |
       references.  Returns one row per block reference per WAL record.
       For example:
 <screen>
-postgres=# SELECT * FROM pg_get_wal_block_info('0/1230278', '0/12302B8');
+postgres=# SELECT * FROM pg_get_wal_block_info('1230278', '12302B8');
 -[ RECORD 1 ]-----+-----------------------------------
-start_lsn         | 0/1230278
-end_lsn           | 0/12302B8
-prev_lsn          | 0/122FD40
+start_lsn         | 0000000001230278
+end_lsn           | 00000000012302B8
+prev_lsn          | 000000000122FD40
 block_id          | 0
 reltablespace     | 1663
 reldatabase       | 1
@@ -249,7 +249,7 @@ block_fpi_data    |
       it returns one row per <replaceable>record_type</replaceable>.
       For example:
 <screen>
-postgres=# SELECT * FROM pg_get_wal_stats('0/1E847D00', '0/1E84F500')
+postgres=# SELECT * FROM pg_get_wal_stats('1E847D00', '1E84F500')
            WHERE count > 0 AND
                  "resource_manager/record_type" = 'Transaction'
            LIMIT 1;
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml
index 3bd9e68e6ce..075614f8310 100644
--- a/doc/src/sgml/protocol.sgml
+++ b/doc/src/sgml/protocol.sgml
@@ -2402,13 +2402,13 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
     </varlistentry>
 
     <varlistentry id="protocol-replication-start-replication">
-     <term><literal>START_REPLICATION</literal> [ <literal>SLOT</literal> <replaceable class="parameter">slot_name</replaceable> ] [ <literal>PHYSICAL</literal> ] <replaceable class="parameter">XXX/XXX</replaceable> [ <literal>TIMELINE</literal> <replaceable class="parameter">tli</replaceable> ]
+     <term><literal>START_REPLICATION</literal> [ <literal>SLOT</literal> <replaceable class="parameter">slot_name</replaceable> ] [ <literal>PHYSICAL</literal> ] <replaceable class="parameter">XXXXXXXXXXXXXX</replaceable> [ <literal>TIMELINE</literal> <replaceable class="parameter">tli</replaceable> ]
       <indexterm><primary>START_REPLICATION</primary></indexterm>
      </term>
      <listitem>
       <para>
        Instructs server to start streaming WAL, starting at
-       WAL location <replaceable class="parameter">XXX/XXX</replaceable>.
+       WAL location <replaceable class="parameter">XXXXXXXXXXXXXXXX</replaceable>.
        If <literal>TIMELINE</literal> option is specified,
        streaming starts on timeline <replaceable class="parameter">tli</replaceable>;
        otherwise, the server's current timeline is selected. The server can
@@ -2714,12 +2714,12 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
     </varlistentry>
 
     <varlistentry id="protocol-replication-start-replication-slot-logical">
-     <term><literal>START_REPLICATION</literal> <literal>SLOT</literal> <replaceable class="parameter">slot_name</replaceable> <literal>LOGICAL</literal> <replaceable class="parameter">XXX/XXX</replaceable> [ ( <replaceable>option_name</replaceable> [ <replaceable>option_value</replaceable> ] [, ...] ) ]</term>
+     <term><literal>START_REPLICATION</literal> <literal>SLOT</literal> <replaceable class="parameter">slot_name</replaceable> <literal>LOGICAL</literal> <replaceable class="parameter">XXXXXXXXXXXXXXXX</replaceable> [ ( <replaceable>option_name</replaceable> [ <replaceable>option_value</replaceable> ] [, ...] ) ]</term>
      <listitem>
       <para>
        Instructs server to start streaming WAL for logical replication,
        starting at either WAL location <replaceable
-       class="parameter">XXX/XXX</replaceable> or the slot's
+       class="parameter">XXXXXXXXXXXXXXXX</replaceable> or the slot's
        <literal>confirmed_flush_lsn</literal> (see <xref
        linkend="view-pg-replication-slots"/>), whichever is greater. This
        behavior makes it easier for clients to avoid updating their local LSN
@@ -2761,7 +2761,7 @@ psql "dbname=postgres replication=database" -c "IDENTIFY_SYSTEM;"
        </varlistentry>
 
        <varlistentry>
-        <term><replaceable class="parameter">XXX/XXX</replaceable></term>
+        <term><replaceable class="parameter">XXXXXXXXXXXXXXXX</replaceable></term>
         <listitem>
          <para>
           The WAL location to begin streaming at.
diff --git a/doc/src/sgml/test-decoding.sgml b/doc/src/sgml/test-decoding.sgml
index 5d1ae8f4f52..426110b8b0c 100644
--- a/doc/src/sgml/test-decoding.sgml
+++ b/doc/src/sgml/test-decoding.sgml
@@ -25,16 +25,16 @@
 
 <programlisting>
 postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'include-xids', '0');
-   lsn     | xid |                       data
------------+-----+--------------------------------------------------
- 0/16D30F8 | 691 | BEGIN
- 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'
- 0/16D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'
- 0/16D32A0 | 691 | COMMIT
- 0/16D32D8 | 692 | BEGIN
- 0/16D3398 | 692 | table public.data: DELETE: id[int4]:2
- 0/16D3398 | 692 | table public.data: DELETE: id[int4]:3
- 0/16D3398 | 692 | COMMIT
+       lsn        | xid |                       data
+------------------+-----+---------------------------------------------------------
+ 00000000016D30F8 | 691 | BEGIN
+ 00000000016D32A0 | 691 | table public.data: INSERT: id[int4]:2 data[text]:'arg'
+ 00000000016D32A0 | 691 | table public.data: INSERT: id[int4]:3 data[text]:'demo'
+ 00000000016D32A0 | 691 | COMMIT
+ 00000000016D32D8 | 692 | BEGIN
+ 00000000016D3398 | 692 | table public.data: DELETE: id[int4]:2
+ 00000000016D3398 | 692 | table public.data: DELETE: id[int4]:3
+ 00000000016D3398 | 692 | COMMIT
 (8 rows)
 </programlisting>
  </para>
@@ -45,18 +45,18 @@ postgres=# SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'i
 
 <programlisting>
 postgres[33712]=#* SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL, 'stream-changes', '1');
-    lsn    | xid |                       data
------------+-----+--------------------------------------------------
- 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503
- 0/16B21F8 | 503 | streaming change for TXN 503
- 0/16B2300 | 503 | streaming change for TXN 503
- 0/16B2408 | 503 | streaming change for TXN 503
- 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503
- 0/16B21F8 | 503 | opening a streamed block for transaction TXN 503
- 0/16BECA8 | 503 | streaming change for TXN 503
- 0/16BEDB0 | 503 | streaming change for TXN 503
- 0/16BEEB8 | 503 | streaming change for TXN 503
- 0/16BEBA0 | 503 | closing a streamed block for transaction TXN 503
+       lsn        | xid |                       data
+-----------+-----+---------------------------------------------------------
+ 00000000016B21F8 | 503 | opening a streamed block for transaction TXN 503
+ 00000000016B21F8 | 503 | streaming change for TXN 503
+ 00000000016B2300 | 503 | streaming change for TXN 503
+ 00000000016B2408 | 503 | streaming change for TXN 503
+ 00000000016BEBA0 | 503 | closing a streamed block for transaction TXN 503
+ 00000000016B21F8 | 503 | opening a streamed block for transaction TXN 503
+ 00000000016BECA8 | 503 | streaming change for TXN 503
+ 00000000016BEDB0 | 503 | streaming change for TXN 503
+ 00000000016BEEB8 | 503 | streaming change for TXN 503
+ 00000000016BEBA0 | 503 | closing a streamed block for transaction TXN 503
 (10 rows)
 </programlisting>
  </para>
diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c
index e6d2b5fced1..be60cfc5c61 100644
--- a/src/backend/access/heap/rewriteheap.c
+++ b/src/backend/access/heap/rewriteheap.c
@@ -963,7 +963,7 @@ logical_rewrite_log_mapping(RewriteState state, TransactionId xid,
 		snprintf(path, MAXPGPATH,
 				 "%s/" LOGICAL_REWRITE_FORMAT,
 				 PG_LOGICAL_MAPPINGS_DIR, dboid, relid,
-				 LSN_FORMAT_ARGS(state->rs_begin_lsn),
+				 state->rs_begin_lsn,
 				 xid, GetCurrentTransactionId());
 
 		dclist_init(&src->mappings);
@@ -1083,7 +1083,7 @@ heap_xlog_logical_rewrite(XLogReaderState *r)
 	snprintf(path, MAXPGPATH,
 			 "%s/" LOGICAL_REWRITE_FORMAT,
 			 PG_LOGICAL_MAPPINGS_DIR, xlrec->mapped_db, xlrec->mapped_rel,
-			 LSN_FORMAT_ARGS(xlrec->start_lsn),
+			 xlrec->start_lsn,
 			 xlrec->mapped_xid, XLogRecGetXid(r));
 
 	fd = OpenTransientFile(path,
@@ -1181,8 +1181,6 @@ CheckPointLogicalRewriteHeap(void)
 		XLogRecPtr	lsn;
 		TransactionId rewrite_xid;
 		TransactionId create_xid;
-		uint32		hi,
-					lo;
 		PGFileType	de_type;
 
 		if (strcmp(mapping_de->d_name, ".") == 0 ||
@@ -1199,12 +1197,10 @@ CheckPointLogicalRewriteHeap(void)
 		if (strncmp(mapping_de->d_name, "map-", 4) != 0)
 			continue;
 
-		if (sscanf(mapping_de->d_name, LOGICAL_REWRITE_FORMAT,
-				   &dboid, &relid, &hi, &lo, &rewrite_xid, &create_xid) != 6)
+		if (sscanf(mapping_de->d_name, LOGICAL_REWRITE_FORMAT_SCANF,
+				   &dboid, &relid, &lsn, &rewrite_xid, &create_xid) != 5)
 			elog(ERROR, "could not parse filename \"%s\"", mapping_de->d_name);
 
-		lsn = ((uint64) hi) << 32 | lo;
-
 		if (lsn < cutoff || cutoff == InvalidXLogRecPtr)
 		{
 			elog(DEBUG1, "removing logical rewrite file \"%s\"", path);
diff --git a/src/backend/access/rmgrdesc/replorigindesc.c b/src/backend/access/rmgrdesc/replorigindesc.c
index 5dd74233996..4c6f9c53850 100644
--- a/src/backend/access/rmgrdesc/replorigindesc.c
+++ b/src/backend/access/rmgrdesc/replorigindesc.c
@@ -29,9 +29,9 @@ replorigin_desc(StringInfo buf, XLogReaderState *record)
 
 				xlrec = (xl_replorigin_set *) rec;
 
-				appendStringInfo(buf, "set %u; lsn %X/%X; force: %d",
+				appendStringInfo(buf, "set %u; lsn %016" PRIX64 "; force: %d",
 								 xlrec->node_id,
-								 LSN_FORMAT_ARGS(xlrec->remote_lsn),
+								 xlrec->remote_lsn,
 								 xlrec->force);
 				break;
 			}
diff --git a/src/backend/access/rmgrdesc/xactdesc.c b/src/backend/access/rmgrdesc/xactdesc.c
index 715cc1f7bad..4b03c6ae9f8 100644
--- a/src/backend/access/rmgrdesc/xactdesc.c
+++ b/src/backend/access/rmgrdesc/xactdesc.c
@@ -357,9 +357,9 @@ xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId
 
 	if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
 	{
-		appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
+		appendStringInfo(buf, "; origin: node %u, lsn %016" PRIX64 ", at %s",
 						 origin_id,
-						 LSN_FORMAT_ARGS(parsed.origin_lsn),
+						 parsed.origin_lsn,
 						 timestamptz_to_str(parsed.origin_timestamp));
 	}
 }
@@ -382,9 +382,9 @@ xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec, RepOriginId or
 
 	if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
 	{
-		appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
+		appendStringInfo(buf, "; origin: node %u, lsn %016" PRIX64 ", at %s",
 						 origin_id,
-						 LSN_FORMAT_ARGS(parsed.origin_lsn),
+						 parsed.origin_lsn,
 						 timestamptz_to_str(parsed.origin_timestamp));
 	}
 
@@ -416,9 +416,9 @@ xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec, RepOriginI
 	 * way as PrepareRedoAdd().
 	 */
 	if (origin_id != InvalidRepOriginId)
-		appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
+		appendStringInfo(buf, "; origin: node %u, lsn %016" PRIX64 ", at %s",
 						 origin_id,
-						 LSN_FORMAT_ARGS(parsed.origin_lsn),
+						 parsed.origin_lsn,
 						 timestamptz_to_str(parsed.origin_timestamp));
 }
 
diff --git a/src/backend/access/rmgrdesc/xlogdesc.c b/src/backend/access/rmgrdesc/xlogdesc.c
index 58040f28656..bf2fa5664aa 100644
--- a/src/backend/access/rmgrdesc/xlogdesc.c
+++ b/src/backend/access/rmgrdesc/xlogdesc.c
@@ -65,12 +65,12 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 	{
 		CheckPoint *checkpoint = (CheckPoint *) rec;
 
-		appendStringInfo(buf, "redo %X/%X; "
+		appendStringInfo(buf, "redo %016" PRIX64 "; "
 						 "tli %u; prev tli %u; fpw %s; wal_level %s; xid %u:%u; oid %u; multi %u; offset %u; "
 						 "oldest xid %u in DB %u; oldest multi %u in DB %u; "
 						 "oldest/newest commit timestamp xid: %u/%u; "
 						 "oldest running xid %u; %s",
-						 LSN_FORMAT_ARGS(checkpoint->redo),
+						 checkpoint->redo,
 						 checkpoint->ThisTimeLineID,
 						 checkpoint->PrevTimeLineID,
 						 checkpoint->fullPageWrites ? "true" : "false",
@@ -111,7 +111,7 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 		XLogRecPtr	startpoint;
 
 		memcpy(&startpoint, rec, sizeof(XLogRecPtr));
-		appendStringInfo(buf, "%X/%X", LSN_FORMAT_ARGS(startpoint));
+		appendStringInfo(buf, "%016" PRIX64, startpoint);
 	}
 	else if (info == XLOG_PARAMETER_CHANGE)
 	{
@@ -156,8 +156,8 @@ xlog_desc(StringInfo buf, XLogReaderState *record)
 		xl_overwrite_contrecord xlrec;
 
 		memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
-		appendStringInfo(buf, "lsn %X/%X; time %s",
-						 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
+		appendStringInfo(buf, "lsn %016" PRIX64 "; time %s",
+						 xlrec.overwritten_lsn,
 						 timestamptz_to_str(xlrec.overwrite_time));
 	}
 	else if (info == XLOG_CHECKPOINT_REDO)
diff --git a/src/backend/access/transam/timeline.c b/src/backend/access/transam/timeline.c
index a27f27cc037..0ccadc0b981 100644
--- a/src/backend/access/transam/timeline.c
+++ b/src/backend/access/transam/timeline.c
@@ -128,8 +128,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 		char	   *res;
 		char	   *ptr;
 		TimeLineID	tli;
-		uint32		switchpoint_hi;
-		uint32		switchpoint_lo;
+		XLogRecPtr	switchpoint;
 		int			nfields;
 
 		pgstat_report_wait_start(WAIT_EVENT_TIMELINE_HISTORY_READ);
@@ -154,7 +153,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 		if (*ptr == '\0' || *ptr == '#')
 			continue;
 
-		nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
+		nfields = sscanf(fline, "%u\t%" SCNx64, &tli, &switchpoint);
 
 		if (nfields < 1)
 		{
@@ -163,7 +162,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 					(errmsg("syntax error in history file: %s", fline),
 					 errhint("Expected a numeric timeline ID.")));
 		}
-		if (nfields != 3)
+		if (nfields != 2)
 			ereport(FATAL,
 					(errmsg("syntax error in history file: %s", fline),
 					 errhint("Expected a write-ahead log switchpoint location.")));
@@ -178,7 +177,7 @@ readTimeLineHistory(TimeLineID targetTLI)
 		entry = (TimeLineHistoryEntry *) palloc(sizeof(TimeLineHistoryEntry));
 		entry->tli = tli;
 		entry->begin = prevend;
-		entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
+		entry->end = switchpoint;
 		prevend = entry->end;
 
 		/* Build list with newest item first */
@@ -399,10 +398,10 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
 	 * parent file failed to end with one.
 	 */
 	snprintf(buffer, sizeof(buffer),
-			 "%s%u\t%X/%X\t%s\n",
+			 "%s%u\t%016" PRIX64 "\t%s\n",
 			 (srcfd < 0) ? "" : "\n",
 			 parentTLI,
-			 LSN_FORMAT_ARGS(switchpoint),
+			 switchpoint,
 			 reason);
 
 	nbytes = strlen(buffer);
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index eb8597df338..cbe7d4abe32 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -1426,21 +1426,21 @@ XlogReadTwoPhaseData(XLogRecPtr lsn, char **buf, int *len)
 		if (errormsg)
 			ereport(ERROR,
 					(errcode_for_file_access(),
-					 errmsg("could not read two-phase state from WAL at %X/%X: %s",
-							LSN_FORMAT_ARGS(lsn), errormsg)));
+					 errmsg("could not read two-phase state from WAL at %016" PRIX64 ": %s",
+							lsn, errormsg)));
 		else
 			ereport(ERROR,
 					(errcode_for_file_access(),
-					 errmsg("could not read two-phase state from WAL at %X/%X",
-							LSN_FORMAT_ARGS(lsn))));
+					 errmsg("could not read two-phase state from WAL at %016" PRIX64,
+							lsn)));
 	}
 
 	if (XLogRecGetRmid(xlogreader) != RM_XACT_ID ||
 		(XLogRecGetInfo(xlogreader) & XLOG_XACT_OPMASK) != XLOG_XACT_PREPARE)
 		ereport(ERROR,
 				(errcode_for_file_access(),
-				 errmsg("expected two-phase state data is not present in WAL at %X/%X",
-						LSN_FORMAT_ARGS(lsn))));
+				 errmsg("expected two-phase state data is not present in WAL at %016" PRIX64,
+						lsn)));
 
 	if (len != NULL)
 		*len = XLogRecGetDataLen(xlogreader);
@@ -2512,8 +2512,8 @@ PrepareRedoAdd(char *buf, XLogRecPtr start_lsn,
 			ereport(reachedConsistency ? ERROR : WARNING,
 					(errmsg("could not recover two-phase state file for transaction %u",
 							hdr->xid),
-					 errdetail("Two-phase state file has been found in WAL record %X/%X, but this transaction has already been restored from disk.",
-							   LSN_FORMAT_ARGS(start_lsn))));
+					 errdetail("Two-phase state file has been found in WAL record %016" PRIX64 ", but this transaction has already been restored from disk.",
+							   start_lsn)));
 			return;
 		}
 
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 799fc739e18..9f0986fcccc 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -1017,7 +1017,7 @@ XLogInsertRecord(XLogRecData *rdata,
 		oldCxt = MemoryContextSwitchTo(walDebugCxt);
 
 		initStringInfo(&buf);
-		appendStringInfo(&buf, "INSERT @ %X/%X: ", LSN_FORMAT_ARGS(EndPos));
+		appendStringInfo(&buf, "INSERT @ %016" PRIX64 ": ", EndPos);
 
 		/*
 		 * We have to piece together the WAL record data from the XLogRecData
@@ -1538,8 +1538,9 @@ WaitXLogInsertionsToFinish(XLogRecPtr upto)
 	if (upto > reservedUpto)
 	{
 		ereport(LOG,
-				(errmsg("request to flush past end of generated WAL; request %X/%X, current position %X/%X",
-						LSN_FORMAT_ARGS(upto), LSN_FORMAT_ARGS(reservedUpto))));
+				(errmsg("request to flush past end of generated WAL; request %016"
+						PRIX64 ", current position %016" PRIX64,
+						upto, reservedUpto)));
 		upto = reservedUpto;
 	}
 
@@ -1705,8 +1706,7 @@ GetXLogBuffer(XLogRecPtr ptr, TimeLineID tli)
 		endptr = pg_atomic_read_u64(&XLogCtl->xlblocks[idx]);
 
 		if (expectedEndPtr != endptr)
-			elog(PANIC, "could not find WAL buffer for %X/%X",
-				 LSN_FORMAT_ARGS(ptr));
+			elog(PANIC, "could not find WAL buffer for %016" PRIX64, ptr);
 	}
 	else
 	{
@@ -1765,9 +1765,10 @@ WALReadFromBuffers(char *dstbuf, XLogRecPtr startptr, Size count,
 	inserted = pg_atomic_read_u64(&XLogCtl->logInsertResult);
 	if (startptr + count > inserted)
 		ereport(ERROR,
-				errmsg("cannot read past end of generated WAL: requested %X/%X, current position %X/%X",
-					   LSN_FORMAT_ARGS(startptr + count),
-					   LSN_FORMAT_ARGS(inserted)));
+				errmsg("cannot read past end of generated WAL: requested %016"
+					   PRIX64 ", current position %016" PRIX64,
+					   startptr + count,
+					   inserted));
 
 	/*
 	 * Loop through the buffers without a lock. For each buffer, atomically
@@ -2148,8 +2149,8 @@ AdvanceXLInsertBuffer(XLogRecPtr upto, TimeLineID tli, bool opportunistic)
 #ifdef WAL_DEBUG
 	if (XLOG_DEBUG && npages > 0)
 	{
-		elog(DEBUG1, "initialized %d pages, up to %X/%X",
-			 npages, LSN_FORMAT_ARGS(NewPageEndPtr));
+		elog(DEBUG1, "initialized %d pages, up to %016" PRIX64,
+			 npages, NewPageEndPtr);
 	}
 #endif
 }
@@ -2359,9 +2360,10 @@ XLogWrite(XLogwrtRqst WriteRqst, TimeLineID tli, bool flexible)
 		XLogRecPtr	EndPtr = pg_atomic_read_u64(&XLogCtl->xlblocks[curridx]);
 
 		if (LogwrtResult.Write >= EndPtr)
-			elog(PANIC, "xlog write request %X/%X is past end of log %X/%X",
-				 LSN_FORMAT_ARGS(LogwrtResult.Write),
-				 LSN_FORMAT_ARGS(EndPtr));
+			elog(PANIC, "xlog write request %016" PRIX64
+				 " is past end of log %016" PRIX64,
+				 LogwrtResult.Write,
+				 EndPtr);
 
 		/* Advance LogwrtResult.Write to end of current buffer page */
 		LogwrtResult.Write = EndPtr;
@@ -2759,8 +2761,9 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
 		newMinRecoveryPoint = GetCurrentReplayRecPtr(&newMinRecoveryPointTLI);
 		if (!force && newMinRecoveryPoint < lsn)
 			elog(WARNING,
-				 "xlog min recovery request %X/%X is past current point %X/%X",
-				 LSN_FORMAT_ARGS(lsn), LSN_FORMAT_ARGS(newMinRecoveryPoint));
+				 "xlog min recovery request %016" PRIX64
+				 " is past current point %016" PRIX64,
+				 lsn, newMinRecoveryPoint);
 
 		/* update control file */
 		if (ControlFile->minRecoveryPoint < newMinRecoveryPoint)
@@ -2772,8 +2775,9 @@ UpdateMinRecoveryPoint(XLogRecPtr lsn, bool force)
 			LocalMinRecoveryPointTLI = newMinRecoveryPointTLI;
 
 			ereport(DEBUG2,
-					(errmsg_internal("updated min recovery point to %X/%X on timeline %u",
-									 LSN_FORMAT_ARGS(newMinRecoveryPoint),
+					(errmsg_internal("updated min recovery point to %016" PRIX64
+									 " on timeline %u",
+									 newMinRecoveryPoint,
 									 newMinRecoveryPointTLI)));
 		}
 	}
@@ -2812,10 +2816,11 @@ XLogFlush(XLogRecPtr record)
 
 #ifdef WAL_DEBUG
 	if (XLOG_DEBUG)
-		elog(LOG, "xlog flush request %X/%X; write %X/%X; flush %X/%X",
-			 LSN_FORMAT_ARGS(record),
-			 LSN_FORMAT_ARGS(LogwrtResult.Write),
-			 LSN_FORMAT_ARGS(LogwrtResult.Flush));
+		elog(LOG, "xlog flush request %016" PRIX64 "; write %016" PRIX64
+			 "; flush %016" PRIX64,
+			 record,
+			 LogwrtResult.Write,
+			 LogwrtResult.Flush);
 #endif
 
 	START_CRIT_SECTION();
@@ -2945,9 +2950,9 @@ XLogFlush(XLogRecPtr record)
 	 */
 	if (LogwrtResult.Flush < record)
 		elog(ERROR,
-			 "xlog flush request %X/%X is not satisfied --- flushed only to %X/%X",
-			 LSN_FORMAT_ARGS(record),
-			 LSN_FORMAT_ARGS(LogwrtResult.Flush));
+			 "xlog flush request %016" PRIX64 " is not satisfied --- flushed only to %016" PRIX64,
+			 record,
+			 LogwrtResult.Flush);
 }
 
 /*
@@ -3072,11 +3077,12 @@ XLogBackgroundFlush(void)
 
 #ifdef WAL_DEBUG
 	if (XLOG_DEBUG)
-		elog(LOG, "xlog bg flush request write %X/%X; flush: %X/%X, current is write %X/%X; flush %X/%X",
-			 LSN_FORMAT_ARGS(WriteRqst.Write),
-			 LSN_FORMAT_ARGS(WriteRqst.Flush),
-			 LSN_FORMAT_ARGS(LogwrtResult.Write),
-			 LSN_FORMAT_ARGS(LogwrtResult.Flush));
+		elog(LOG, "xlog bg flush request write %016" PRIX64 "; flush: %016" PRIX64
+			 ", current is write %016" PRIX64 "; flush %016" PRIX6,
+			 WriteRqst.Write,
+			 WriteRqst.Flush,
+			 LogwrtResult.Write,
+			 LogwrtResult.Flush);
 #endif
 
 	START_CRIT_SECTION();
@@ -6779,7 +6785,7 @@ LogCheckpointEnd(bool restartpoint)
 						"%d removed, %d recycled; write=%ld.%03d s, "
 						"sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, "
 						"longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, "
-						"estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X",
+						"estimate=%d kB; lsn=%016" PRIX64 ", redo lsn=%016" PRIX64,
 						CheckpointStats.ckpt_bufs_written,
 						(double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers,
 						CheckpointStats.ckpt_slru_written,
@@ -6794,8 +6800,8 @@ LogCheckpointEnd(bool restartpoint)
 						average_msecs / 1000, (int) (average_msecs % 1000),
 						(int) (PrevCheckPointDistance / 1024.0),
 						(int) (CheckPointDistanceEstimate / 1024.0),
-						LSN_FORMAT_ARGS(ControlFile->checkPoint),
-						LSN_FORMAT_ARGS(ControlFile->checkPointCopy.redo))));
+						ControlFile->checkPoint,
+						ControlFile->checkPointCopy.redo)));
 	else
 		ereport(LOG,
 				(errmsg("checkpoint complete: wrote %d buffers (%.1f%%), "
@@ -6803,7 +6809,7 @@ LogCheckpointEnd(bool restartpoint)
 						"%d removed, %d recycled; write=%ld.%03d s, "
 						"sync=%ld.%03d s, total=%ld.%03d s; sync files=%d, "
 						"longest=%ld.%03d s, average=%ld.%03d s; distance=%d kB, "
-						"estimate=%d kB; lsn=%X/%X, redo lsn=%X/%X",
+						"estimate=%d kB; lsn=%016" PRIX64 ", redo lsn=%016" PRIX64,
 						CheckpointStats.ckpt_bufs_written,
 						(double) CheckpointStats.ckpt_bufs_written * 100 / NBuffers,
 						CheckpointStats.ckpt_slru_written,
@@ -6818,8 +6824,8 @@ LogCheckpointEnd(bool restartpoint)
 						average_msecs / 1000, (int) (average_msecs % 1000),
 						(int) (PrevCheckPointDistance / 1024.0),
 						(int) (CheckPointDistanceEstimate / 1024.0),
-						LSN_FORMAT_ARGS(ControlFile->checkPoint),
-						LSN_FORMAT_ARGS(ControlFile->checkPointCopy.redo))));
+						ControlFile->checkPoint,
+						ControlFile->checkPointCopy.redo)));
 }
 
 /*
@@ -7495,8 +7501,9 @@ CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr pagePtr,
 	if (!RecoveryInProgress())
 		elog(ERROR, "can only be used at end of recovery");
 	if (pagePtr % XLOG_BLCKSZ != 0)
-		elog(ERROR, "invalid position for missing continuation record %X/%X",
-			 LSN_FORMAT_ARGS(pagePtr));
+		elog(ERROR,
+			 "invalid position for missing continuation record %016" PRIX64,
+			 pagePtr);
 
 	/* The current WAL insert position should be right after the page header */
 	startPos = pagePtr;
@@ -7506,8 +7513,9 @@ CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr pagePtr,
 		startPos += SizeOfXLogShortPHD;
 	recptr = GetXLogInsertRecPtr();
 	if (recptr != startPos)
-		elog(ERROR, "invalid WAL insert position %X/%X for OVERWRITE_CONTRECORD",
-			 LSN_FORMAT_ARGS(recptr));
+		elog(ERROR, "invalid WAL insert position %016" PRIX64
+			 " for OVERWRITE_CONTRECORD",
+			 recptr);
 
 	START_CRIT_SECTION();
 
@@ -7536,8 +7544,10 @@ CreateOverwriteContrecordRecord(XLogRecPtr aborted_lsn, XLogRecPtr pagePtr,
 
 	/* check that the record was inserted to the right place */
 	if (ProcLastRecPtr != startPos)
-		elog(ERROR, "OVERWRITE_CONTRECORD was inserted to unexpected position %X/%X",
-			 LSN_FORMAT_ARGS(ProcLastRecPtr));
+		elog(ERROR,
+			 "OVERWRITE_CONTRECORD was inserted to unexpected position %016"
+			 PRIX64,
+			 ProcLastRecPtr);
 
 	XLogFlush(recptr);
 
@@ -7605,9 +7615,9 @@ RecoveryRestartPoint(const CheckPoint *checkPoint, XLogReaderState *record)
 	if (XLogHaveInvalidPages())
 	{
 		elog(DEBUG2,
-			 "could not record restart point at %X/%X because there "
+			 "could not record restart point at %016" PRIX64 " because there "
 			 "are unresolved references to invalid pages",
-			 LSN_FORMAT_ARGS(checkPoint->redo));
+			 checkPoint->redo);
 		return;
 	}
 
@@ -7686,8 +7696,9 @@ CreateRestartPoint(int flags)
 		lastCheckPoint.redo <= ControlFile->checkPointCopy.redo)
 	{
 		ereport(DEBUG2,
-				(errmsg_internal("skipping restartpoint, already performed at %X/%X",
-								 LSN_FORMAT_ARGS(lastCheckPoint.redo))));
+				(errmsg_internal("skipping restartpoint, already performed at %016"
+								 PRIX64,
+								 lastCheckPoint.redo)));
 
 		UpdateMinRecoveryPoint(InvalidXLogRecPtr, true);
 		if (flags & CHECKPOINT_IS_SHUTDOWN)
@@ -7871,8 +7882,8 @@ CreateRestartPoint(int flags)
 
 	xtime = GetLatestXTime();
 	ereport((log_checkpoints ? LOG : DEBUG2),
-			(errmsg("recovery restart point at %X/%X",
-					LSN_FORMAT_ARGS(lastCheckPoint.redo)),
+			(errmsg("recovery restart point at %016" PRIX64,
+					lastCheckPoint.redo),
 			 xtime ? errdetail("Last completed transaction was at log time %s.",
 							   timestamptz_to_str(xtime)) : 0));
 
@@ -8135,8 +8146,8 @@ XLogRestorePoint(const char *rpName)
 	RecPtr = XLogInsert(RM_XLOG_ID, XLOG_RESTORE_POINT);
 
 	ereport(LOG,
-			(errmsg("restore point \"%s\" created at %X/%X",
-					rpName, LSN_FORMAT_ARGS(RecPtr))));
+			(errmsg("restore point \"%s\" created at %016" PRIX64,
+					rpName, RecPtr)));
 
 	return RecPtr;
 }
diff --git a/src/backend/access/transam/xlogbackup.c b/src/backend/access/transam/xlogbackup.c
index 342590e0a46..b300057c7b1 100644
--- a/src/backend/access/transam/xlogbackup.c
+++ b/src/backend/access/transam/xlogbackup.c
@@ -42,8 +42,8 @@ build_backup_content(BackupState *state, bool ishistoryfile)
 
 	XLByteToSeg(state->startpoint, startsegno, wal_segment_size);
 	XLogFileName(startxlogfile, state->starttli, startsegno, wal_segment_size);
-	appendStringInfo(result, "START WAL LOCATION: %X/%X (file %s)\n",
-					 LSN_FORMAT_ARGS(state->startpoint), startxlogfile);
+	appendStringInfo(result, "START WAL LOCATION: %016" PRIX64 " (file %s)\n",
+					 state->startpoint, startxlogfile);
 
 	if (ishistoryfile)
 	{
@@ -52,12 +52,12 @@ build_backup_content(BackupState *state, bool ishistoryfile)
 
 		XLByteToSeg(state->stoppoint, stopsegno, wal_segment_size);
 		XLogFileName(stopxlogfile, state->stoptli, stopsegno, wal_segment_size);
-		appendStringInfo(result, "STOP WAL LOCATION: %X/%X (file %s)\n",
-						 LSN_FORMAT_ARGS(state->stoppoint), stopxlogfile);
+		appendStringInfo(result, "STOP WAL LOCATION: %016" PRIX64 " (file %s)\n",
+						 state->stoppoint, stopxlogfile);
 	}
 
-	appendStringInfo(result, "CHECKPOINT LOCATION: %X/%X\n",
-					 LSN_FORMAT_ARGS(state->checkpointloc));
+	appendStringInfo(result, "CHECKPOINT LOCATION: %016" PRIX64 "\n",
+					 state->checkpointloc);
 	appendStringInfoString(result, "BACKUP METHOD: streamed\n");
 	appendStringInfo(result, "BACKUP FROM: %s\n",
 					 state->started_in_recovery ? "standby" : "primary");
@@ -81,8 +81,8 @@ build_backup_content(BackupState *state, bool ishistoryfile)
 	Assert(XLogRecPtrIsInvalid(state->istartpoint) == (state->istarttli == 0));
 	if (!XLogRecPtrIsInvalid(state->istartpoint))
 	{
-		appendStringInfo(result, "INCREMENTAL FROM LSN: %X/%X\n",
-						 LSN_FORMAT_ARGS(state->istartpoint));
+		appendStringInfo(result, "INCREMENTAL FROM LSN: %016" PRIX64 "\n",
+						 state->istartpoint);
 		appendStringInfo(result, "INCREMENTAL FROM TLI: %u\n",
 						 state->istarttli);
 	}
diff --git a/src/backend/access/transam/xlogprefetcher.c b/src/backend/access/transam/xlogprefetcher.c
index 7735562db01..8a8a1807d9a 100644
--- a/src/backend/access/transam/xlogprefetcher.c
+++ b/src/backend/access/transam/xlogprefetcher.c
@@ -546,8 +546,8 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
 
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 					elog(XLOGPREFETCHER_DEBUG_LEVEL,
-						 "suppressing all readahead until %X/%X is replayed due to possible TLI change",
-						 LSN_FORMAT_ARGS(record->lsn));
+						 "suppressing all readahead until %016" PRIX64 " is replayed due to possible TLI change",
+						 record->lsn);
 #endif
 
 					/* Fall through so we move past this record. */
@@ -579,9 +579,10 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
 
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 					elog(XLOGPREFETCHER_DEBUG_LEVEL,
-						 "suppressing prefetch in database %u until %X/%X is replayed due to raw file copy",
+						 "suppressing prefetch in database %u until %016" PRIX64
+						 " is replayed due to raw file copy",
 						 rlocator.dbOid,
-						 LSN_FORMAT_ARGS(record->lsn));
+						 record->lsn);
 #endif
 				}
 			}
@@ -607,11 +608,12 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
 
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 						elog(XLOGPREFETCHER_DEBUG_LEVEL,
-							 "suppressing prefetch in relation %u/%u/%u until %X/%X is replayed, which creates the relation",
+							 "suppressing prefetch in relation %u/%u/%u until %016"
+							 PRIX64 " is replayed, which creates the relation",
 							 xlrec->rlocator.spcOid,
 							 xlrec->rlocator.dbOid,
 							 xlrec->rlocator.relNumber,
-							 LSN_FORMAT_ARGS(record->lsn));
+							 record->lsn);
 #endif
 					}
 				}
@@ -630,12 +632,13 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
 
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 					elog(XLOGPREFETCHER_DEBUG_LEVEL,
-						 "suppressing prefetch in relation %u/%u/%u from block %u until %X/%X is replayed, which truncates the relation",
+						 "suppressing prefetch in relation %u/%u/%u from block %u until %016"
+						 PRIX64 " is replayed, which truncates the relation",
 						 xlrec->rlocator.spcOid,
 						 xlrec->rlocator.dbOid,
 						 xlrec->rlocator.relNumber,
 						 xlrec->blkno,
-						 LSN_FORMAT_ARGS(record->lsn));
+						 record->lsn);
 #endif
 				}
 			}
@@ -729,11 +732,11 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
 			{
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 				elog(XLOGPREFETCHER_DEBUG_LEVEL,
-					 "suppressing all prefetch in relation %u/%u/%u until %X/%X is replayed, because the relation does not exist on disk",
+					 "suppressing all prefetch in relation %u/%u/%u until %016" PRIX64 " is replayed, because the relation does not exist on disk",
 					 reln->smgr_rlocator.locator.spcOid,
 					 reln->smgr_rlocator.locator.dbOid,
 					 reln->smgr_rlocator.locator.relNumber,
-					 LSN_FORMAT_ARGS(record->lsn));
+					 record->lsn);
 #endif
 				XLogPrefetcherAddFilter(prefetcher, block->rlocator, 0,
 										record->lsn);
@@ -750,12 +753,12 @@ XLogPrefetcherNextBlock(uintptr_t pgsr_private, XLogRecPtr *lsn)
 			{
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 				elog(XLOGPREFETCHER_DEBUG_LEVEL,
-					 "suppressing prefetch in relation %u/%u/%u from block %u until %X/%X is replayed, because the relation is too small",
+					 "suppressing prefetch in relation %u/%u/%u from block %u until %016" PRIX64 " is replayed, because the relation is too small",
 					 reln->smgr_rlocator.locator.spcOid,
 					 reln->smgr_rlocator.locator.dbOid,
 					 reln->smgr_rlocator.locator.relNumber,
 					 block->blkno,
-					 LSN_FORMAT_ARGS(record->lsn));
+					 record->lsn);
 #endif
 				XLogPrefetcherAddFilter(prefetcher, block->rlocator, block->blkno,
 										record->lsn);
@@ -928,9 +931,9 @@ XLogPrefetcherIsFiltered(XLogPrefetcher *prefetcher, RelFileLocator rlocator,
 		{
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 			elog(XLOGPREFETCHER_DEBUG_LEVEL,
-				 "prefetch of %u/%u/%u block %u suppressed; filtering until LSN %X/%X is replayed (blocks >= %u filtered)",
+				 "prefetch of %u/%u/%u block %u suppressed; filtering until LSN %016" PRIX64 " is replayed (blocks >= %u filtered)",
 				 rlocator.spcOid, rlocator.dbOid, rlocator.relNumber, blockno,
-				 LSN_FORMAT_ARGS(filter->filter_until_replayed),
+				 filter->filter_until_replayed,
 				 filter->filter_from_block);
 #endif
 			return true;
@@ -944,9 +947,9 @@ XLogPrefetcherIsFiltered(XLogPrefetcher *prefetcher, RelFileLocator rlocator,
 		{
 #ifdef XLOGPREFETCHER_DEBUG_LEVEL
 			elog(XLOGPREFETCHER_DEBUG_LEVEL,
-				 "prefetch of %u/%u/%u block %u suppressed; filtering until LSN %X/%X is replayed (whole database)",
+				 "prefetch of %u/%u/%u block %u suppressed; filtering until LSN %016" PRIX64 " is replayed (whole database)",
 				 rlocator.spcOid, rlocator.dbOid, rlocator.relNumber, blockno,
-				 LSN_FORMAT_ARGS(filter->filter_until_replayed));
+				 filter->filter_until_replayed);
 #endif
 			return true;
 		}
diff --git a/src/backend/access/transam/xlogreader.c b/src/backend/access/transam/xlogreader.c
index 42f3b725ff0..3da34f7d711 100644
--- a/src/backend/access/transam/xlogreader.c
+++ b/src/backend/access/transam/xlogreader.c
@@ -617,8 +617,8 @@ restart:
 	}
 	else if (targetRecOff < pageHeaderSize)
 	{
-		report_invalid_record(state, "invalid record offset at %X/%X: expected at least %u, got %u",
-							  LSN_FORMAT_ARGS(RecPtr),
+		report_invalid_record(state, "invalid record offset at %016" PRIX64 ": expected at least %u, got %u",
+							  RecPtr,
 							  pageHeaderSize, targetRecOff);
 		goto err;
 	}
@@ -626,8 +626,8 @@ restart:
 	if ((((XLogPageHeader) state->readBuf)->xlp_info & XLP_FIRST_IS_CONTRECORD) &&
 		targetRecOff == pageHeaderSize)
 	{
-		report_invalid_record(state, "contrecord is requested by %X/%X",
-							  LSN_FORMAT_ARGS(RecPtr));
+		report_invalid_record(state, "contrecord is requested by %016" PRIX64,
+							  RecPtr);
 		goto err;
 	}
 
@@ -667,8 +667,8 @@ restart:
 		if (total_len < SizeOfXLogRecord)
 		{
 			report_invalid_record(state,
-								  "invalid record length at %X/%X: expected at least %u, got %u",
-								  LSN_FORMAT_ARGS(RecPtr),
+								  "invalid record length at %016" PRIX64 ": expected at least %u, got %u",
+								  RecPtr,
 								  (uint32) SizeOfXLogRecord, total_len);
 			goto err;
 		}
@@ -756,8 +756,9 @@ restart:
 			if (!(pageHeader->xlp_info & XLP_FIRST_IS_CONTRECORD))
 			{
 				report_invalid_record(state,
-									  "there is no contrecord flag at %X/%X",
-									  LSN_FORMAT_ARGS(RecPtr));
+									  "there is no contrecord flag at %016"
+									  PRIX64,
+									  RecPtr);
 				goto err;
 			}
 
@@ -769,10 +770,10 @@ restart:
 				total_len != (pageHeader->xlp_rem_len + gotlen))
 			{
 				report_invalid_record(state,
-									  "invalid contrecord length %u (expected %u) at %X/%X",
+									  "invalid contrecord length %u (expected %u) at %016" PRIX64,
 									  pageHeader->xlp_rem_len,
 									  total_len - gotlen,
-									  LSN_FORMAT_ARGS(RecPtr));
+									  RecPtr);
 				goto err;
 			}
 
@@ -1132,16 +1133,16 @@ ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
 	if (record->xl_tot_len < SizeOfXLogRecord)
 	{
 		report_invalid_record(state,
-							  "invalid record length at %X/%X: expected at least %u, got %u",
-							  LSN_FORMAT_ARGS(RecPtr),
+							  "invalid record length at %016" PRIX64 ": expected at least %u, got %u",
+							  RecPtr,
 							  (uint32) SizeOfXLogRecord, record->xl_tot_len);
 		return false;
 	}
 	if (!RmgrIdIsValid(record->xl_rmid))
 	{
 		report_invalid_record(state,
-							  "invalid resource manager ID %u at %X/%X",
-							  record->xl_rmid, LSN_FORMAT_ARGS(RecPtr));
+							  "invalid resource manager ID %u at %016" PRIX64,
+							  record->xl_rmid, RecPtr);
 		return false;
 	}
 	if (randAccess)
@@ -1153,9 +1154,10 @@ ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
 		if (!(record->xl_prev < RecPtr))
 		{
 			report_invalid_record(state,
-								  "record with incorrect prev-link %X/%X at %X/%X",
-								  LSN_FORMAT_ARGS(record->xl_prev),
-								  LSN_FORMAT_ARGS(RecPtr));
+								  "record with incorrect prev-link %016" PRIX64
+								  " at %016" PRIX64,
+								  record->xl_prev,
+								  RecPtr);
 			return false;
 		}
 	}
@@ -1169,9 +1171,10 @@ ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
 		if (record->xl_prev != PrevRecPtr)
 		{
 			report_invalid_record(state,
-								  "record with incorrect prev-link %X/%X at %X/%X",
-								  LSN_FORMAT_ARGS(record->xl_prev),
-								  LSN_FORMAT_ARGS(RecPtr));
+								  "record with incorrect prev-link %016" PRIX64
+								  " at %016" PRIX64,
+								  record->xl_prev,
+								  RecPtr);
 			return false;
 		}
 	}
@@ -1207,8 +1210,8 @@ ValidXLogRecord(XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)
 	if (!EQ_CRC32C(record->xl_crc, crc))
 	{
 		report_invalid_record(state,
-							  "incorrect resource manager data checksum in record at %X/%X",
-							  LSN_FORMAT_ARGS(recptr));
+							  "incorrect resource manager data checksum in record at %016" PRIX64,
+							  recptr);
 		return false;
 	}
 
@@ -1241,10 +1244,10 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
 		XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
 
 		report_invalid_record(state,
-							  "invalid magic number %04X in WAL segment %s, LSN %X/%X, offset %u",
+							  "invalid magic number %04X in WAL segment %s, LSN %016" PRIX64 ", offset %u",
 							  hdr->xlp_magic,
 							  fname,
-							  LSN_FORMAT_ARGS(recptr),
+							  recptr,
 							  offset);
 		return false;
 	}
@@ -1256,10 +1259,10 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
 		XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
 
 		report_invalid_record(state,
-							  "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u",
+							  "invalid info bits %04X in WAL segment %s, LSN %016" PRIX64 ", offset %u",
 							  hdr->xlp_info,
 							  fname,
-							  LSN_FORMAT_ARGS(recptr),
+							  recptr,
 							  offset);
 		return false;
 	}
@@ -1298,10 +1301,10 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
 
 		/* hmm, first page of file doesn't have a long header? */
 		report_invalid_record(state,
-							  "invalid info bits %04X in WAL segment %s, LSN %X/%X, offset %u",
+							  "invalid info bits %04X in WAL segment %s, LSN %016" PRIX64 ", offset %u",
 							  hdr->xlp_info,
 							  fname,
-							  LSN_FORMAT_ARGS(recptr),
+							  recptr,
 							  offset);
 		return false;
 	}
@@ -1318,10 +1321,10 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
 		XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
 
 		report_invalid_record(state,
-							  "unexpected pageaddr %X/%X in WAL segment %s, LSN %X/%X, offset %u",
-							  LSN_FORMAT_ARGS(hdr->xlp_pageaddr),
+							  "unexpected pageaddr %016" PRIX64 " in WAL segment %s, LSN %016" PRIX64 ", offset %u",
+							  hdr->xlp_pageaddr,
 							  fname,
-							  LSN_FORMAT_ARGS(recptr),
+							  recptr,
 							  offset);
 		return false;
 	}
@@ -1344,11 +1347,11 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
 			XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
 
 			report_invalid_record(state,
-								  "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%X, offset %u",
+								  "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %016" PRIX64 ", offset %u",
 								  hdr->xlp_tli,
 								  state->latestPageTLI,
 								  fname,
-								  LSN_FORMAT_ARGS(recptr),
+								  recptr,
 								  offset);
 			return false;
 		}
@@ -1756,9 +1759,9 @@ DecodeXLogRecord(XLogReaderState *state,
 			if (block_id <= decoded->max_block_id)
 			{
 				report_invalid_record(state,
-									  "out-of-order block_id %u at %X/%X",
+									  "out-of-order block_id %u at %016" PRIX64,
 									  block_id,
-									  LSN_FORMAT_ARGS(state->ReadRecPtr));
+									  state->ReadRecPtr);
 				goto err;
 			}
 			decoded->max_block_id = block_id;
@@ -1780,16 +1783,16 @@ DecodeXLogRecord(XLogReaderState *state,
 			if (blk->has_data && blk->data_len == 0)
 			{
 				report_invalid_record(state,
-									  "BKPBLOCK_HAS_DATA set, but no data included at %X/%X",
-									  LSN_FORMAT_ARGS(state->ReadRecPtr));
+									  "BKPBLOCK_HAS_DATA set, but no data included at %016" PRIX64,
+									  state->ReadRecPtr);
 				goto err;
 			}
 			if (!blk->has_data && blk->data_len != 0)
 			{
 				report_invalid_record(state,
-									  "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X",
+									  "BKPBLOCK_HAS_DATA not set, but data length is %u at %016" PRIX64,
 									  (unsigned int) blk->data_len,
-									  LSN_FORMAT_ARGS(state->ReadRecPtr));
+									  state->ReadRecPtr);
 				goto err;
 			}
 			datatotal += blk->data_len;
@@ -1823,11 +1826,11 @@ DecodeXLogRecord(XLogReaderState *state,
 					 blk->bimg_len == BLCKSZ))
 				{
 					report_invalid_record(state,
-										  "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X",
+										  "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %016" PRIX64,
 										  (unsigned int) blk->hole_offset,
 										  (unsigned int) blk->hole_length,
 										  (unsigned int) blk->bimg_len,
-										  LSN_FORMAT_ARGS(state->ReadRecPtr));
+										  state->ReadRecPtr);
 					goto err;
 				}
 
@@ -1839,10 +1842,10 @@ DecodeXLogRecord(XLogReaderState *state,
 					(blk->hole_offset != 0 || blk->hole_length != 0))
 				{
 					report_invalid_record(state,
-										  "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X",
+										  "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %016" PRIX64,
 										  (unsigned int) blk->hole_offset,
 										  (unsigned int) blk->hole_length,
-										  LSN_FORMAT_ARGS(state->ReadRecPtr));
+										  state->ReadRecPtr);
 					goto err;
 				}
 
@@ -1853,9 +1856,9 @@ DecodeXLogRecord(XLogReaderState *state,
 					blk->bimg_len == BLCKSZ)
 				{
 					report_invalid_record(state,
-										  "BKPIMAGE_COMPRESSED set, but block image length %u at %X/%X",
+										  "BKPIMAGE_COMPRESSED set, but block image length %u at %016" PRIX64,
 										  (unsigned int) blk->bimg_len,
-										  LSN_FORMAT_ARGS(state->ReadRecPtr));
+										  state->ReadRecPtr);
 					goto err;
 				}
 
@@ -1868,9 +1871,9 @@ DecodeXLogRecord(XLogReaderState *state,
 					blk->bimg_len != BLCKSZ)
 				{
 					report_invalid_record(state,
-										  "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %X/%X",
+										  "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %u at %016" PRIX64,
 										  (unsigned int) blk->data_len,
-										  LSN_FORMAT_ARGS(state->ReadRecPtr));
+										  state->ReadRecPtr);
 					goto err;
 				}
 			}
@@ -1884,8 +1887,8 @@ DecodeXLogRecord(XLogReaderState *state,
 				if (rlocator == NULL)
 				{
 					report_invalid_record(state,
-										  "BKPBLOCK_SAME_REL set but no previous rel at %X/%X",
-										  LSN_FORMAT_ARGS(state->ReadRecPtr));
+										  "BKPBLOCK_SAME_REL set but no previous rel at %016" PRIX64,
+										  state->ReadRecPtr);
 					goto err;
 				}
 
@@ -1896,8 +1899,8 @@ DecodeXLogRecord(XLogReaderState *state,
 		else
 		{
 			report_invalid_record(state,
-								  "invalid block_id %u at %X/%X",
-								  block_id, LSN_FORMAT_ARGS(state->ReadRecPtr));
+								  "invalid block_id %u at %016" PRIX64,
+								  block_id, state->ReadRecPtr);
 			goto err;
 		}
 	}
@@ -1963,8 +1966,8 @@ DecodeXLogRecord(XLogReaderState *state,
 
 shortdata_err:
 	report_invalid_record(state,
-						  "record with invalid length at %X/%X",
-						  LSN_FORMAT_ARGS(state->ReadRecPtr));
+						  "record with invalid length at %016" PRIX64,
+						  state->ReadRecPtr);
 err:
 	*errormsg = state->errormsg_buf;
 
@@ -2073,15 +2076,17 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
 		!record->record->blocks[block_id].in_use)
 	{
 		report_invalid_record(record,
-							  "could not restore image at %X/%X with invalid block %d specified",
-							  LSN_FORMAT_ARGS(record->ReadRecPtr),
+							  "could not restore image at %016" PRIX64
+							  " with invalid block %d specified",
+							  record->ReadRecPtr,
 							  block_id);
 		return false;
 	}
 	if (!record->record->blocks[block_id].has_image)
 	{
-		report_invalid_record(record, "could not restore image at %X/%X with invalid state, block %d",
-							  LSN_FORMAT_ARGS(record->ReadRecPtr),
+		report_invalid_record(record, "could not restore image at %016" PRIX64
+							  " with invalid state, block %d",
+							  record->ReadRecPtr,
 							  block_id);
 		return false;
 	}
@@ -2107,8 +2112,9 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
 									bkpb->bimg_len, BLCKSZ - bkpb->hole_length) <= 0)
 				decomp_success = false;
 #else
-			report_invalid_record(record, "could not restore image at %X/%X compressed with %s not supported by build, block %d",
-								  LSN_FORMAT_ARGS(record->ReadRecPtr),
+			report_invalid_record(record, "could not restore image at %016" PRIX64
+								  " compressed with %s not supported by build, block %d",
+								  record->ReadRecPtr,
 								  "LZ4",
 								  block_id);
 			return false;
@@ -2124,8 +2130,9 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
 			if (ZSTD_isError(decomp_result))
 				decomp_success = false;
 #else
-			report_invalid_record(record, "could not restore image at %X/%X compressed with %s not supported by build, block %d",
-								  LSN_FORMAT_ARGS(record->ReadRecPtr),
+			report_invalid_record(record, "could not restore image at %016"
+								  PRIX64 " compressed with %s not supported by build, block %d",
+								  record->ReadRecPtr,
 								  "zstd",
 								  block_id);
 			return false;
@@ -2133,16 +2140,18 @@ RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
 		}
 		else
 		{
-			report_invalid_record(record, "could not restore image at %X/%X compressed with unknown method, block %d",
-								  LSN_FORMAT_ARGS(record->ReadRecPtr),
+			report_invalid_record(record, "could not restore image at %016" PRIX64
+								  " compressed with unknown method, block %d",
+								  record->ReadRecPtr,
 								  block_id);
 			return false;
 		}
 
 		if (!decomp_success)
 		{
-			report_invalid_record(record, "could not decompress image at %X/%X, block %d",
-								  LSN_FORMAT_ARGS(record->ReadRecPtr),
+			report_invalid_record(record, "could not decompress image at %016" PRIX64
+								  ", block %d",
+								  record->ReadRecPtr,
 								  block_id);
 			return false;
 		}
diff --git a/src/backend/access/transam/xlogrecovery.c b/src/backend/access/transam/xlogrecovery.c
index 52f53fa12e0..4a6823e2b98 100644
--- a/src/backend/access/transam/xlogrecovery.c
+++ b/src/backend/access/transam/xlogrecovery.c
@@ -615,9 +615,11 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 		 * than ControlFile->checkPoint is used.
 		 */
 		ereport(LOG,
-				(errmsg("starting backup recovery with redo LSN %X/%X, checkpoint LSN %X/%X, on timeline ID %u",
-						LSN_FORMAT_ARGS(RedoStartLSN),
-						LSN_FORMAT_ARGS(CheckPointLoc),
+				(errmsg("starting backup recovery with redo LSN %016"
+						PRIX64 ", checkpoint LSN %016" PRIX64
+						", on timeline ID %u",
+						RedoStartLSN,
+						CheckPointLoc,
 						CheckPointTLI)));
 
 		/*
@@ -631,8 +633,8 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 			memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
 			wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
 			ereport(DEBUG1,
-					(errmsg_internal("checkpoint record is at %X/%X",
-									 LSN_FORMAT_ARGS(CheckPointLoc))));
+					(errmsg_internal("checkpoint record is at %016" PRIX64,
+									 CheckPointLoc)));
 			InRecovery = true;	/* force recovery even if SHUTDOWNED */
 
 			/*
@@ -647,8 +649,10 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 				if (!ReadRecord(xlogprefetcher, LOG, false,
 								checkPoint.ThisTimeLineID))
 					ereport(FATAL,
-							(errmsg("could not find redo location %X/%X referenced by checkpoint record at %X/%X",
-									LSN_FORMAT_ARGS(checkPoint.redo), LSN_FORMAT_ARGS(CheckPointLoc)),
+							(errmsg("could not find redo location %016" PRIX64
+									" referenced by checkpoint record at %016"
+									PRIX64,
+									checkPoint.redo, CheckPointLoc),
 							 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
 									 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
 									 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
@@ -658,8 +662,9 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 		else
 		{
 			ereport(FATAL,
-					(errmsg("could not locate required checkpoint record at %X/%X",
-							LSN_FORMAT_ARGS(CheckPointLoc)),
+					(errmsg("could not locate required checkpoint record at %016"
+							PRIX64,
+							CheckPointLoc),
 					 errhint("If you are restoring from a backup, touch \"%s/recovery.signal\" or \"%s/standby.signal\" and add required recovery options.\n"
 							 "If you are not restoring from a backup, try removing the file \"%s/backup_label\".\n"
 							 "Be careful: removing \"%s/backup_label\" will result in a corrupt cluster if restoring from a backup.",
@@ -768,8 +773,9 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 		 */
 		if (!XLogRecPtrIsInvalid(ControlFile->backupStartPoint))
 			ereport(LOG,
-					(errmsg("restarting backup recovery with redo LSN %X/%X",
-							LSN_FORMAT_ARGS(ControlFile->backupStartPoint))));
+					(errmsg("restarting backup recovery with redo LSN %016"
+							PRIX64,
+							ControlFile->backupStartPoint)));
 
 		/* Get the last valid checkpoint record. */
 		CheckPointLoc = ControlFile->checkPoint;
@@ -781,8 +787,8 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 		if (record != NULL)
 		{
 			ereport(DEBUG1,
-					(errmsg_internal("checkpoint record is at %X/%X",
-									 LSN_FORMAT_ARGS(CheckPointLoc))));
+					(errmsg_internal("checkpoint record is at %016" PRIX64,
+									 CheckPointLoc)));
 		}
 		else
 		{
@@ -793,8 +799,9 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 			 * simplify processing around checkpoints.
 			 */
 			ereport(PANIC,
-					(errmsg("could not locate a valid checkpoint record at %X/%X",
-							LSN_FORMAT_ARGS(CheckPointLoc))));
+					(errmsg("could not locate a valid checkpoint record at %016"
+							PRIX64,
+							CheckPointLoc)));
 		}
 		memcpy(&checkPoint, XLogRecGetData(xlogreader), sizeof(CheckPoint));
 		wasShutdown = ((record->xl_info & ~XLR_INFO_MASK) == XLOG_CHECKPOINT_SHUTDOWN);
@@ -819,8 +826,8 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 							recoveryTargetName)));
 		else if (recoveryTarget == RECOVERY_TARGET_LSN)
 			ereport(LOG,
-					(errmsg("starting point-in-time recovery to WAL location (LSN) \"%X/%X\"",
-							LSN_FORMAT_ARGS(recoveryTargetLSN))));
+					(errmsg("starting point-in-time recovery to WAL location (LSN) \"%016" PRIX64 "\"",
+							recoveryTargetLSN)));
 		else if (recoveryTarget == RECOVERY_TARGET_IMMEDIATE)
 			ereport(LOG,
 					(errmsg("starting point-in-time recovery to earliest consistent point")));
@@ -850,11 +857,11 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 				(errmsg("requested timeline %u is not a child of this server's history",
 						recoveryTargetTLI),
 		/* translator: %s is a backup_label file or a pg_control file */
-				 errdetail("Latest checkpoint in file \"%s\" is at %X/%X on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %X/%X.",
+				 errdetail("Latest checkpoint in file \"%s\" is at %016" PRIX64 " on timeline %u, but in the history of the requested timeline, the server forked off from that timeline at %016" PRIX64 ".",
 						   haveBackupLabel ? "backup_label" : "pg_control",
-						   LSN_FORMAT_ARGS(CheckPointLoc),
+						   CheckPointLoc,
 						   CheckPointTLI,
-						   LSN_FORMAT_ARGS(switchpoint))));
+						   switchpoint)));
 	}
 
 	/*
@@ -865,14 +872,14 @@ InitWalRecovery(ControlFileData *ControlFile, bool *wasShutdown_ptr,
 		tliOfPointInHistory(ControlFile->minRecoveryPoint - 1, expectedTLEs) !=
 		ControlFile->minRecoveryPointTLI)
 		ereport(FATAL,
-				(errmsg("requested timeline %u does not contain minimum recovery point %X/%X on timeline %u",
+				(errmsg("requested timeline %u does not contain minimum recovery point %016" PRIX64 " on timeline %u",
 						recoveryTargetTLI,
-						LSN_FORMAT_ARGS(ControlFile->minRecoveryPoint),
+						ControlFile->minRecoveryPoint,
 						ControlFile->minRecoveryPointTLI)));
 
 	ereport(DEBUG1,
-			(errmsg_internal("redo record is at %X/%X; shutdown %s",
-							 LSN_FORMAT_ARGS(checkPoint.redo),
+			(errmsg_internal("redo record is at %016" PRIX64 "; shutdown %s",
+							 checkPoint.redo,
 							 wasShutdown ? "true" : "false")));
 	ereport(DEBUG1,
 			(errmsg_internal("next transaction ID: " UINT64_FORMAT "; next OID: %u",
@@ -1220,8 +1227,7 @@ read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI,
 	char		backupfrom[20];
 	char		backuplabel[MAXPGPATH];
 	char		backuptime[128];
-	uint32		hi,
-				lo;
+	XLogRecPtr	dummy_lsn;
 
 	/* suppress possible uninitialized-variable warnings */
 	*checkPointLoc = InvalidXLogRecPtr;
@@ -1248,19 +1254,17 @@ read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI,
 	 * is pretty crude, but we are not expecting any variability in the file
 	 * format).
 	 */
-	if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %08X%16s)%c",
-			   &hi, &lo, &tli_from_walseg, startxlogfilename, &ch) != 5 || ch != '\n')
+	if (fscanf(lfp, "START WAL LOCATION: %" SCNx64 " (file %08X%16s)%c",
+			   &RedoStartLSN, &tli_from_walseg, startxlogfilename, &ch) != 4 || ch != '\n')
 		ereport(FATAL,
 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 				 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
-	RedoStartLSN = ((uint64) hi) << 32 | lo;
 	RedoStartTLI = tli_from_walseg;
-	if (fscanf(lfp, "CHECKPOINT LOCATION: %X/%X%c",
-			   &hi, &lo, &ch) != 3 || ch != '\n')
+	if (fscanf(lfp, "CHECKPOINT LOCATION: %" SCNx64 "%c",
+			   checkPointLoc, &ch) != 2 || ch != '\n')
 		ereport(FATAL,
 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 				 errmsg("invalid data in file \"%s\"", BACKUP_LABEL_FILE)));
-	*checkPointLoc = ((uint64) hi) << 32 | lo;
 	*backupLabelTLI = tli_from_walseg;
 
 	/*
@@ -1327,7 +1331,7 @@ read_backup_label(XLogRecPtr *checkPointLoc, TimeLineID *backupLabelTLI,
 								 tli_from_file, BACKUP_LABEL_FILE)));
 	}
 
-	if (fscanf(lfp, "INCREMENTAL FROM LSN: %X/%X\n", &hi, &lo) > 0)
+	if (fscanf(lfp, "INCREMENTAL FROM LSN: %" SCNx64 "\n", &dummy_lsn) > 0)
 		ereport(FATAL,
 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 				 errmsg("this is an incremental backup, not a data directory"),
@@ -1717,8 +1721,9 @@ PerformWalRecovery(void)
 		if (record->xl_rmid != RM_XLOG_ID ||
 			(record->xl_info & ~XLR_INFO_MASK) != XLOG_CHECKPOINT_REDO)
 			ereport(FATAL,
-					(errmsg("unexpected record type found at redo point %X/%X",
-							LSN_FORMAT_ARGS(xlogreader->ReadRecPtr))));
+					(errmsg("unexpected record type found at redo point %016"
+							PRIX64,
+							xlogreader->ReadRecPtr)));
 	}
 	else
 	{
@@ -1740,8 +1745,7 @@ PerformWalRecovery(void)
 		RmgrStartup();
 
 		ereport(LOG,
-				(errmsg("redo starts at %X/%X",
-						LSN_FORMAT_ARGS(xlogreader->ReadRecPtr))));
+				(errmsg("redo starts at %016" PRIX64, xlogreader->ReadRecPtr)));
 
 		/* Prepare to report progress of the redo phase. */
 		if (!StandbyMode)
@@ -1753,8 +1757,8 @@ PerformWalRecovery(void)
 		do
 		{
 			if (!StandbyMode)
-				ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %X/%X",
-										 LSN_FORMAT_ARGS(xlogreader->ReadRecPtr));
+				ereport_startup_progress("redo in progress, elapsed time: %ld.%02d s, current LSN: %016" PRIX64,
+										 xlogreader->ReadRecPtr);
 
 #ifdef WAL_DEBUG
 			if (XLOG_DEBUG)
@@ -1762,9 +1766,9 @@ PerformWalRecovery(void)
 				StringInfoData buf;
 
 				initStringInfo(&buf);
-				appendStringInfo(&buf, "REDO @ %X/%X; LSN %X/%X: ",
-								 LSN_FORMAT_ARGS(xlogreader->ReadRecPtr),
-								 LSN_FORMAT_ARGS(xlogreader->EndRecPtr));
+				appendStringInfo(&buf, "REDO @ %016" PRIX64 "; LSN %016" PRIX64 ": ",
+								 xlogreader->ReadRecPtr,
+								 xlogreader->EndRecPtr);
 				xlog_outrec(&buf, xlogreader);
 				appendStringInfoString(&buf, " - ");
 				xlog_outdesc(&buf, xlogreader);
@@ -1875,8 +1879,8 @@ PerformWalRecovery(void)
 		RmgrCleanup();
 
 		ereport(LOG,
-				(errmsg("redo done at %X/%X system usage: %s",
-						LSN_FORMAT_ARGS(xlogreader->ReadRecPtr),
+				(errmsg("redo done at %016" PRIX64 " system usage: %s",
+						xlogreader->ReadRecPtr,
 						pg_rusage_show(&ru0))));
 		xtime = GetLatestXTime();
 		if (xtime)
@@ -2087,17 +2091,18 @@ xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI)
 
 		memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_overwrite_contrecord));
 		if (xlrec.overwritten_lsn != record->overwrittenRecPtr)
-			elog(FATAL, "mismatching overwritten LSN %X/%X -> %X/%X",
-				 LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
-				 LSN_FORMAT_ARGS(record->overwrittenRecPtr));
+			elog(FATAL, "mismatching overwritten LSN %016" PRIX64 " -> %016" PRIX64,
+				 xlrec.overwritten_lsn,
+				 record->overwrittenRecPtr);
 
 		/* We have safely skipped the aborted record */
 		abortedRecPtr = InvalidXLogRecPtr;
 		missingContrecPtr = InvalidXLogRecPtr;
 
 		ereport(LOG,
-				(errmsg("successfully skipped missing contrecord at %X/%X, overwritten at %s",
-						LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
+				(errmsg("successfully skipped missing contrecord at %016" PRIX64
+						", overwritten at %s",
+						xlrec.overwritten_lsn,
 						timestamptz_to_str(xlrec.overwrite_time))));
 
 		/* Verifying the record should only happen once */
@@ -2124,8 +2129,9 @@ xlogrecovery_redo(XLogReaderState *record, TimeLineID replayTLI)
 			backupEndPoint = lsn;
 		}
 		else
-			elog(DEBUG1, "saw end-of-backup record for backup starting at %X/%X, waiting for %X/%X",
-				 LSN_FORMAT_ARGS(startpoint), LSN_FORMAT_ARGS(backupStartPoint));
+			elog(DEBUG1, "saw end-of-backup record for backup starting at %016"
+				 PRIX64 ", waiting for %016" PRIX64,
+				 startpoint, backupStartPoint);
 	}
 }
 
@@ -2219,9 +2225,10 @@ CheckRecoveryConsistency(void)
 		backupEndRequired = false;
 
 		ereport(LOG,
-				(errmsg("completed backup recovery with redo LSN %X/%X and end LSN %X/%X",
-						LSN_FORMAT_ARGS(saveBackupStartPoint),
-						LSN_FORMAT_ARGS(saveBackupEndPoint))));
+				(errmsg("completed backup recovery with redo LSN %016" PRIX64
+						" and end LSN %016" PRIX64,
+						saveBackupStartPoint,
+						saveBackupEndPoint)));
 	}
 
 	/*
@@ -2249,8 +2256,8 @@ CheckRecoveryConsistency(void)
 
 		reachedConsistency = true;
 		ereport(LOG,
-				(errmsg("consistent recovery state reached at %X/%X",
-						LSN_FORMAT_ARGS(lastReplayedEndRecPtr))));
+				(errmsg("consistent recovery state reached at %016" PRIX64,
+						lastReplayedEndRecPtr)));
 	}
 
 	/*
@@ -2287,8 +2294,8 @@ rm_redo_error_callback(void *arg)
 	xlog_block_info(&buf, record);
 
 	/* translator: %s is a WAL record description */
-	errcontext("WAL redo at %X/%X for %s",
-			   LSN_FORMAT_ARGS(record->ReadRecPtr),
+	errcontext("WAL redo at %016" PRIX64 " for %s",
+			   record->ReadRecPtr,
 			   buf.data);
 
 	pfree(buf.data);
@@ -2322,8 +2329,8 @@ xlog_outdesc(StringInfo buf, XLogReaderState *record)
 static void
 xlog_outrec(StringInfo buf, XLogReaderState *record)
 {
-	appendStringInfo(buf, "prev %X/%X; xid %u",
-					 LSN_FORMAT_ARGS(XLogRecGetPrev(record)),
+	appendStringInfo(buf, "prev %016" PRIX64 "; xid %u",
+					 XLogRecGetPrev(record),
 					 XLogRecGetXid(record));
 
 	appendStringInfo(buf, "; len %u",
@@ -2410,9 +2417,9 @@ checkTimeLineSwitch(XLogRecPtr lsn, TimeLineID newTLI, TimeLineID prevTLI,
 		lsn < minRecoveryPoint &&
 		newTLI > minRecoveryPointTLI)
 		ereport(PANIC,
-				(errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %X/%X on timeline %u",
+				(errmsg("unexpected timeline ID %u in checkpoint record, before reaching minimum recovery point %016" PRIX64 " on timeline %u",
 						newTLI,
-						LSN_FORMAT_ARGS(minRecoveryPoint),
+						minRecoveryPoint,
 						minRecoveryPointTLI)));
 
 	/* Looks good */
@@ -2615,8 +2622,9 @@ recoveryStopsBefore(XLogReaderState *record)
 		recoveryStopTime = 0;
 		recoveryStopName[0] = '\0';
 		ereport(LOG,
-				(errmsg("recovery stopping before WAL location (LSN) \"%X/%X\"",
-						LSN_FORMAT_ARGS(recoveryStopLSN))));
+				(errmsg("recovery stopping before WAL location (LSN) \"%016"
+						PRIX64 "\"",
+						recoveryStopLSN)));
 		return true;
 	}
 
@@ -2783,8 +2791,9 @@ recoveryStopsAfter(XLogReaderState *record)
 		recoveryStopTime = 0;
 		recoveryStopName[0] = '\0';
 		ereport(LOG,
-				(errmsg("recovery stopping after WAL location (LSN) \"%X/%X\"",
-						LSN_FORMAT_ARGS(recoveryStopLSN))));
+				(errmsg("recovery stopping after WAL location (LSN) \"%016"
+						PRIX64 "\"",
+						recoveryStopLSN)));
 		return true;
 	}
 
@@ -2904,9 +2913,9 @@ getRecoveryStopReason(void)
 				 timestamptz_to_str(recoveryStopTime));
 	else if (recoveryTarget == RECOVERY_TARGET_LSN)
 		snprintf(reason, sizeof(reason),
-				 "%s LSN %X/%X\n",
+				 "%s LSN %016" PRIX64 "\n",
 				 recoveryStopAfter ? "after" : "before",
-				 LSN_FORMAT_ARGS(recoveryStopLSN));
+				 recoveryStopLSN);
 	else if (recoveryTarget == RECOVERY_TARGET_NAME)
 		snprintf(reason, sizeof(reason),
 				 "at restore point \"%s\"",
@@ -3207,10 +3216,10 @@ ReadRecord(XLogPrefetcher *xlogprefetcher, int emode,
 			XLogFileName(fname, xlogreader->seg.ws_tli, segno,
 						 wal_segment_size);
 			ereport(emode_for_corrupt_record(emode, xlogreader->EndRecPtr),
-					(errmsg("unexpected timeline ID %u in WAL segment %s, LSN %X/%X, offset %u",
+					(errmsg("unexpected timeline ID %u in WAL segment %s, LSN %016" PRIX64 ", offset %u",
 							xlogreader->latestPageTLI,
 							fname,
-							LSN_FORMAT_ARGS(xlogreader->latestPagePtr),
+							xlogreader->latestPagePtr,
 							offset)));
 			record = NULL;
 		}
@@ -3423,15 +3432,17 @@ retry:
 			errno = save_errno;
 			ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
 					(errcode_for_file_access(),
-					 errmsg("could not read from WAL segment %s, LSN %X/%X, offset %u: %m",
-							fname, LSN_FORMAT_ARGS(targetPagePtr),
+					 errmsg("could not read from WAL segment %s, LSN %016" PRIX64
+							", offset %u: %m",
+							fname, targetPagePtr,
 							readOff)));
 		}
 		else
 			ereport(emode_for_corrupt_record(emode, targetPagePtr + reqLen),
 					(errcode(ERRCODE_DATA_CORRUPTED),
-					 errmsg("could not read from WAL segment %s, LSN %X/%X, offset %u: read %d of %zu",
-							fname, LSN_FORMAT_ARGS(targetPagePtr),
+					 errmsg("could not read from WAL segment %s, LSN %016" PRIX64
+							", offset %u: read %d of %zu",
+							fname, targetPagePtr,
 							readOff, r, (Size) XLOG_BLCKSZ)));
 		goto next_record_is_invalid;
 	}
@@ -3712,8 +3723,9 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 						wait_time = wal_retrieve_retry_interval -
 							TimestampDifferenceMilliseconds(last_fail_time, now);
 
-						elog(LOG, "waiting for WAL to become available at %X/%X",
-							 LSN_FORMAT_ARGS(RecPtr));
+						elog(LOG, "waiting for WAL to become available at %016"
+							 PRIX64,
+							 RecPtr);
 
 						/* Do background tasks that might benefit us later. */
 						KnownAssignedTransactionIdsIdleMaintenance();
@@ -3858,8 +3870,8 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
 							tli = tliOfPointInHistory(tliRecPtr, expectedTLEs);
 
 							if (curFileTLI > 0 && tli < curFileTLI)
-								elog(ERROR, "according to history file, WAL location %X/%X belongs to timeline %u, but previous recovered WAL file came from timeline %u",
-									 LSN_FORMAT_ARGS(tliRecPtr),
+								elog(ERROR, "according to history file, WAL location %016" PRIX64 " belongs to timeline %u, but previous recovered WAL file came from timeline %u",
+									 tliRecPtr,
 									 tli, curFileTLI);
 						}
 						curFileTLI = tli;
@@ -4171,10 +4183,10 @@ rescanLatestTimeLine(TimeLineID replayTLI, XLogRecPtr replayLSN)
 	if (currentTle->end < replayLSN)
 	{
 		ereport(LOG,
-				(errmsg("new timeline %u forked off current database system timeline %u before current recovery point %X/%X",
+				(errmsg("new timeline %u forked off current database system timeline %u before current recovery point %016" PRIX64,
 						newtarget,
 						replayTLI,
-						LSN_FORMAT_ARGS(replayLSN))));
+						replayLSN)));
 		return false;
 	}
 
diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c
index b61a0eb4014..95efb49dcd1 100644
--- a/src/backend/access/transam/xlogutils.c
+++ b/src/backend/access/transam/xlogutils.c
@@ -795,9 +795,9 @@ XLogReadDetermineTimeline(XLogReaderState *state, XLogRecPtr wantPage,
 
 		list_free_deep(timelineHistory);
 
-		elog(DEBUG3, "switched to timeline %u valid until %X/%X",
+		elog(DEBUG3, "switched to timeline %u valid until %016" PRIX64,
 			 state->currTLI,
-			 LSN_FORMAT_ARGS(state->currTLIValidUntil));
+			 state->currTLIValidUntil);
 	}
 }
 
diff --git a/src/backend/backup/backup_manifest.c b/src/backend/backup/backup_manifest.c
index 22e2be37c95..dd8eb2ff5a2 100644
--- a/src/backend/backup/backup_manifest.c
+++ b/src/backend/backup/backup_manifest.c
@@ -281,11 +281,11 @@ AddWALInfoToBackupManifest(backup_manifest_info *manifest, XLogRecPtr startptr,
 		}
 
 		AppendToManifest(manifest,
-						 "%s{ \"Timeline\": %u, \"Start-LSN\": \"%X/%X\", \"End-LSN\": \"%X/%X\" }",
+						 "%s{ \"Timeline\": %u, \"Start-LSN\": \"%016" PRIX64 "\", \"End-LSN\": \"%016" PRIX64 "\" }",
 						 first_wal_range ? "" : ",\n",
 						 entry->tli,
-						 LSN_FORMAT_ARGS(tl_beginptr),
-						 LSN_FORMAT_ARGS(endptr));
+						 tl_beginptr,
+						 endptr);
 
 		if (starttli == entry->tli)
 		{
diff --git a/src/backend/backup/basebackup_copy.c b/src/backend/backup/basebackup_copy.c
index a284ce318ff..5fd6e0c0072 100644
--- a/src/backend/backup/basebackup_copy.c
+++ b/src/backend/backup/basebackup_copy.c
@@ -361,7 +361,7 @@ SendXlogRecPtrResult(XLogRecPtr ptr, TimeLineID tli)
 	tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
 	/* Data row */
-	values[0] = CStringGetTextDatum(psprintf("%X/%X", LSN_FORMAT_ARGS(ptr)));
+	values[0] = CStringGetTextDatum(psprintf("%016" PRIX64, ptr));
 	values[1] = Int64GetDatum(tli);
 	do_tup_output(tstate, values, nulls);
 
diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c
index 51543699e83..a7bc0dc8bc1 100644
--- a/src/backend/backup/basebackup_incremental.c
+++ b/src/backend/backup/basebackup_incremental.c
@@ -409,20 +409,20 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
 			if (range->start_lsn < tlep[i]->begin)
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("manifest requires WAL from initial timeline %u starting at %X/%X, but that timeline begins at %X/%X",
+						 errmsg("manifest requires WAL from initial timeline %u starting at %016" PRIX64 ", but that timeline begins at %016" PRIX64,
 								range->tli,
-								LSN_FORMAT_ARGS(range->start_lsn),
-								LSN_FORMAT_ARGS(tlep[i]->begin))));
+								range->start_lsn,
+								tlep[i]->begin)));
 		}
 		else
 		{
 			if (range->start_lsn != tlep[i]->begin)
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("manifest requires WAL from continuation timeline %u starting at %X/%X, but that timeline begins at %X/%X",
+						 errmsg("manifest requires WAL from continuation timeline %u starting at %016" PRIX64 ", but that timeline begins at %016" PRIX64,
 								range->tli,
-								LSN_FORMAT_ARGS(range->start_lsn),
-								LSN_FORMAT_ARGS(tlep[i]->begin))));
+								range->start_lsn,
+								tlep[i]->begin)));
 		}
 
 		if (range->tli == latest_wal_range_tli)
@@ -430,10 +430,10 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
 			if (range->end_lsn > backup_state->startpoint)
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("manifest requires WAL from final timeline %u ending at %X/%X, but this backup starts at %X/%X",
+						 errmsg("manifest requires WAL from final timeline %u ending at %016" PRIX64 ", but this backup starts at %016" PRIX64,
 								range->tli,
-								LSN_FORMAT_ARGS(range->end_lsn),
-								LSN_FORMAT_ARGS(backup_state->startpoint)),
+								range->end_lsn,
+								backup_state->startpoint),
 						 errhint("This can happen for incremental backups on a standby if there was little activity since the previous backup.")));
 		}
 		else
@@ -441,10 +441,10 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
 			if (range->end_lsn != tlep[i]->end)
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("manifest requires WAL from non-final timeline %u ending at %X/%X, but this server switched timelines at %X/%X",
+						 errmsg("manifest requires WAL from non-final timeline %u ending at %016" PRIX64 ", but this server switched timelines at %016" PRIX64,
 								range->tli,
-								LSN_FORMAT_ARGS(range->end_lsn),
-								LSN_FORMAT_ARGS(tlep[i]->end))));
+								range->end_lsn,
+								tlep[i]->end)));
 		}
 
 	}
@@ -522,19 +522,19 @@ PrepareForIncrementalBackup(IncrementalBackupInfo *ib,
 			if (XLogRecPtrIsInvalid(tli_missing_lsn))
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("WAL summaries are required on timeline %u from %X/%X to %X/%X, but no summaries for that timeline and LSN range exist",
+						 errmsg("WAL summaries are required on timeline %u from %016" PRIX64 " to %016" PRIX64 ", but no summaries for that timeline and LSN range exist",
 								tle->tli,
-								LSN_FORMAT_ARGS(tli_start_lsn),
-								LSN_FORMAT_ARGS(tli_end_lsn))));
+								tli_start_lsn,
+								tli_end_lsn)));
 			else
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-						 errmsg("WAL summaries are required on timeline %u from %X/%X to %X/%X, but the summaries for that timeline and LSN range are incomplete",
+						 errmsg("WAL summaries are required on timeline %u from %016" PRIX64 " to %016" PRIX64 ", but the summaries for that timeline and LSN range are incomplete",
 								tle->tli,
-								LSN_FORMAT_ARGS(tli_start_lsn),
-								LSN_FORMAT_ARGS(tli_end_lsn)),
-						 errdetail("The first unsummarized LSN in this range is %X/%X.",
-								   LSN_FORMAT_ARGS(tli_missing_lsn))));
+								tli_start_lsn,
+								tli_end_lsn),
+						 errdetail("The first unsummarized LSN in this range is %016" PRIX64 ".",
+								   tli_missing_lsn)));
 		}
 
 		/*
diff --git a/src/backend/backup/walsummary.c b/src/backend/backup/walsummary.c
index c7a2c65cc6a..4805ed5ef38 100644
--- a/src/backend/backup/walsummary.c
+++ b/src/backend/backup/walsummary.c
@@ -208,10 +208,10 @@ OpenWalSummaryFile(WalSummaryFile *ws, bool missing_ok)
 	File		file;
 
 	snprintf(path, MAXPGPATH,
-			 XLOGDIR "/summaries/%08X%08X%08X%08X%08X.summary",
+			 XLOGDIR "/summaries/%08X%016" PRIX64 "%016" PRIX64 ".summary",
 			 ws->tli,
-			 LSN_FORMAT_ARGS(ws->start_lsn),
-			 LSN_FORMAT_ARGS(ws->end_lsn));
+			 ws->start_lsn,
+			 ws->end_lsn);
 
 	file = PathNameOpenFile(path, O_RDONLY);
 	if (file < 0 && (errno != EEXIST || !missing_ok))
@@ -233,10 +233,10 @@ RemoveWalSummaryIfOlderThan(WalSummaryFile *ws, time_t cutoff_time)
 	struct stat statbuf;
 
 	snprintf(path, MAXPGPATH,
-			 XLOGDIR "/summaries/%08X%08X%08X%08X%08X.summary",
+			 XLOGDIR "/summaries/%08X%016" PRIX64 "%016" PRIX64 ".summary",
 			 ws->tli,
-			 LSN_FORMAT_ARGS(ws->start_lsn),
-			 LSN_FORMAT_ARGS(ws->end_lsn));
+			 ws->start_lsn,
+			 ws->end_lsn);
 
 	if (lstat(path, &statbuf) != 0)
 	{
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 4aec73bcc6b..826db2eb450 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1539,9 +1539,9 @@ AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt,
 					if (!XLogRecPtrIsInvalid(remote_lsn) && opts.lsn < remote_lsn)
 						ereport(ERROR,
 								(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-								 errmsg("skip WAL location (LSN %X/%X) must be greater than origin LSN %X/%X",
-										LSN_FORMAT_ARGS(opts.lsn),
-										LSN_FORMAT_ARGS(remote_lsn))));
+								 errmsg("skip WAL location (LSN %016" PRIX64 ") must be greater than origin LSN %016" PRIX64,
+										opts.lsn,
+										remote_lsn)));
 				}
 
 				values[Anum_pg_subscription_subskiplsn - 1] = LSNGetDatum(opts.lsn);
diff --git a/src/backend/postmaster/walsummarizer.c b/src/backend/postmaster/walsummarizer.c
index f4d61c1f3bb..d5be806dc77 100644
--- a/src/backend/postmaster/walsummarizer.c
+++ b/src/backend/postmaster/walsummarizer.c
@@ -382,8 +382,8 @@ WalSummarizerMain(const void *startup_data, size_t startup_data_len)
 
 			switch_lsn = tliSwitchPoint(current_tli, tles, &switch_tli);
 			ereport(DEBUG1,
-					errmsg_internal("switch point from TLI %u to TLI %u is at %X/%X",
-									current_tli, switch_tli, LSN_FORMAT_ARGS(switch_lsn)));
+					errmsg_internal("switch point from TLI %u to TLI %u is at %016" PRIX64,
+									current_tli, switch_tli, switch_lsn));
 		}
 
 		/*
@@ -738,10 +738,10 @@ WaitForWalSummarization(XLogRecPtr lsn)
 				ereport(ERROR,
 						(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 						 errmsg("WAL summarization is not progressing"),
-						 errdetail("Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory.",
-								   LSN_FORMAT_ARGS(lsn),
-								   LSN_FORMAT_ARGS(summarized_lsn),
-								   LSN_FORMAT_ARGS(pending_lsn))));
+						 errdetail("Summarization is needed through %016" PRIX64 ", but is stuck at %016" PRIX64 " on disk and %016" PRIX64 " in memory.",
+								   lsn,
+								   summarized_lsn,
+								   pending_lsn)));
 
 
 			/*
@@ -752,14 +752,14 @@ WaitForWalSummarization(XLogRecPtr lsn)
 												current_time) / 1000;
 			ereport(WARNING,
 					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-					 errmsg_plural("still waiting for WAL summarization through %X/%X after %ld second",
-								   "still waiting for WAL summarization through %X/%X after %ld seconds",
+					 errmsg_plural("still waiting for WAL summarization through %016" PRIX64 " after %ld second",
+								   "still waiting for WAL summarization through %016" PRIX64 " after %ld seconds",
 								   elapsed_seconds,
-								   LSN_FORMAT_ARGS(lsn),
+								   lsn,
 								   elapsed_seconds),
-					 errdetail("Summarization has reached %X/%X on disk and %X/%X in memory.",
-							   LSN_FORMAT_ARGS(summarized_lsn),
-							   LSN_FORMAT_ARGS(pending_lsn))));
+					 errdetail("Summarization has reached %016" PRIX64 " on disk and %016" PRIX64 " in memory.",
+							   summarized_lsn,
+							   pending_lsn)));
 		}
 
 		/*
@@ -978,10 +978,10 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 			if (private_data->end_of_wal)
 			{
 				ereport(DEBUG1,
-						errmsg_internal("could not read WAL from timeline %u at %X/%X: end of WAL at %X/%X",
+						errmsg_internal("could not read WAL from timeline %u at %016" PRIX64 ": end of WAL at %016" PRIX64,
 										tli,
-										LSN_FORMAT_ARGS(start_lsn),
-										LSN_FORMAT_ARGS(private_data->read_upto)));
+										start_lsn,
+										private_data->read_upto));
 
 				/*
 				 * The timeline ends at or after start_lsn, without containing
@@ -997,8 +997,8 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 			}
 			else
 				ereport(ERROR,
-						(errmsg("could not find a valid record after %X/%X",
-								LSN_FORMAT_ARGS(start_lsn))));
+						(errmsg("could not find a valid record after %016" PRIX64,
+								start_lsn)));
 		}
 
 		/* We shouldn't go backward. */
@@ -1031,10 +1031,10 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 				 * able to read a complete record.
 				 */
 				ereport(DEBUG1,
-						errmsg_internal("could not read WAL from timeline %u at %X/%X: end of WAL at %X/%X",
+						errmsg_internal("could not read WAL from timeline %u at %016" PRIX64 ": end of WAL at %016" PRIX64,
 										tli,
-										LSN_FORMAT_ARGS(xlogreader->EndRecPtr),
-										LSN_FORMAT_ARGS(private_data->read_upto)));
+										xlogreader->EndRecPtr,
+										private_data->read_upto));
 				/* Summary ends at end of WAL. */
 				summary_end_lsn = private_data->read_upto;
 				break;
@@ -1042,14 +1042,16 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 			if (errormsg)
 				ereport(ERROR,
 						(errcode_for_file_access(),
-						 errmsg("could not read WAL from timeline %u at %X/%X: %s",
-								tli, LSN_FORMAT_ARGS(xlogreader->EndRecPtr),
+						 errmsg("could not read WAL from timeline %u at %016"
+								PRIX64 ": %s",
+								tli, xlogreader->EndRecPtr,
 								errormsg)));
 			else
 				ereport(ERROR,
 						(errcode_for_file_access(),
-						 errmsg("could not read WAL from timeline %u at %X/%X",
-								tli, LSN_FORMAT_ARGS(xlogreader->EndRecPtr))));
+						 errmsg("could not read WAL from timeline %u at %016"
+								PRIX64,
+								tli, xlogreader->EndRecPtr)));
 		}
 
 		/* We shouldn't go backward. */
@@ -1198,10 +1200,10 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 		snprintf(temp_path, MAXPGPATH,
 				 XLOGDIR "/summaries/temp.summary");
 		snprintf(final_path, MAXPGPATH,
-				 XLOGDIR "/summaries/%08X%08X%08X%08X%08X.summary",
+				 XLOGDIR "/summaries/%08X%016" PRIX64 "%016" PRIX64 ".summary",
 				 tli,
-				 LSN_FORMAT_ARGS(summary_start_lsn),
-				 LSN_FORMAT_ARGS(summary_end_lsn));
+				 summary_start_lsn,
+				 summary_end_lsn);
 
 		/* Open the temporary file for writing. */
 		io.filepos = 0;
@@ -1219,10 +1221,11 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 
 		/* Tell the user what we did. */
 		ereport(DEBUG1,
-				errmsg_internal("summarized WAL on TLI %u from %X/%X to %X/%X",
+				errmsg_internal("summarized WAL on TLI %u from %016" PRIX64
+								" to %016" PRIX64,
 								tli,
-								LSN_FORMAT_ARGS(summary_start_lsn),
-								LSN_FORMAT_ARGS(summary_end_lsn)));
+								summary_start_lsn,
+								summary_end_lsn));
 
 		/* Durably rename the new summary into place. */
 		durable_rename(temp_path, final_path, ERROR);
@@ -1231,10 +1234,11 @@ SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact,
 	/* If we skipped a non-zero amount of WAL, log a debug message. */
 	if (summary_end_lsn > summary_start_lsn && fast_forward)
 		ereport(DEBUG1,
-				errmsg_internal("skipped summarizing WAL on TLI %u from %X/%X to %X/%X",
+				errmsg_internal("skipped summarizing WAL on TLI %u from %016"
+								PRIX64 " to %016" PRIX64,
 								tli,
-								LSN_FORMAT_ARGS(summary_start_lsn),
-								LSN_FORMAT_ARGS(summary_end_lsn)));
+								summary_start_lsn,
+								summary_end_lsn));
 
 	return summary_end_lsn;
 }
@@ -1577,8 +1581,9 @@ summarizer_read_local_xlog_page(XLogReaderState *state,
 
 					/* Debugging output. */
 					ereport(DEBUG1,
-							errmsg_internal("timeline %u became historic, can read up to %X/%X",
-											private_data->tli, LSN_FORMAT_ARGS(private_data->read_upto)));
+							errmsg_internal("timeline %u became historic, can read up to %016" PRIX64,
+											private_data->tli,
+											private_data->read_upto));
 				}
 
 				/* Go around and try again. */
diff --git a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
index 1b158c9d288..64ecb84df23 100644
--- a/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
+++ b/src/backend/replication/libpqwalreceiver/libpqwalreceiver.c
@@ -569,7 +569,7 @@ libpqrcv_startstreaming(WalReceiverConn *conn,
 	if (options->logical)
 		appendStringInfoString(&cmd, " LOGICAL");
 
-	appendStringInfo(&cmd, " %X/%X", LSN_FORMAT_ARGS(options->startpoint));
+	appendStringInfo(&cmd, " %016" PRIX64, options->startpoint);
 
 	/*
 	 * Additional options are different depending on if we are doing logical
diff --git a/src/backend/replication/logical/logical.c b/src/backend/replication/logical/logical.c
index a8d2e024d34..e72a2561333 100644
--- a/src/backend/replication/logical/logical.c
+++ b/src/backend/replication/logical/logical.c
@@ -565,9 +565,10 @@ CreateDecodingContext(XLogRecPtr start_lsn,
 		 * kinds of client errors; so the client may wish to check that
 		 * confirmed_flush_lsn matches its expectations.
 		 */
-		elog(LOG, "%X/%X has been already streamed, forwarding to %X/%X",
-			 LSN_FORMAT_ARGS(start_lsn),
-			 LSN_FORMAT_ARGS(slot->data.confirmed_flush));
+		elog(LOG, "%016" PRIX64
+			 " has been already streamed, forwarding to %016" PRIX64,
+			 start_lsn,
+			 slot->data.confirmed_flush);
 
 		start_lsn = slot->data.confirmed_flush;
 	}
@@ -608,9 +609,10 @@ CreateDecodingContext(XLogRecPtr start_lsn,
 	ereport(LOG,
 			(errmsg("starting logical decoding for slot \"%s\"",
 					NameStr(slot->data.name)),
-			 errdetail("Streaming transactions committing after %X/%X, reading WAL from %X/%X.",
-					   LSN_FORMAT_ARGS(slot->data.confirmed_flush),
-					   LSN_FORMAT_ARGS(slot->data.restart_lsn))));
+			 errdetail("Streaming transactions committing after %016" PRIX64
+					   ", reading WAL from %016" PRIX64 ".",
+					   slot->data.confirmed_flush,
+					   slot->data.restart_lsn)));
 
 	return ctx;
 }
@@ -635,8 +637,8 @@ DecodingContextFindStartpoint(LogicalDecodingContext *ctx)
 	/* Initialize from where to start reading WAL. */
 	XLogBeginRead(ctx->reader, slot->data.restart_lsn);
 
-	elog(DEBUG1, "searching for logical decoding starting point, starting at %X/%X",
-		 LSN_FORMAT_ARGS(slot->data.restart_lsn));
+	elog(DEBUG1, "searching for logical decoding starting point, starting at %016" PRIX64,
+		 slot->data.restart_lsn);
 
 	/* Wait for a consistent starting point */
 	for (;;)
@@ -756,11 +758,11 @@ output_plugin_error_callback(void *arg)
 
 	/* not all callbacks have an associated LSN  */
 	if (state->report_location != InvalidXLogRecPtr)
-		errcontext("slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %X/%X",
+		errcontext("slot \"%s\", output plugin \"%s\", in the %s callback, associated LSN %016" PRIX64,
 				   NameStr(state->ctx->slot->data.name),
 				   NameStr(state->ctx->slot->data.plugin),
 				   state->callback_name,
-				   LSN_FORMAT_ARGS(state->report_location));
+				   state->report_location);
 	else
 		errcontext("slot \"%s\", output plugin \"%s\", in the %s callback",
 				   NameStr(state->ctx->slot->data.name),
@@ -1723,8 +1725,8 @@ LogicalIncreaseXminForSlot(XLogRecPtr current_lsn, TransactionId xmin)
 	SpinLockRelease(&slot->mutex);
 
 	if (got_new_xmin)
-		elog(DEBUG1, "got new catalog xmin %u at %X/%X", xmin,
-			 LSN_FORMAT_ARGS(current_lsn));
+		elog(DEBUG1, "got new catalog xmin %u at %016" PRIX64, xmin,
+			 current_lsn);
 
 	/* candidate already valid with the current flush position, apply */
 	if (updated_xmin)
@@ -1783,9 +1785,9 @@ LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart
 		slot->candidate_restart_lsn = restart_lsn;
 		SpinLockRelease(&slot->mutex);
 
-		elog(DEBUG1, "got new restart lsn %X/%X at %X/%X",
-			 LSN_FORMAT_ARGS(restart_lsn),
-			 LSN_FORMAT_ARGS(current_lsn));
+		elog(DEBUG1, "got new restart lsn %016" PRIX64 " at %016" PRIX64,
+			 restart_lsn,
+			 current_lsn);
 	}
 	else
 	{
@@ -1798,12 +1800,14 @@ LogicalIncreaseRestartDecodingForSlot(XLogRecPtr current_lsn, XLogRecPtr restart
 		confirmed_flush = slot->data.confirmed_flush;
 		SpinLockRelease(&slot->mutex);
 
-		elog(DEBUG1, "failed to increase restart lsn: proposed %X/%X, after %X/%X, current candidate %X/%X, current after %X/%X, flushed up to %X/%X",
-			 LSN_FORMAT_ARGS(restart_lsn),
-			 LSN_FORMAT_ARGS(current_lsn),
-			 LSN_FORMAT_ARGS(candidate_restart_lsn),
-			 LSN_FORMAT_ARGS(candidate_restart_valid),
-			 LSN_FORMAT_ARGS(confirmed_flush));
+		elog(DEBUG1, "failed to increase restart lsn: proposed %016" PRIX64
+			 ", after %016" PRIX64 ", current candidate %016" PRIX64
+			 ", current after %016" PRIX64 ", flushed up to %016" PRIX64,
+			 restart_lsn,
+			 current_lsn,
+			 candidate_restart_lsn,
+			 candidate_restart_valid,
+			 confirmed_flush);
 	}
 
 	/* candidates are already valid with the current flush position, apply */
diff --git a/src/backend/replication/logical/origin.c b/src/backend/replication/logical/origin.c
index c3c1d7a2a51..90f4a7b0833 100644
--- a/src/backend/replication/logical/origin.c
+++ b/src/backend/replication/logical/origin.c
@@ -807,9 +807,9 @@ StartupReplicationOrigin(void)
 		last_state++;
 
 		ereport(LOG,
-				(errmsg("recovered replication state of node %d to %X/%X",
+				(errmsg("recovered replication state of node %d to %016" PRIX64,
 						disk_state.roident,
-						LSN_FORMAT_ARGS(disk_state.remote_lsn))));
+						disk_state.remote_lsn)));
 	}
 
 	/* now check checksum */
diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c
index 5186ad2a397..4ff1bcc2112 100644
--- a/src/backend/replication/logical/reorderbuffer.c
+++ b/src/backend/replication/logical/reorderbuffer.c
@@ -4764,10 +4764,10 @@ ReorderBufferSerializedPath(char *path, ReplicationSlot *slot, TransactionId xid
 
 	XLogSegNoOffsetToRecPtr(segno, 0, wal_segment_size, recptr);
 
-	snprintf(path, MAXPGPATH, "%s/%s/xid-%u-lsn-%X-%X.spill",
+	snprintf(path, MAXPGPATH, "%s/%s/xid-%u-lsn-%016" PRIX64 ".spill",
 			 PG_REPLSLOT_DIR,
 			 NameStr(MyReplicationSlot->data.name),
-			 xid, LSN_FORMAT_ARGS(recptr));
+			 xid, recptr);
 }
 
 /*
@@ -5333,8 +5333,6 @@ UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
 		TransactionId f_mapped_xid;
 		TransactionId f_create_xid;
 		XLogRecPtr	f_lsn;
-		uint32		f_hi,
-					f_lo;
 		RewriteMappingFile *f;
 
 		if (strcmp(mapping_de->d_name, ".") == 0 ||
@@ -5345,13 +5343,11 @@ UpdateLogicalMappings(HTAB *tuplecid_data, Oid relid, Snapshot snapshot)
 		if (strncmp(mapping_de->d_name, "map-", 4) != 0)
 			continue;
 
-		if (sscanf(mapping_de->d_name, LOGICAL_REWRITE_FORMAT,
-				   &f_dboid, &f_relid, &f_hi, &f_lo,
-				   &f_mapped_xid, &f_create_xid) != 6)
+		if (sscanf(mapping_de->d_name, LOGICAL_REWRITE_FORMAT_SCANF,
+				   &f_dboid, &f_relid, &f_lsn,
+				   &f_mapped_xid, &f_create_xid) != 5)
 			elog(ERROR, "could not parse filename \"%s\"", mapping_de->d_name);
 
-		f_lsn = ((uint64) f_hi) << 32 | f_lo;
-
 		/* mapping for another database */
 		if (f_dboid != dboid)
 			continue;
diff --git a/src/backend/replication/logical/slotsync.c b/src/backend/replication/logical/slotsync.c
index 2c0a7439be4..9bf6934b7fa 100644
--- a/src/backend/replication/logical/slotsync.c
+++ b/src/backend/replication/logical/slotsync.c
@@ -212,10 +212,10 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid,
 		ereport(slot->data.persistency == RS_TEMPORARY ? LOG : DEBUG1,
 				errmsg("could not synchronize replication slot \"%s\" because remote slot precedes local slot",
 					   remote_slot->name),
-				errdetail("The remote slot has LSN %X/%X and catalog xmin %u, but the local slot has LSN %X/%X and catalog xmin %u.",
-						  LSN_FORMAT_ARGS(remote_slot->restart_lsn),
+				errdetail("The remote slot has LSN %016" PRIX64 " and catalog xmin %u, but the local slot has LSN %016" PRIX64 " and catalog xmin %u.",
+						  remote_slot->restart_lsn,
 						  remote_slot->catalog_xmin,
-						  LSN_FORMAT_ARGS(slot->data.restart_lsn),
+						  slot->data.restart_lsn,
 						  slot->data.catalog_xmin));
 
 		if (remote_slot_precedes)
@@ -265,9 +265,9 @@ update_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid,
 				ereport(ERROR,
 						errmsg_internal("synchronized confirmed_flush for slot \"%s\" differs from remote slot",
 										remote_slot->name),
-						errdetail_internal("Remote slot has LSN %X/%X but local slot has LSN %X/%X.",
-										   LSN_FORMAT_ARGS(remote_slot->confirmed_lsn),
-										   LSN_FORMAT_ARGS(slot->data.confirmed_flush)));
+						errdetail_internal("Remote slot has LSN %016" PRIX64 " but local slot has LSN %016" PRIX64 ".",
+										   remote_slot->confirmed_lsn,
+										   slot->data.confirmed_flush));
 		}
 
 		updated_xmin_or_lsn = true;
@@ -575,8 +575,8 @@ update_and_persist_local_synced_slot(RemoteSlot *remote_slot, Oid remote_dbid)
 	{
 		ereport(LOG,
 				errmsg("could not synchronize replication slot \"%s\"", remote_slot->name),
-				errdetail("Logical decoding could not find consistent point from local slot's LSN %X/%X.",
-						  LSN_FORMAT_ARGS(slot->data.restart_lsn)));
+				errdetail("Logical decoding could not find consistent point from local slot's LSN %016" PRIX64 ".",
+						  slot->data.restart_lsn));
 
 		return false;
 	}
@@ -624,10 +624,10 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid)
 		ereport(AmLogicalSlotSyncWorkerProcess() ? LOG : ERROR,
 				errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 				errmsg("skipping slot synchronization because the received slot sync"
-					   " LSN %X/%X for slot \"%s\" is ahead of the standby position %X/%X",
-					   LSN_FORMAT_ARGS(remote_slot->confirmed_lsn),
+					   " LSN %016" PRIX64 " for slot \"%s\" is ahead of the standby position %016" PRIX64,
+					   remote_slot->confirmed_lsn,
 					   remote_slot->name,
-					   LSN_FORMAT_ARGS(latestFlushPtr)));
+					   latestFlushPtr));
 
 		return false;
 	}
@@ -715,9 +715,9 @@ synchronize_one_slot(RemoteSlot *remote_slot, Oid remote_dbid)
 				ereport(ERROR,
 						errmsg_internal("cannot synchronize local slot \"%s\"",
 										remote_slot->name),
-						errdetail_internal("Local slot's start streaming location LSN(%X/%X) is ahead of remote slot's LSN(%X/%X).",
-										   LSN_FORMAT_ARGS(slot->data.confirmed_flush),
-										   LSN_FORMAT_ARGS(remote_slot->confirmed_lsn)));
+						errdetail_internal("Local slot's start streaming location LSN(%016" PRIX64 ") is ahead of remote slot's LSN(%016" PRIX64 ").",
+										   slot->data.confirmed_flush,
+										   remote_slot->confirmed_lsn));
 
 			slot_updated = update_local_synced_slot(remote_slot, remote_dbid,
 													NULL, NULL);
diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c
index bd0680dcbe5..c8b320edcfc 100644
--- a/src/backend/replication/logical/snapbuild.c
+++ b/src/backend/replication/logical/snapbuild.c
@@ -764,8 +764,8 @@ SnapBuildDistributeNewCatalogSnapshot(SnapBuild *builder, XLogRecPtr lsn)
 		if (rbtxn_is_prepared(txn))
 			continue;
 
-		elog(DEBUG2, "adding a new snapshot to %u at %X/%X",
-			 txn->xid, LSN_FORMAT_ARGS(lsn));
+		elog(DEBUG2, "adding a new snapshot to %u at %016" PRIX64,
+			 txn->xid, lsn);
 
 		/*
 		 * increase the snapshot's refcount for the transaction we are handing
@@ -1223,8 +1223,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 									builder->initial_xmin_horizon))
 	{
 		ereport(DEBUG1,
-				(errmsg_internal("skipping snapshot at %X/%X while building logical decoding snapshot, xmin horizon too low",
-								 LSN_FORMAT_ARGS(lsn)),
+				(errmsg_internal("skipping snapshot at %016" PRIX64 " while building logical decoding snapshot, xmin horizon too low",
+								 lsn),
 				 errdetail_internal("initial xmin horizon of %u vs the snapshot's %u",
 									builder->initial_xmin_horizon, running->oldestRunningXid)));
 
@@ -1262,8 +1262,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 		builder->next_phase_at = InvalidTransactionId;
 
 		ereport(LOG,
-				(errmsg("logical decoding found consistent point at %X/%X",
-						LSN_FORMAT_ARGS(lsn)),
+				(errmsg("logical decoding found consistent point at %016" PRIX64,
+						lsn),
 				 errdetail("There are no running transactions.")));
 
 		return false;
@@ -1311,8 +1311,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 		Assert(TransactionIdIsNormal(builder->xmax));
 
 		ereport(LOG,
-				(errmsg("logical decoding found initial starting point at %X/%X",
-						LSN_FORMAT_ARGS(lsn)),
+				(errmsg("logical decoding found initial starting point at %016" PRIX64,
+						lsn),
 				 errdetail("Waiting for transactions (approximately %d) older than %u to end.",
 						   running->xcnt, running->nextXid)));
 
@@ -1335,8 +1335,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 		builder->next_phase_at = running->nextXid;
 
 		ereport(LOG,
-				(errmsg("logical decoding found initial consistent point at %X/%X",
-						LSN_FORMAT_ARGS(lsn)),
+				(errmsg("logical decoding found initial consistent point at %016" PRIX64,
+						lsn),
 				 errdetail("Waiting for transactions (approximately %d) older than %u to end.",
 						   running->xcnt, running->nextXid)));
 
@@ -1359,8 +1359,8 @@ SnapBuildFindSnapshot(SnapBuild *builder, XLogRecPtr lsn, xl_running_xacts *runn
 		builder->next_phase_at = InvalidTransactionId;
 
 		ereport(LOG,
-				(errmsg("logical decoding found consistent point at %X/%X",
-						LSN_FORMAT_ARGS(lsn)),
+				(errmsg("logical decoding found consistent point at %016" PRIX64,
+						lsn),
 				 errdetail("There are no old transactions anymore.")));
 	}
 
@@ -1481,9 +1481,9 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
 	 * unless the user used pg_resetwal or similar. If a user did so, there's
 	 * no hope continuing to decode anyway.
 	 */
-	sprintf(path, "%s/%X-%X.snap",
+	sprintf(path, "%s/%016" PRIX64 ".snap",
 			PG_LOGICAL_SNAPSHOTS_DIR,
-			LSN_FORMAT_ARGS(lsn));
+			lsn);
 
 	/*
 	 * first check whether some other backend already has written the snapshot
@@ -1525,9 +1525,9 @@ SnapBuildSerialize(SnapBuild *builder, XLogRecPtr lsn)
 	elog(DEBUG1, "serializing snapshot to %s", path);
 
 	/* to make sure only we will write to this tempfile, include pid */
-	sprintf(tmppath, "%s/%X-%X.snap.%d.tmp",
+	sprintf(tmppath, "%s/%016" PRIX64 ".snap.%d.tmp",
 			PG_LOGICAL_SNAPSHOTS_DIR,
-			LSN_FORMAT_ARGS(lsn), MyProcPid);
+			lsn, MyProcPid);
 
 	/*
 	 * Unlink temporary file if it already exists, needs to have been before a
@@ -1794,9 +1794,9 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
 	if (builder->state == SNAPBUILD_CONSISTENT)
 		return false;
 
-	sprintf(path, "%s/%X-%X.snap",
+	sprintf(path, "%s/%016" PRIX64 ".snap",
 			PG_LOGICAL_SNAPSHOTS_DIR,
-			LSN_FORMAT_ARGS(lsn));
+			lsn);
 
 	/* validate and restore the snapshot to 'ondisk' */
 	if (!SnapBuildRestoreSnapshot(&ondisk, path, builder->context, true))
@@ -1865,8 +1865,8 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn)
 	Assert(builder->state == SNAPBUILD_CONSISTENT);
 
 	ereport(LOG,
-			(errmsg("logical decoding found consistent point at %X/%X",
-					LSN_FORMAT_ARGS(lsn)),
+			(errmsg("logical decoding found consistent point at %016" PRIX64,
+					lsn),
 			 errdetail("Logical decoding will begin using saved snapshot.")));
 	return true;
 
@@ -2013,9 +2013,9 @@ SnapBuildSnapshotExists(XLogRecPtr lsn)
 	int			ret;
 	struct stat stat_buf;
 
-	sprintf(path, "%s/%X-%X.snap",
+	sprintf(path, "%s/%016" PRIX64 ".snap",
 			PG_LOGICAL_SNAPSHOTS_DIR,
-			LSN_FORMAT_ARGS(lsn));
+			lsn);
 
 	ret = stat(path, &stat_buf);
 
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 6af5c9fe16c..b251877f79a 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -1549,8 +1549,8 @@ LogicalRepSyncTableStart(XLogRecPtr *origin_startpos)
 copy_table_done:
 
 	elog(DEBUG1,
-		 "LogicalRepSyncTableStart: '%s' origin_startpos lsn %X/%X",
-		 originname, LSN_FORMAT_ARGS(*origin_startpos));
+		 "LogicalRepSyncTableStart: '%s' origin_startpos lsn %016" PRIX64,
+		 originname, *origin_startpos);
 
 	/*
 	 * We are done with the initial data synchronization, update the state.
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 31ab69ea13a..dfc5592c130 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -1021,9 +1021,9 @@ apply_handle_commit(StringInfo s)
 	if (commit_data.commit_lsn != remote_final_lsn)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 errmsg_internal("incorrect commit LSN %X/%X in commit message (expected %X/%X)",
-								 LSN_FORMAT_ARGS(commit_data.commit_lsn),
-								 LSN_FORMAT_ARGS(remote_final_lsn))));
+				 errmsg_internal("incorrect commit LSN %016" PRIX64 " in commit message (expected %016" PRIX64 ")",
+								 commit_data.commit_lsn,
+								 remote_final_lsn)));
 
 	apply_handle_commit_internal(&commit_data);
 
@@ -1113,9 +1113,9 @@ apply_handle_prepare(StringInfo s)
 	if (prepare_data.prepare_lsn != remote_final_lsn)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 errmsg_internal("incorrect prepare LSN %X/%X in prepare message (expected %X/%X)",
-								 LSN_FORMAT_ARGS(prepare_data.prepare_lsn),
-								 LSN_FORMAT_ARGS(remote_final_lsn))));
+				 errmsg_internal("incorrect prepare LSN %016" PRIX64 " in prepare message (expected %016" PRIX64 ")",
+								 prepare_data.prepare_lsn,
+								 remote_final_lsn)));
 
 	/*
 	 * Unlike commit, here, we always prepare the transaction even though no
@@ -3912,11 +3912,11 @@ send_feedback(XLogRecPtr recvpos, bool force, bool requestReply)
 	pq_sendint64(reply_message, now);	/* sendTime */
 	pq_sendbyte(reply_message, requestReply);	/* replyRequested */
 
-	elog(DEBUG2, "sending feedback (force %d) to recv %X/%X, write %X/%X, flush %X/%X",
+	elog(DEBUG2, "sending feedback (force %d) to recv %016" PRIX64 ", write %016" PRIX64 ", flush %016" PRIX64,
 		 force,
-		 LSN_FORMAT_ARGS(recvpos),
-		 LSN_FORMAT_ARGS(writepos),
-		 LSN_FORMAT_ARGS(flushpos));
+		 recvpos,
+		 writepos,
+		 flushpos);
 
 	walrcv_send(LogRepWorkerWalRcvConn,
 				reply_message->data, reply_message->len);
@@ -4894,8 +4894,8 @@ maybe_start_skipping_changes(XLogRecPtr finish_lsn)
 	skip_xact_finish_lsn = finish_lsn;
 
 	ereport(LOG,
-			errmsg("logical replication starts skipping transaction at LSN %X/%X",
-				   LSN_FORMAT_ARGS(skip_xact_finish_lsn)));
+			errmsg("logical replication starts skipping transaction at LSN %016" PRIX64,
+				   skip_xact_finish_lsn));
 }
 
 /*
@@ -4908,8 +4908,8 @@ stop_skipping_changes(void)
 		return;
 
 	ereport(LOG,
-			(errmsg("logical replication completed skipping transaction at LSN %X/%X",
-					LSN_FORMAT_ARGS(skip_xact_finish_lsn))));
+			(errmsg("logical replication completed skipping transaction at LSN %016" PRIX64,
+					skip_xact_finish_lsn)));
 
 	/* Stop skipping changes */
 	skip_xact_finish_lsn = InvalidXLogRecPtr;
@@ -4991,9 +4991,9 @@ clear_subscription_skip_lsn(XLogRecPtr finish_lsn)
 		if (myskiplsn != finish_lsn)
 			ereport(WARNING,
 					errmsg("skip-LSN of subscription \"%s\" cleared", MySubscription->name),
-					errdetail("Remote transaction's finish WAL location (LSN) %X/%X did not match skip-LSN %X/%X.",
-							  LSN_FORMAT_ARGS(finish_lsn),
-							  LSN_FORMAT_ARGS(myskiplsn)));
+					errdetail("Remote transaction's finish WAL location (LSN) %016" PRIX64 " did not match skip-LSN %016" PRIX64 ".",
+							  finish_lsn,
+							  myskiplsn));
 	}
 
 	heap_freetuple(tup);
@@ -5037,11 +5037,11 @@ apply_error_callback(void *arg)
 					   logicalrep_message_type(errarg->command),
 					   errarg->remote_xid);
 		else
-			errcontext("processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %X/%X",
+			errcontext("processing remote data for replication origin \"%s\" during message type \"%s\" in transaction %u, finished at %016" PRIX64,
 					   errarg->origin_name,
 					   logicalrep_message_type(errarg->command),
 					   errarg->remote_xid,
-					   LSN_FORMAT_ARGS(errarg->finish_lsn));
+					   errarg->finish_lsn);
 	}
 	else
 	{
@@ -5055,13 +5055,13 @@ apply_error_callback(void *arg)
 						   errarg->rel->remoterel.relname,
 						   errarg->remote_xid);
 			else
-				errcontext("processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %X/%X",
+				errcontext("processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" in transaction %u, finished at %016" PRIX64,
 						   errarg->origin_name,
 						   logicalrep_message_type(errarg->command),
 						   errarg->rel->remoterel.nspname,
 						   errarg->rel->remoterel.relname,
 						   errarg->remote_xid,
-						   LSN_FORMAT_ARGS(errarg->finish_lsn));
+						   errarg->finish_lsn);
 		}
 		else
 		{
@@ -5074,14 +5074,14 @@ apply_error_callback(void *arg)
 						   errarg->rel->remoterel.attnames[errarg->remote_attnum],
 						   errarg->remote_xid);
 			else
-				errcontext("processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %X/%X",
+				errcontext("processing remote data for replication origin \"%s\" during message type \"%s\" for replication target relation \"%s.%s\" column \"%s\" in transaction %u, finished at %016" PRIX64,
 						   errarg->origin_name,
 						   logicalrep_message_type(errarg->command),
 						   errarg->rel->remoterel.nspname,
 						   errarg->rel->remoterel.relname,
 						   errarg->rel->remoterel.attnames[errarg->remote_attnum],
 						   errarg->remote_xid,
-						   LSN_FORMAT_ARGS(errarg->finish_lsn));
+						   errarg->finish_lsn);
 		}
 	}
 }
diff --git a/src/backend/replication/repl_gram.y b/src/backend/replication/repl_gram.y
index 7440aae5a1a..e4b7a14f31b 100644
--- a/src/backend/replication/repl_gram.y
+++ b/src/backend/replication/repl_gram.y
@@ -279,7 +279,7 @@ alter_replication_slot:
 			;
 
 /*
- * START_REPLICATION [SLOT slot] [PHYSICAL] %X/%X [TIMELINE %u]
+ * START_REPLICATION [SLOT slot] [PHYSICAL] startpoint [TIMELINE %u]
  */
 start_replication:
 			K_START_REPLICATION opt_slot opt_physical RECPTR opt_timeline
@@ -295,7 +295,7 @@ start_replication:
 				}
 			;
 
-/* START_REPLICATION SLOT slot LOGICAL %X/%X options */
+/* START_REPLICATION SLOT slot LOGICAL startpoint options */
 start_logical_replication:
 			K_START_REPLICATION K_SLOT IDENT K_LOGICAL RECPTR plugin_options
 				{
diff --git a/src/backend/replication/repl_scanner.l b/src/backend/replication/repl_scanner.l
index 014ea8d25c6..7c82d4067d2 100644
--- a/src/backend/replication/repl_scanner.l
+++ b/src/backend/replication/repl_scanner.l
@@ -147,17 +147,14 @@ UPLOAD_MANIFEST		{ return K_UPLOAD_MANIFEST; }
 
 {space}+		{ /* do nothing */ }
 
-{digit}+		{
+{digit}{1,10}	{
 					yylval->uintval = strtoul(yytext, NULL, 10);
 					return UCONST;
 				}
 
-{hexdigit}+\/{hexdigit}+		{
-					uint32	hi,
-							lo;
-					if (sscanf(yytext, "%X/%X", &hi, &lo) != 2)
+{hexdigit}{16}	{
+					if (sscanf(yytext, "%" SCNx64, &yylval->recptr) != 1)
 						replication_yyerror(NULL, yyscanner, "invalid streaming start location");
-					yylval->recptr = ((uint64) hi) << 32 | lo;
 					return RECPTR;
 				}
 
diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c
index f52a2c0fa8f..ecb885d1341 100644
--- a/src/backend/replication/slot.c
+++ b/src/backend/replication/slot.c
@@ -1547,10 +1547,10 @@ ReportSlotInvalidation(ReplicationSlotInvalidationCause cause,
 				uint64		ex = oldestLSN - restart_lsn;
 
 				appendStringInfo(&err_detail,
-								 ngettext("The slot's restart_lsn %X/%X exceeds the limit by %" PRIu64 " byte.",
-										  "The slot's restart_lsn %X/%X exceeds the limit by %" PRIu64 " bytes.",
+								 ngettext("The slot's restart_lsn %016" PRIX64 " exceeds the limit by %" PRIu64 " byte.",
+										  "The slot's restart_lsn %016" PRIX64 " exceeds the limit by %" PRIu64 " bytes.",
 										  ex),
-								 LSN_FORMAT_ARGS(restart_lsn),
+								 restart_lsn,
 								 ex);
 				/* translator: %s is a GUC variable name */
 				appendStringInfo(&err_hint, _("You might need to increase \"%s\"."),
diff --git a/src/backend/replication/slotfuncs.c b/src/backend/replication/slotfuncs.c
index 146eef5871e..486df3ee66f 100644
--- a/src/backend/replication/slotfuncs.c
+++ b/src/backend/replication/slotfuncs.c
@@ -560,8 +560,8 @@ pg_replication_slot_advance(PG_FUNCTION_ARGS)
 	if (moveto < minlsn)
 		ereport(ERROR,
 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("cannot advance replication slot to %X/%X, minimum is %X/%X",
-						LSN_FORMAT_ARGS(moveto), LSN_FORMAT_ARGS(minlsn))));
+				 errmsg("cannot advance replication slot to %016" PRIX64 ", minimum is %016" PRIX64,
+						moveto, minlsn)));
 
 	/* Do the actual slot update, depending on the slot type */
 	if (OidIsValid(MyReplicationSlot->data.database))
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index d75e3968035..f1f84bd8850 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -215,7 +215,7 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
 	{
 		char		buffer[32];
 
-		sprintf(buffer, "waiting for %X/%X", LSN_FORMAT_ARGS(lsn));
+		sprintf(buffer, "waiting for %016" PRIX64, lsn);
 		set_ps_display_suffix(buffer);
 	}
 
@@ -523,10 +523,10 @@ SyncRepReleaseWaiters(void)
 
 	LWLockRelease(SyncRepLock);
 
-	elog(DEBUG3, "released %d procs up to write %X/%X, %d procs up to flush %X/%X, %d procs up to apply %X/%X",
-		 numwrite, LSN_FORMAT_ARGS(writePtr),
-		 numflush, LSN_FORMAT_ARGS(flushPtr),
-		 numapply, LSN_FORMAT_ARGS(applyPtr));
+	elog(DEBUG3, "released %d procs up to write %016" PRIX64 ", %d procs up to flush %016" PRIX64 ", %d procs up to apply %016" PRIX64,
+		 numwrite, writePtr,
+		 numflush, flushPtr,
+		 numapply, applyPtr);
 }
 
 /*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 99a1d7d606c..443d187ad2c 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -417,12 +417,12 @@ WalReceiverMain(const void *startup_data, size_t startup_data_len)
 		{
 			if (first_stream)
 				ereport(LOG,
-						(errmsg("started streaming WAL from primary at %X/%X on timeline %u",
-								LSN_FORMAT_ARGS(startpoint), startpointTLI)));
+						(errmsg("started streaming WAL from primary at %016" PRIX64 " on timeline %u",
+								startpoint, startpointTLI)));
 			else
 				ereport(LOG,
-						(errmsg("restarted WAL streaming at %X/%X on timeline %u",
-								LSN_FORMAT_ARGS(startpoint), startpointTLI)));
+						(errmsg("restarted WAL streaming at %016" PRIX64 " on timeline %u",
+								startpoint, startpointTLI)));
 			first_stream = false;
 
 			/* Initialize LogstreamResult and buffers for processing messages */
@@ -501,9 +501,9 @@ WalReceiverMain(const void *startup_data, size_t startup_data_len)
 						{
 							ereport(LOG,
 									(errmsg("replication terminated by primary server"),
-									 errdetail("End of WAL reached on timeline %u at %X/%X.",
+									 errdetail("End of WAL reached on timeline %u at %016" PRIX64 ".",
 											   startpointTLI,
-											   LSN_FORMAT_ARGS(LogstreamResult.Write))));
+											   LogstreamResult.Write)));
 							endofwal = true;
 							break;
 						}
@@ -732,8 +732,8 @@ WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
 	{
 		char		activitymsg[50];
 
-		snprintf(activitymsg, sizeof(activitymsg), "restarting at %X/%X",
-				 LSN_FORMAT_ARGS(*startpoint));
+		snprintf(activitymsg, sizeof(activitymsg), "restarting at %016" PRIX64,
+				 *startpoint);
 		set_ps_display(activitymsg);
 	}
 }
@@ -1023,8 +1023,8 @@ XLogWalRcvFlush(bool dying, TimeLineID tli)
 		{
 			char		activitymsg[50];
 
-			snprintf(activitymsg, sizeof(activitymsg), "streaming %X/%X",
-					 LSN_FORMAT_ARGS(LogstreamResult.Write));
+			snprintf(activitymsg, sizeof(activitymsg), "streaming %016" PRIX64,
+					 LogstreamResult.Write);
 			set_ps_display(activitymsg);
 		}
 
@@ -1147,10 +1147,10 @@ XLogWalRcvSendReply(bool force, bool requestReply)
 	pq_sendbyte(&reply_message, requestReply ? 1 : 0);
 
 	/* Send it */
-	elog(DEBUG2, "sending write %X/%X flush %X/%X apply %X/%X%s",
-		 LSN_FORMAT_ARGS(writePtr),
-		 LSN_FORMAT_ARGS(flushPtr),
-		 LSN_FORMAT_ARGS(applyPtr),
+	elog(DEBUG2, "sending write %016" PRIX64 " flush %016" PRIX64 " apply %016" PRIX64 "%s",
+		 writePtr,
+		 flushPtr,
+		 applyPtr,
 		 requestReply ? " (reply requested)" : "");
 
 	walrcv_send(wrconn, reply_message.data, reply_message.len);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 446d10c1a7d..f9c15914554 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -402,7 +402,7 @@ IdentifySystem(void)
 	else
 		logptr = GetFlushRecPtr(&currTLI);
 
-	snprintf(xloc, sizeof(xloc), "%X/%X", LSN_FORMAT_ARGS(logptr));
+	snprintf(xloc, sizeof(xloc), "%016" PRIX64, logptr);
 
 	if (MyDatabaseId != InvalidOid)
 	{
@@ -509,8 +509,8 @@ ReadReplicationSlot(ReadReplicationSlotCmd *cmd)
 		{
 			char		xloc[64];
 
-			snprintf(xloc, sizeof(xloc), "%X/%X",
-					 LSN_FORMAT_ARGS(slot_contents.data.restart_lsn));
+			snprintf(xloc, sizeof(xloc), "%016" PRIX64,
+					 slot_contents.data.restart_lsn);
 			values[i] = CStringGetTextDatum(xloc);
 			nulls[i] = false;
 		}
@@ -886,12 +886,12 @@ StartReplication(StartReplicationCmd *cmd)
 				switchpoint < cmd->startpoint)
 			{
 				ereport(ERROR,
-						(errmsg("requested starting point %X/%X on timeline %u is not in this server's history",
-								LSN_FORMAT_ARGS(cmd->startpoint),
+						(errmsg("requested starting point %016" PRIX64 " on timeline %u is not in this server's history",
+								cmd->startpoint,
 								cmd->timeline),
-						 errdetail("This server's history forked from timeline %u at %X/%X.",
+						 errdetail("This server's history forked from timeline %u at %016" PRIX64 ".",
 								   cmd->timeline,
-								   LSN_FORMAT_ARGS(switchpoint))));
+								   switchpoint)));
 			}
 			sendTimeLineValidUpto = switchpoint;
 		}
@@ -933,9 +933,9 @@ StartReplication(StartReplicationCmd *cmd)
 		if (FlushPtr < cmd->startpoint)
 		{
 			ereport(ERROR,
-					(errmsg("requested starting point %X/%X is ahead of the WAL flush position of this server %X/%X",
-							LSN_FORMAT_ARGS(cmd->startpoint),
-							LSN_FORMAT_ARGS(FlushPtr))));
+					(errmsg("requested starting point %016" PRIX64 " is ahead of the WAL flush position of this server %016" PRIX64,
+							cmd->startpoint,
+							FlushPtr)));
 		}
 
 		/* Start streaming from the requested point */
@@ -977,8 +977,8 @@ StartReplication(StartReplicationCmd *cmd)
 		Datum		values[2];
 		bool		nulls[2] = {0};
 
-		snprintf(startpos_str, sizeof(startpos_str), "%X/%X",
-				 LSN_FORMAT_ARGS(sendTimeLineValidUpto));
+		snprintf(startpos_str, sizeof(startpos_str), "%016" PRIX64,
+				 sendTimeLineValidUpto);
 
 		dest = CreateDestReceiver(DestRemoteSimple);
 
@@ -1318,8 +1318,8 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 			ReplicationSlotPersist();
 	}
 
-	snprintf(xloc, sizeof(xloc), "%X/%X",
-			 LSN_FORMAT_ARGS(MyReplicationSlot->data.confirmed_flush));
+	snprintf(xloc, sizeof(xloc), "%016" PRIX64,
+			 MyReplicationSlot->data.confirmed_flush);
 
 	dest = CreateDestReceiver(DestRemoteSimple);
 
@@ -1958,6 +1958,7 @@ exec_replication_command(const char *cmd_string)
 	MemoryContext cmd_context;
 	MemoryContext old_context;
 
+elog(LOG, "XXX: %s", cmd_string);
 	/*
 	 * If WAL sender has been told that shutdown is getting close, switch its
 	 * status accordingly to handle the next replication commands correctly.
@@ -2387,10 +2388,10 @@ ProcessStandbyReplyMessage(void)
 		/* Copy because timestamptz_to_str returns a static buffer */
 		replyTimeStr = pstrdup(timestamptz_to_str(replyTime));
 
-		elog(DEBUG2, "write %X/%X flush %X/%X apply %X/%X%s reply_time %s",
-			 LSN_FORMAT_ARGS(writePtr),
-			 LSN_FORMAT_ARGS(flushPtr),
-			 LSN_FORMAT_ARGS(applyPtr),
+		elog(DEBUG2, "write %016" PRIX64 " flush %016" PRIX64 " apply %016" PRIX64 "%s reply_time %s",
+			 writePtr,
+			 flushPtr,
+			 applyPtr,
 			 replyRequested ? " (reply requested)" : "",
 			 replyTimeStr);
 
@@ -3193,9 +3194,9 @@ XLogSendPhysical(void)
 
 		WalSndCaughtUp = true;
 
-		elog(DEBUG1, "walsender reached end of timeline at %X/%X (sent up to %X/%X)",
-			 LSN_FORMAT_ARGS(sendTimeLineValidUpto),
-			 LSN_FORMAT_ARGS(sentPtr));
+		elog(DEBUG1, "walsender reached end of timeline at %016" PRIX64 " (sent up to %016" PRIX64 ")",
+			 sendTimeLineValidUpto,
+			 sentPtr);
 		return;
 	}
 
@@ -3334,8 +3335,8 @@ retry:
 	{
 		char		activitymsg[50];
 
-		snprintf(activitymsg, sizeof(activitymsg), "streaming %X/%X",
-				 LSN_FORMAT_ARGS(sentPtr));
+		snprintf(activitymsg, sizeof(activitymsg), "streaming %016" PRIX64,
+				 sentPtr);
 		set_ps_display(activitymsg);
 	}
 }
diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index 5acb4508f85..393380856a5 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -1364,17 +1364,17 @@ LogCurrentRunningXacts(RunningTransactions CurrRunningXacts)
 
 	if (xlrec.subxid_overflow)
 		elog(DEBUG2,
-			 "snapshot of %d running transactions overflowed (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
+			 "snapshot of %d running transactions overflowed (lsn %016" PRIX64 " oldest xid %u latest complete %u next xid %u)",
 			 CurrRunningXacts->xcnt,
-			 LSN_FORMAT_ARGS(recptr),
+			 recptr,
 			 CurrRunningXacts->oldestRunningXid,
 			 CurrRunningXacts->latestCompletedXid,
 			 CurrRunningXacts->nextXid);
 	else
 		elog(DEBUG2,
-			 "snapshot of %d+%d running transaction ids (lsn %X/%X oldest xid %u latest complete %u next xid %u)",
+			 "snapshot of %d+%d running transaction ids (lsn %016" PRIX64 " oldest xid %u latest complete %u next xid %u)",
 			 CurrRunningXacts->xcnt, CurrRunningXacts->subxcnt,
-			 LSN_FORMAT_ARGS(recptr),
+			 recptr,
 			 CurrRunningXacts->oldestRunningXid,
 			 CurrRunningXacts->latestCompletedXid,
 			 CurrRunningXacts->nextXid);
diff --git a/src/backend/utils/activity/pgstat.c b/src/backend/utils/activity/pgstat.c
index 7c8e274f082..d2f96158657 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -1602,8 +1602,8 @@ pgstat_write_statsfile(XLogRecPtr redo)
 	/* we're shutting down, so it's ok to just override this */
 	pgstat_fetch_consistency = PGSTAT_FETCH_CONSISTENCY_NONE;
 
-	elog(DEBUG2, "writing stats file \"%s\" with redo %X/%X", statfile,
-		 LSN_FORMAT_ARGS(redo));
+	elog(DEBUG2, "writing stats file \"%s\" with redo %016" PRIX64, statfile,
+		 redo);
 
 	/*
 	 * Open the statistics temp file to write out the current values.
@@ -1785,8 +1785,8 @@ pgstat_read_statsfile(XLogRecPtr redo)
 	/* shouldn't be called from postmaster */
 	Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
 
-	elog(DEBUG2, "reading stats file \"%s\" with redo %X/%X", statfile,
-		 LSN_FORMAT_ARGS(redo));
+	elog(DEBUG2, "reading stats file \"%s\" with redo %016" PRIX64, statfile,
+		 redo);
 
 	/*
 	 * Try to open the stats file. If it doesn't exist, the backends simply
@@ -1835,8 +1835,8 @@ pgstat_read_statsfile(XLogRecPtr redo)
 
 	if (file_redo != redo)
 	{
-		elog(WARNING, "found incorrect redo LSN %X/%X (expected %X/%X)",
-			 LSN_FORMAT_ARGS(file_redo), LSN_FORMAT_ARGS(redo));
+		elog(WARNING, "found incorrect redo LSN %016" PRIX64 " (expected %016" PRIX64 ")",
+			 file_redo, redo);
 		goto error;
 	}
 
diff --git a/src/backend/utils/adt/pg_lsn.c b/src/backend/utils/adt/pg_lsn.c
index 16311590a14..12af92e8acf 100644
--- a/src/backend/utils/adt/pg_lsn.c
+++ b/src/backend/utils/adt/pg_lsn.c
@@ -18,6 +18,7 @@
 #include "utils/numeric.h"
 #include "utils/pg_lsn.h"
 
+/* These values are used for the legacy format with a slash. */
 #define MAXPG_LSNLEN			17
 #define MAXPG_LSNCOMPONENT	8
 
@@ -33,10 +34,17 @@ pg_lsn_in_internal(const char *str, bool *have_error)
 	uint32		id,
 				off;
 	XLogRecPtr	result;
+	char		dummy;
 
 	Assert(have_error != NULL);
 	*have_error = false;
 
+	/* Try to parse it directly as a simple hex value. */
+	if (sscanf(str, "%" SCNx64 "%c", &result, &dummy) == 1)
+		return result;
+
+	/* Otherwise try to parse the legacy format. */
+
 	/* Sanity check input format. */
 	len1 = strspn(str, "0123456789abcdefABCDEF");
 	if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
@@ -83,7 +91,7 @@ pg_lsn_out(PG_FUNCTION_ARGS)
 	char		buf[MAXPG_LSNLEN + 1];
 	char	   *result;
 
-	snprintf(buf, sizeof buf, "%X/%X", LSN_FORMAT_ARGS(lsn));
+	snprintf(buf, sizeof buf, "%016" PRIX64, lsn);
 	result = pstrdup(buf);
 	PG_RETURN_CSTRING(result);
 }
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index dc0c805137a..c252644b5a8 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -480,17 +480,14 @@ reached_end_position(XLogRecPtr segendpos, uint32 timeline,
 		if (r == 1)
 		{
 			char		xlogend[64] = {0};
-			uint32		hi,
-						lo;
 
 			r = read(bgpipe[0], xlogend, sizeof(xlogend) - 1);
 			if (r < 0)
 				pg_fatal("could not read from ready pipe: %m");
 
-			if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
+			if (sscanf(xlogend, "%" SCNx64, &xlogendptr) != 1)
 				pg_fatal("could not parse write-ahead log location \"%s\"",
 						 xlogend);
-			xlogendptr = ((uint64) hi) << 32 | lo;
 			has_xlogendptr = 1;
 
 			/*
@@ -618,8 +615,6 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier,
 				 int wal_compress_level)
 {
 	logstreamer_param *param;
-	uint32		hi,
-				lo;
 	char		statusdir[MAXPGPATH];
 
 	param = pg_malloc0(sizeof(logstreamer_param));
@@ -629,10 +624,9 @@ StartLogStreamer(char *startpos, uint32 timeline, char *sysidentifier,
 	param->wal_compress_level = wal_compress_level;
 
 	/* Convert the starting position */
-	if (sscanf(startpos, "%X/%X", &hi, &lo) != 2)
+	if (sscanf(startpos, "%016" SCNx64, &param->startptr) != 1)
 		pg_fatal("could not parse write-ahead log location \"%s\"",
 				 startpos);
-	param->startptr = ((uint64) hi) << 32 | lo;
 	/* Round off to even segment position */
 	param->startptr -= XLogSegmentOffset(param->startptr, WalSegSz);
 
@@ -2227,8 +2221,6 @@ BaseBackup(char *compression_algorithm, char *compression_detail,
 		 * casting to a different size on WIN64.
 		 */
 		intptr_t	bgchild_handle = bgchild;
-		uint32		hi,
-					lo;
 #endif
 
 		if (verbose)
@@ -2254,10 +2246,9 @@ BaseBackup(char *compression_algorithm, char *compression_detail,
 		 * value directly in the variable, and then set the flag that says
 		 * it's there.
 		 */
-		if (sscanf(xlogend, "%X/%X", &hi, &lo) != 2)
+		if (sscanf(xlogend, "%" SCNx64, &xlogendptr) != 1)
 			pg_fatal("could not parse write-ahead log location \"%s\"",
 					 xlogend);
-		xlogendptr = ((uint64) hi) << 32 | lo;
 		InterlockedIncrement(&has_xlogendptr);
 
 		/* First wait for the thread to exit */
diff --git a/src/bin/pg_basebackup/pg_createsubscriber.c b/src/bin/pg_basebackup/pg_createsubscriber.c
index c4b96b6a160..d48689d400f 100644
--- a/src/bin/pg_basebackup/pg_createsubscriber.c
+++ b/src/bin/pg_basebackup/pg_createsubscriber.c
@@ -1250,8 +1250,8 @@ setup_recovery(const struct LogicalRepInfo *dbinfo, const char *datadir, const c
 	{
 		appendPQExpBuffer(recoveryconfcontents, "# dry run mode");
 		appendPQExpBuffer(recoveryconfcontents,
-						  "recovery_target_lsn = '%X/%X'\n",
-						  LSN_FORMAT_ARGS((XLogRecPtr) InvalidXLogRecPtr));
+						  "recovery_target_lsn = '%016" PRIX64 "'\n",
+						  InvalidXLogRecPtr);
 	}
 	else
 	{
@@ -1814,7 +1814,7 @@ set_replication_progress(PGconn *conn, const struct LogicalRepInfo *dbinfo, cons
 	if (dry_run)
 	{
 		suboid = InvalidOid;
-		lsnstr = psprintf("%X/%X", LSN_FORMAT_ARGS((XLogRecPtr) InvalidXLogRecPtr));
+		lsnstr = psprintf("%016" PRIX64, InvalidXLogRecPtr);
 	}
 	else
 	{
diff --git a/src/bin/pg_basebackup/pg_receivewal.c b/src/bin/pg_basebackup/pg_receivewal.c
index f8e091c72a1..16bbfb7d507 100644
--- a/src/bin/pg_basebackup/pg_receivewal.c
+++ b/src/bin/pg_basebackup/pg_receivewal.c
@@ -188,15 +188,15 @@ stop_streaming(XLogRecPtr xlogpos, uint32 timeline, bool segment_finished)
 
 	/* we assume that we get called once at the end of each segment */
 	if (verbose && segment_finished)
-		pg_log_info("finished segment at %X/%X (timeline %u)",
-					LSN_FORMAT_ARGS(xlogpos),
+		pg_log_info("finished segment at %016" PRIX64 " (timeline %u)",
+					xlogpos,
 					timeline);
 
 	if (!XLogRecPtrIsInvalid(endpos) && endpos < xlogpos)
 	{
 		if (verbose)
-			pg_log_info("stopped log streaming at %X/%X (timeline %u)",
-						LSN_FORMAT_ARGS(xlogpos),
+			pg_log_info("stopped log streaming at %016" PRIX64 " (timeline %u)",
+						xlogpos,
 						timeline);
 		time_to_stop = true;
 		return true;
@@ -211,9 +211,9 @@ stop_streaming(XLogRecPtr xlogpos, uint32 timeline, bool segment_finished)
 	 * timeline, but it's close enough for reporting purposes.
 	 */
 	if (verbose && prevtimeline != 0 && prevtimeline != timeline)
-		pg_log_info("switched to timeline %u at %X/%X",
+		pg_log_info("switched to timeline %u at %016" PRIX64,
 					timeline,
-					LSN_FORMAT_ARGS(prevpos));
+					prevpos);
 
 	prevtimeline = timeline;
 	prevpos = xlogpos;
@@ -575,8 +575,8 @@ StreamLog(void)
 	 * Start the replication
 	 */
 	if (verbose)
-		pg_log_info("starting log streaming at %X/%X (timeline %u)",
-					LSN_FORMAT_ARGS(stream.startpos),
+		pg_log_info("starting log streaming at %016" PRIX64 " (timeline %u)",
+					stream.startpos,
 					stream.timeline);
 
 	stream.stream_stop = stop_streaming;
@@ -651,8 +651,6 @@ main(int argc, char **argv)
 	int			c;
 	int			option_index;
 	char	   *db_name;
-	uint32		hi,
-				lo;
 	pg_compress_specification compression_spec;
 	char	   *compression_detail = NULL;
 	char	   *compression_algorithm_str = "none";
@@ -689,9 +687,8 @@ main(int argc, char **argv)
 				basedir = pg_strdup(optarg);
 				break;
 			case 'E':
-				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				if (sscanf(optarg, "%" SCNx64, &endpos) != 1)
 					pg_fatal("could not parse end position \"%s\"", optarg);
-				endpos = ((uint64) hi) << 32 | lo;
 				break;
 			case 'h':
 				dbhost = pg_strdup(optarg);
diff --git a/src/bin/pg_basebackup/pg_recvlogical.c b/src/bin/pg_basebackup/pg_recvlogical.c
index b9ea23e1426..0371b393bd8 100644
--- a/src/bin/pg_basebackup/pg_recvlogical.c
+++ b/src/bin/pg_basebackup/pg_recvlogical.c
@@ -140,9 +140,9 @@ sendFeedback(PGconn *conn, TimestampTz now, bool force, bool replyRequested)
 		return true;
 
 	if (verbose)
-		pg_log_info("confirming write up to %X/%X, flush to %X/%X (slot %s)",
-					LSN_FORMAT_ARGS(output_written_lsn),
-					LSN_FORMAT_ARGS(output_fsync_lsn),
+		pg_log_info("confirming write up to %016" PRIX64 ", flush to %016" PRIX64 " (slot %s)",
+					output_written_lsn,
+					output_fsync_lsn,
 					replication_slot);
 
 	replybuf[len] = 'r';
@@ -234,14 +234,14 @@ StreamLogicalLog(void)
 	 * Start the replication
 	 */
 	if (verbose)
-		pg_log_info("starting log streaming at %X/%X (slot %s)",
-					LSN_FORMAT_ARGS(startpos),
+		pg_log_info("starting log streaming at %016" PRIX64 " (slot %s)",
+					startpos,
 					replication_slot);
 
 	/* Initiate the replication stream at specified location */
 	query = createPQExpBuffer();
-	appendPQExpBuffer(query, "START_REPLICATION SLOT \"%s\" LOGICAL %X/%X",
-					  replication_slot, LSN_FORMAT_ARGS(startpos));
+	appendPQExpBuffer(query, "START_REPLICATION SLOT \"%s\" LOGICAL %016" PRIX64,
+					  replication_slot, startpos);
 
 	/* print options if there are any */
 	if (noptions)
@@ -721,8 +721,6 @@ main(int argc, char **argv)
 	};
 	int			c;
 	int			option_index;
-	uint32		hi,
-				lo;
 	char	   *db_name;
 
 	pg_logging_init(argv[0]);
@@ -790,14 +788,12 @@ main(int argc, char **argv)
 				break;
 /* replication options */
 			case 'I':
-				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				if (sscanf(optarg, "%" SCNx64, &startpos) != 1)
 					pg_fatal("could not parse start position \"%s\"", optarg);
-				startpos = ((uint64) hi) << 32 | lo;
 				break;
 			case 'E':
-				if (sscanf(optarg, "%X/%X", &hi, &lo) != 2)
+				if (sscanf(optarg, "%" SCNx64, &endpos) != 1)
 					pg_fatal("could not parse end position \"%s\"", optarg);
-				endpos = ((uint64) hi) << 32 | lo;
 				break;
 			case 'o':
 				{
@@ -1051,13 +1047,13 @@ prepareToTerminate(PGconn *conn, XLogRecPtr endpos, StreamStopReason reason,
 				pg_log_info("received interrupt signal, exiting");
 				break;
 			case STREAM_STOP_KEEPALIVE:
-				pg_log_info("end position %X/%X reached by keepalive",
-							LSN_FORMAT_ARGS(endpos));
+				pg_log_info("end position %016" PRIX64 " reached by keepalive",
+							endpos);
 				break;
 			case STREAM_STOP_END_OF_WAL:
 				Assert(!XLogRecPtrIsInvalid(lsn));
-				pg_log_info("end position %X/%X reached by WAL record at %X/%X",
-							LSN_FORMAT_ARGS(endpos), LSN_FORMAT_ARGS(lsn));
+				pg_log_info("end position %016" PRIX64 " reached by WAL record at %016" PRIX64,
+							endpos, lsn);
 				break;
 			case STREAM_STOP_NONE:
 				Assert(false);
diff --git a/src/bin/pg_basebackup/receivelog.c b/src/bin/pg_basebackup/receivelog.c
index 6b6e32dfbdf..f9e8cbab05a 100644
--- a/src/bin/pg_basebackup/receivelog.c
+++ b/src/bin/pg_basebackup/receivelog.c
@@ -571,9 +571,9 @@ ReceiveXlogStream(PGconn *conn, StreamCtl *stream)
 			return true;
 
 		/* Initiate the replication stream at specified location */
-		snprintf(query, sizeof(query), "START_REPLICATION %s%X/%X TIMELINE %u",
+		snprintf(query, sizeof(query), "START_REPLICATION %s%016" PRIX64 " TIMELINE %u",
 				 slotcmd,
-				 LSN_FORMAT_ARGS(stream->startpos),
+				 stream->startpos,
 				 stream->timeline);
 		res = PQexec(conn, query);
 		if (PQresultStatus(res) != PGRES_COPY_BOTH)
@@ -628,9 +628,9 @@ ReceiveXlogStream(PGconn *conn, StreamCtl *stream)
 			}
 			if (stream->startpos > stoppos)
 			{
-				pg_log_error("server stopped streaming timeline %u at %X/%X, but reported next timeline %u to begin at %X/%X",
-							 stream->timeline, LSN_FORMAT_ARGS(stoppos),
-							 newtimeline, LSN_FORMAT_ARGS(stream->startpos));
+				pg_log_error("server stopped streaming timeline %u at %016" PRIX64 ", but reported next timeline %u to begin at %016" PRIX64,
+							 stream->timeline, stoppos,
+							 newtimeline, stream->startpos);
 				goto error;
 			}
 
@@ -697,15 +697,12 @@ error:
 static bool
 ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos, uint32 *timeline)
 {
-	uint32		startpos_xlogid,
-				startpos_xrecoff;
-
 	/*----------
 	 * The result set consists of one row and two columns, e.g:
 	 *
 	 *	next_tli | next_tli_startpos
 	 * ----------+-------------------
-	 *		   4 | 0/9949AE0
+	 *		   4 | 0000000009949AE0
 	 *
 	 * next_tli is the timeline ID of the next timeline after the one that
 	 * just finished streaming. next_tli_startpos is the WAL location where
@@ -720,14 +717,12 @@ ReadEndOfStreamingResult(PGresult *res, XLogRecPtr *startpos, uint32 *timeline)
 	}
 
 	*timeline = atoi(PQgetvalue(res, 0, 0));
-	if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &startpos_xlogid,
-			   &startpos_xrecoff) != 2)
+	if (sscanf(PQgetvalue(res, 0, 1), "%" SCNx64, startpos) != 1)
 	{
 		pg_log_error("could not parse next timeline's starting point \"%s\"",
 					 PQgetvalue(res, 0, 1));
 		return false;
 	}
-	*startpos = ((uint64) startpos_xlogid << 32) | startpos_xrecoff;
 
 	return true;
 }
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 021ab61fcb0..26364f58da2 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -479,8 +479,6 @@ RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli,
 				  XLogRecPtr *startpos, char **db_name)
 {
 	PGresult   *res;
-	uint32		hi,
-				lo;
 
 	/* Check connection existence */
 	Assert(conn != NULL);
@@ -514,7 +512,7 @@ RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli,
 	/* Get LSN start position if necessary */
 	if (startpos != NULL)
 	{
-		if (sscanf(PQgetvalue(res, 0, 2), "%X/%X", &hi, &lo) != 2)
+		if (sscanf(PQgetvalue(res, 0, 2), "%" SCNx64, startpos) != 1)
 		{
 			pg_log_error("could not parse write-ahead log location \"%s\"",
 						 PQgetvalue(res, 0, 2));
@@ -522,7 +520,6 @@ RunIdentifySystem(PGconn *conn, char **sysid, TimeLineID *starttli,
 			PQclear(res);
 			return false;
 		}
-		*startpos = ((uint64) hi) << 32 | lo;
 	}
 
 	/* Get database name, only available in 9.4 and newer versions */
@@ -617,17 +614,13 @@ GetSlotInformation(PGconn *conn, const char *slot_name,
 	/* restart LSN */
 	if (!PQgetisnull(res, 0, 1))
 	{
-		uint32		hi,
-					lo;
-
-		if (sscanf(PQgetvalue(res, 0, 1), "%X/%X", &hi, &lo) != 2)
+		if (sscanf(PQgetvalue(res, 0, 1), "%" SCNx64, &lsn_loc) != 1)
 		{
 			pg_log_error("could not parse restart_lsn \"%s\" for replication slot \"%s\"",
 						 PQgetvalue(res, 0, 1), slot_name);
 			PQclear(res);
 			return false;
 		}
-		lsn_loc = ((uint64) hi) << 32 | lo;
 	}
 
 	/* current TLI */
diff --git a/src/bin/pg_basebackup/t/010_pg_basebackup.pl b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
index 89ff26b6314..760497446a6 100644
--- a/src/bin/pg_basebackup/t/010_pg_basebackup.pl
+++ b/src/bin/pg_basebackup/t/010_pg_basebackup.pl
@@ -854,7 +854,7 @@ $node->command_ok(
 $lsn = $node->safe_psql('postgres',
 	q{SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'slot1'}
 );
-like($lsn, qr!^0/[0-9A-Z]{7,8}$!, 'restart LSN of slot has advanced');
+like($lsn, qr!^[0-9A-Z]{16}$!, 'restart LSN of slot has advanced');
 rmtree("$tempdir/backupxs_sl");
 
 $node->command_ok(
diff --git a/src/bin/pg_combinebackup/backup_label.c b/src/bin/pg_combinebackup/backup_label.c
index e89d4603f09..3d0fee9d6cd 100644
--- a/src/bin/pg_combinebackup/backup_label.c
+++ b/src/bin/pg_combinebackup/backup_label.c
@@ -243,18 +243,13 @@ parse_lsn(char *s, char *e, XLogRecPtr *lsn, char **c)
 	char		save = *e;
 	int			nchars;
 	bool		success;
-	unsigned	hi;
-	unsigned	lo;
 
 	*e = '\0';
-	success = (sscanf(s, "%X/%X%n", &hi, &lo, &nchars) == 2);
+	success = (sscanf(s, "%" SCNx64 "%n", lsn, &nchars) == 1);
 	*e = save;
 
 	if (success)
-	{
-		*lsn = ((XLogRecPtr) hi) << 32 | (XLogRecPtr) lo;
 		*c = s + nchars;
-	}
 
 	return success;
 }
diff --git a/src/bin/pg_combinebackup/pg_combinebackup.c b/src/bin/pg_combinebackup/pg_combinebackup.c
index a0eb3f686d6..9707f29d403 100644
--- a/src/bin/pg_combinebackup/pg_combinebackup.c
+++ b/src/bin/pg_combinebackup/pg_combinebackup.c
@@ -559,10 +559,10 @@ check_backup_label_files(int n_backups, char **backup_dirs)
 			pg_fatal("backup at \"%s\" starts on timeline %u, but expected %u",
 					 backup_dirs[i], start_tli, check_tli);
 		if (i < n_backups - 1 && start_lsn != check_lsn)
-			pg_fatal("backup at \"%s\" starts at LSN %X/%X, but expected %X/%X",
+			pg_fatal("backup at \"%s\" starts at LSN %016" PRIX64 ", but expected %016" PRIX64,
 					 backup_dirs[i],
-					 LSN_FORMAT_ARGS(start_lsn),
-					 LSN_FORMAT_ARGS(check_lsn));
+					 start_lsn,
+					 check_lsn);
 		check_tli = previous_tli;
 		check_lsn = previous_lsn;
 
diff --git a/src/bin/pg_combinebackup/write_manifest.c b/src/bin/pg_combinebackup/write_manifest.c
index 313f8929df5..cd3727ec3f5 100644
--- a/src/bin/pg_combinebackup/write_manifest.c
+++ b/src/bin/pg_combinebackup/write_manifest.c
@@ -155,11 +155,11 @@ finalize_manifest(manifest_writer *mwriter,
 	for (wal_range = first_wal_range; wal_range != NULL;
 		 wal_range = wal_range->next)
 		appendStringInfo(&mwriter->buf,
-						 "%s{ \"Timeline\": %u, \"Start-LSN\": \"%X/%X\", \"End-LSN\": \"%X/%X\" }",
+						 "%s{ \"Timeline\": %u, \"Start-LSN\": \"%016" PRIX64 "\", \"End-LSN\": \"%016" PRIX64 "\" }",
 						 wal_range == first_wal_range ? "" : ",\n",
 						 wal_range->tli,
-						 LSN_FORMAT_ARGS(wal_range->start_lsn),
-						 LSN_FORMAT_ARGS(wal_range->end_lsn));
+						 wal_range->start_lsn,
+						 wal_range->end_lsn);
 
 	/* Terminate the list of WAL ranges. */
 	appendStringInfoString(&mwriter->buf, "\n],\n");
diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c
index 9901a2bae51..8ea91e66d8f 100644
--- a/src/bin/pg_controldata/pg_controldata.c
+++ b/src/bin/pg_controldata/pg_controldata.c
@@ -245,10 +245,10 @@ main(int argc, char *argv[])
 		   dbState(ControlFile->state));
 	printf(_("pg_control last modified:             %s\n"),
 		   pgctime_str);
-	printf(_("Latest checkpoint location:           %X/%X\n"),
-		   LSN_FORMAT_ARGS(ControlFile->checkPoint));
-	printf(_("Latest checkpoint's REDO location:    %X/%X\n"),
-		   LSN_FORMAT_ARGS(ControlFile->checkPointCopy.redo));
+	printf(_("Latest checkpoint location:           %016" PRIX64 "\n"),
+		   ControlFile->checkPoint);
+	printf(_("Latest checkpoint's REDO location:    %016" PRIX64 "\n"),
+		   ControlFile->checkPointCopy.redo);
 	printf(_("Latest checkpoint's REDO WAL file:    %s\n"),
 		   xlogfilename);
 	printf(_("Latest checkpoint's TimeLineID:       %u\n"),
@@ -282,16 +282,16 @@ main(int argc, char *argv[])
 		   ControlFile->checkPointCopy.newestCommitTsXid);
 	printf(_("Time of latest checkpoint:            %s\n"),
 		   ckpttime_str);
-	printf(_("Fake LSN counter for unlogged rels:   %X/%X\n"),
-		   LSN_FORMAT_ARGS(ControlFile->unloggedLSN));
-	printf(_("Minimum recovery ending location:     %X/%X\n"),
-		   LSN_FORMAT_ARGS(ControlFile->minRecoveryPoint));
+	printf(_("Fake LSN counter for unlogged rels:   %016" PRIX64 "\n"),
+		   ControlFile->unloggedLSN);
+	printf(_("Minimum recovery ending location:     %016" PRIX64 "\n"),
+		   ControlFile->minRecoveryPoint);
 	printf(_("Min recovery ending loc's timeline:   %u\n"),
 		   ControlFile->minRecoveryPointTLI);
-	printf(_("Backup start location:                %X/%X\n"),
-		   LSN_FORMAT_ARGS(ControlFile->backupStartPoint));
-	printf(_("Backup end location:                  %X/%X\n"),
-		   LSN_FORMAT_ARGS(ControlFile->backupEndPoint));
+	printf(_("Backup start location:                %016" PRIX64 "\n"),
+		   ControlFile->backupStartPoint);
+	printf(_("Backup end location:                  %016" PRIX64 "\n"),
+		   ControlFile->backupEndPoint);
 	printf(_("End-of-backup record required:        %s\n"),
 		   ControlFile->backupEndRequired ? _("yes") : _("no"));
 	printf(_("wal_level setting:                    %s\n"),
diff --git a/src/bin/pg_rewind/libpq_source.c b/src/bin/pg_rewind/libpq_source.c
index 4a6dfb586d3..b0f14be8f17 100644
--- a/src/bin/pg_rewind/libpq_source.c
+++ b/src/bin/pg_rewind/libpq_source.c
@@ -209,17 +209,13 @@ libpq_get_current_wal_insert_lsn(rewind_source *source)
 {
 	PGconn	   *conn = ((libpq_source *) source)->conn;
 	XLogRecPtr	result;
-	uint32		hi;
-	uint32		lo;
 	char	   *val;
 
 	val = run_simple_query(conn, "SELECT pg_current_wal_insert_lsn()");
 
-	if (sscanf(val, "%X/%X", &hi, &lo) != 2)
+	if (sscanf(val, "%" SCNx64, &result) != 1)
 		pg_fatal("unrecognized result \"%s\" for current WAL insert location", val);
 
-	result = ((uint64) hi) << 32 | lo;
-
 	pg_free(val);
 
 	return result;
diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c
index 2cd44625ca3..28a536a1107 100644
--- a/src/bin/pg_rewind/parsexlog.c
+++ b/src/bin/pg_rewind/parsexlog.c
@@ -89,12 +89,12 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex,
 			XLogRecPtr	errptr = xlogreader->EndRecPtr;
 
 			if (errormsg)
-				pg_fatal("could not read WAL record at %X/%X: %s",
-						 LSN_FORMAT_ARGS(errptr),
+				pg_fatal("could not read WAL record at %016" PRIX64 ": %s",
+						 errptr,
 						 errormsg);
 			else
-				pg_fatal("could not read WAL record at %X/%X",
-						 LSN_FORMAT_ARGS(errptr));
+				pg_fatal("could not read WAL record at %016" PRIX64,
+						 errptr);
 		}
 
 		extractPageInfo(xlogreader);
@@ -105,8 +105,8 @@ extractPageMap(const char *datadir, XLogRecPtr startpoint, int tliIndex,
 	 * messed up.
 	 */
 	if (xlogreader->EndRecPtr != endpoint)
-		pg_fatal("end pointer %X/%X is not a valid end point; expected %X/%X",
-				 LSN_FORMAT_ARGS(endpoint), LSN_FORMAT_ARGS(xlogreader->EndRecPtr));
+		pg_fatal("end pointer %016" PRIX64 " is not a valid end point; expected %016" PRIX64,
+				 endpoint, xlogreader->EndRecPtr);
 
 	XLogReaderFree(xlogreader);
 	if (xlogreadfd != -1)
@@ -143,11 +143,11 @@ readOneRecord(const char *datadir, XLogRecPtr ptr, int tliIndex,
 	if (record == NULL)
 	{
 		if (errormsg)
-			pg_fatal("could not read WAL record at %X/%X: %s",
-					 LSN_FORMAT_ARGS(ptr), errormsg);
+			pg_fatal("could not read WAL record at %016" PRIX64 ": %s",
+					 ptr, errormsg);
 		else
-			pg_fatal("could not read WAL record at %X/%X",
-					 LSN_FORMAT_ARGS(ptr));
+			pg_fatal("could not read WAL record at %016" PRIX64,
+					 ptr);
 	}
 	endptr = xlogreader->EndRecPtr;
 
@@ -211,12 +211,12 @@ findLastCheckpoint(const char *datadir, XLogRecPtr forkptr, int tliIndex,
 		if (record == NULL)
 		{
 			if (errormsg)
-				pg_fatal("could not find previous WAL record at %X/%X: %s",
-						 LSN_FORMAT_ARGS(searchptr),
+				pg_fatal("could not find previous WAL record at %016" PRIX64 ": %s",
+						 searchptr,
 						 errormsg);
 			else
-				pg_fatal("could not find previous WAL record at %X/%X",
-						 LSN_FORMAT_ARGS(searchptr));
+				pg_fatal("could not find previous WAL record at %016" PRIX64,
+						 searchptr);
 		}
 
 		/* Detect if a new WAL file has been opened */
@@ -459,8 +459,8 @@ extractPageInfo(XLogReaderState *record)
 		 * track that change.
 		 */
 		pg_fatal("WAL record modifies a relation, but record type is not recognized: "
-				 "lsn: %X/%X, rmid: %d, rmgr: %s, info: %02X",
-				 LSN_FORMAT_ARGS(record->ReadRecPtr),
+				 "lsn: %016" PRIX64 ", rmid: %d, rmgr: %s, info: %02X",
+				 record->ReadRecPtr,
 				 rmid, RmgrName(rmid), info);
 	}
 
diff --git a/src/bin/pg_rewind/pg_rewind.c b/src/bin/pg_rewind/pg_rewind.c
index 2ce99d06d1d..d2822b00f80 100644
--- a/src/bin/pg_rewind/pg_rewind.c
+++ b/src/bin/pg_rewind/pg_rewind.c
@@ -393,8 +393,8 @@ main(int argc, char **argv)
 								   targetHistory, targetNentries,
 								   &divergerec, &lastcommontliIndex);
 
-		pg_log_info("servers diverged at WAL location %X/%X on timeline %u",
-					LSN_FORMAT_ARGS(divergerec),
+		pg_log_info("servers diverged at WAL location %016" PRIX64 " on timeline %u",
+					divergerec,
 					targetHistory[lastcommontliIndex].tli);
 
 		/*
@@ -460,8 +460,8 @@ main(int argc, char **argv)
 
 	findLastCheckpoint(datadir_target, divergerec, lastcommontliIndex,
 					   &chkptrec, &chkpttli, &chkptredo, restore_command);
-	pg_log_info("rewinding from last common checkpoint at %X/%X on timeline %u",
-				LSN_FORMAT_ARGS(chkptrec), chkpttli);
+	pg_log_info("rewinding from last common checkpoint at %016" PRIX64 " on timeline %u",
+				chkptrec, chkpttli);
 
 	/* Initialize the hash table to track the status of each file */
 	filehash_init();
@@ -900,9 +900,9 @@ getTimelineHistory(TimeLineID tli, bool is_source, int *nentries)
 			TimeLineHistoryEntry *entry;
 
 			entry = &history[i];
-			pg_log_debug("%u: %X/%X - %X/%X", entry->tli,
-						 LSN_FORMAT_ARGS(entry->begin),
-						 LSN_FORMAT_ARGS(entry->end));
+			pg_log_debug("%u: %016" PRIX64 " - %016" PRIX64, entry->tli,
+						 entry->begin,
+						 entry->end);
 		}
 	}
 
@@ -979,14 +979,14 @@ createBackupLabel(XLogRecPtr startpoint, TimeLineID starttli, XLogRecPtr checkpo
 	strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", tmp);
 
 	len = snprintf(buf, sizeof(buf),
-				   "START WAL LOCATION: %X/%X (file %s)\n"
-				   "CHECKPOINT LOCATION: %X/%X\n"
+				   "START WAL LOCATION: %016" PRIX64 " (file %s)\n"
+				   "CHECKPOINT LOCATION: %016" PRIX64 "\n"
 				   "BACKUP METHOD: pg_rewind\n"
 				   "BACKUP FROM: standby\n"
 				   "START TIME: %s\n",
 	/* omit LABEL: line */
-				   LSN_FORMAT_ARGS(startpoint), xlogfilename,
-				   LSN_FORMAT_ARGS(checkpointloc),
+				   startpoint, xlogfilename,
+				   checkpointloc,
 				   strfbuf);
 	if (len >= sizeof(buf))
 		pg_fatal("backup label buffer too small");	/* shouldn't happen */
diff --git a/src/bin/pg_rewind/timeline.c b/src/bin/pg_rewind/timeline.c
index 4d9f0d8301b..b074a48045f 100644
--- a/src/bin/pg_rewind/timeline.c
+++ b/src/bin/pg_rewind/timeline.c
@@ -45,8 +45,7 @@ rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
 	{
 		char	   *ptr;
 		TimeLineID	tli;
-		uint32		switchpoint_hi;
-		uint32		switchpoint_lo;
+		XLogRecPtr	switchpoint;
 		int			nfields;
 
 		fline = bufptr;
@@ -66,7 +65,7 @@ rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
 		if (*ptr == '\0' || *ptr == '#')
 			continue;
 
-		nfields = sscanf(fline, "%u\t%X/%X", &tli, &switchpoint_hi, &switchpoint_lo);
+		nfields = sscanf(fline, "%u\t%016" PRIX64, &tli, &switchpoint);
 
 		if (nfields < 1)
 		{
@@ -75,7 +74,7 @@ rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
 			pg_log_error_detail("Expected a numeric timeline ID.");
 			exit(1);
 		}
-		if (nfields != 3)
+		if (nfields != 2)
 		{
 			pg_log_error("syntax error in history file: %s", fline);
 			pg_log_error_detail("Expected a write-ahead log switchpoint location.");
@@ -96,7 +95,7 @@ rewind_parseTimeLineHistory(char *buffer, TimeLineID targetTLI, int *nentries)
 		entry = &entries[nlines - 1];
 		entry->tli = tli;
 		entry->begin = prevend;
-		entry->end = ((uint64) (switchpoint_hi)) << 32 | (uint64) switchpoint_lo;
+		entry->end = switchpoint;
 		prevend = entry->end;
 
 		/* we ignore the remainder of each line */
diff --git a/src/bin/pg_verifybackup/pg_verifybackup.c b/src/bin/pg_verifybackup/pg_verifybackup.c
index c80f41d8697..6e1db179732 100644
--- a/src/bin/pg_verifybackup/pg_verifybackup.c
+++ b/src/bin/pg_verifybackup/pg_verifybackup.c
@@ -1206,10 +1206,10 @@ parse_required_wal(verifier_context *context, char *pg_waldump_path,
 	{
 		char	   *pg_waldump_cmd;
 
-		pg_waldump_cmd = psprintf("\"%s\" --quiet --path=\"%s\" --timeline=%u --start=%X/%X --end=%X/%X\n",
+		pg_waldump_cmd = psprintf("\"%s\" --quiet --path=\"%s\" --timeline=%u --start=%016" PRIX64 " --end=%016" PRIX64,
 								  pg_waldump_path, wal_directory, this_wal_range->tli,
-								  LSN_FORMAT_ARGS(this_wal_range->start_lsn),
-								  LSN_FORMAT_ARGS(this_wal_range->end_lsn));
+								  this_wal_range->start_lsn,
+								  this_wal_range->end_lsn);
 		fflush(NULL);
 		if (system(pg_waldump_cmd) != 0)
 			report_backup_error(context,
diff --git a/src/bin/pg_waldump/pg_waldump.c b/src/bin/pg_waldump/pg_waldump.c
index 51fb76efc48..d57a137f736 100644
--- a/src/bin/pg_waldump/pg_waldump.c
+++ b/src/bin/pg_waldump/pg_waldump.c
@@ -522,9 +522,9 @@ XLogRecordSaveFPWs(XLogReaderState *record, const char *savepath)
 		else
 			pg_fatal("invalid fork number: %u", fork);
 
-		snprintf(filename, MAXPGPATH, "%s/%08X-%08X-%08X.%u.%u.%u.%u%s", savepath,
+		snprintf(filename, MAXPGPATH, "%s/%08X-%016" PRIX64 ".%u.%u.%u.%u%s", savepath,
 				 record->seg.ws_tli,
-				 LSN_FORMAT_ARGS(record->ReadRecPtr),
+				 record->ReadRecPtr,
 				 rnode.spcOid, rnode.dbOid, rnode.relNumber, blk, forkname);
 
 		file = fopen(filename, PG_BINARY_W);
@@ -555,12 +555,12 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogReaderState *record)
 
 	XLogRecGetLen(record, &rec_len, &fpi_len);
 
-	printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, ",
+	printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %016" PRIX64 ", prev %016" PRIX64 ", ",
 		   desc->rm_name,
 		   rec_len, XLogRecGetTotalLen(record),
 		   XLogRecGetXid(record),
-		   LSN_FORMAT_ARGS(record->ReadRecPtr),
-		   LSN_FORMAT_ARGS(xl_prev));
+		   record->ReadRecPtr,
+		   xl_prev);
 
 	id = desc->rm_identify(info);
 	if (id == NULL)
@@ -656,8 +656,8 @@ XLogDumpDisplayStats(XLogDumpConfig *config, XLogStats *stats)
 	}
 	total_len = total_rec_len + total_fpi_len;
 
-	printf("WAL statistics between %X/%X and %X/%X:\n",
-		   LSN_FORMAT_ARGS(stats->startptr), LSN_FORMAT_ARGS(stats->endptr));
+	printf("WAL statistics between %016" PRIX64 "and %016" PRIX64 ":\n",
+		   stats->startptr, stats->endptr);
 
 	/*
 	 * 27 is strlen("Transaction/COMMIT_PREPARED"), 20 is strlen(2^64), 8 is
@@ -791,8 +791,6 @@ usage(void)
 int
 main(int argc, char **argv)
 {
-	uint32		xlogid;
-	uint32		xrecoff;
 	XLogReaderState *xlogreader_state;
 	XLogDumpPrivate private;
 	XLogDumpConfig config;
@@ -904,13 +902,12 @@ main(int argc, char **argv)
 				config.filter_by_extended = true;
 				break;
 			case 'e':
-				if (sscanf(optarg, "%X/%X", &xlogid, &xrecoff) != 2)
+				if (sscanf(optarg, "%" SCNx64, &private.endptr) != 1)
 				{
 					pg_log_error("invalid WAL location: \"%s\"",
 								 optarg);
 					goto bad_argument;
 				}
-				private.endptr = (uint64) xlogid << 32 | xrecoff;
 				break;
 			case 'f':
 				config.follow = true;
@@ -1002,14 +999,12 @@ main(int argc, char **argv)
 				config.filter_by_extended = true;
 				break;
 			case 's':
-				if (sscanf(optarg, "%X/%X", &xlogid, &xrecoff) != 2)
+				if (sscanf(optarg, "%" SCNx64, &private.startptr) != 1)
 				{
 					pg_log_error("invalid WAL location: \"%s\"",
 								 optarg);
 					goto bad_argument;
 				}
-				else
-					private.startptr = (uint64) xlogid << 32 | xrecoff;
 				break;
 			case 't':
 
@@ -1140,8 +1135,8 @@ main(int argc, char **argv)
 			XLogSegNoOffsetToRecPtr(segno, 0, WalSegSz, private.startptr);
 		else if (!XLByteInSeg(private.startptr, segno, WalSegSz))
 		{
-			pg_log_error("start WAL location %X/%X is not inside file \"%s\"",
-						 LSN_FORMAT_ARGS(private.startptr),
+			pg_log_error("start WAL location %016" PRIX64 " is not inside file \"%s\"",
+						 private.startptr,
 						 fname);
 			goto bad_argument;
 		}
@@ -1182,8 +1177,8 @@ main(int argc, char **argv)
 		if (!XLByteInSeg(private.endptr, segno, WalSegSz) &&
 			private.endptr != (segno + 1) * WalSegSz)
 		{
-			pg_log_error("end WAL location %X/%X is not inside file \"%s\"",
-						 LSN_FORMAT_ARGS(private.endptr),
+			pg_log_error("end WAL location %016" PRIX64 " is not inside file \"%s\"",
+						 private.endptr,
 						 argv[argc - 1]);
 			goto bad_argument;
 		}
@@ -1214,8 +1209,8 @@ main(int argc, char **argv)
 	first_record = XLogFindNextRecord(xlogreader_state, private.startptr);
 
 	if (first_record == InvalidXLogRecPtr)
-		pg_fatal("could not find a valid record after %X/%X",
-				 LSN_FORMAT_ARGS(private.startptr));
+		pg_fatal("could not find a valid record after %016" PRIX64,
+				 private.startptr);
 
 	/*
 	 * Display a message that we're skipping data if `from` wasn't a pointer
@@ -1224,11 +1219,11 @@ main(int argc, char **argv)
 	 */
 	if (first_record != private.startptr &&
 		XLogSegmentOffset(private.startptr, WalSegSz) != 0)
-		pg_log_info(ngettext("first record is after %X/%X, at %X/%X, skipping over %u byte",
-							 "first record is after %X/%X, at %X/%X, skipping over %u bytes",
+		pg_log_info(ngettext("first record is after %016" PRIX64 ", at %016" PRIX64 ", skipping over %u byte",
+							 "first record is after %016" PRIX64 ", at %016" PRIX64 ", skipping over %u bytes",
 							 (first_record - private.startptr)),
-					LSN_FORMAT_ARGS(private.startptr),
-					LSN_FORMAT_ARGS(first_record),
+					private.startptr,
+					first_record,
 					(uint32) (first_record - private.startptr));
 
 	if (config.stats == true && !config.quiet)
@@ -1309,8 +1304,8 @@ main(int argc, char **argv)
 		exit(0);
 
 	if (errormsg)
-		pg_fatal("error in WAL record at %X/%X: %s",
-				 LSN_FORMAT_ARGS(xlogreader_state->ReadRecPtr),
+		pg_fatal("error in WAL record at %016" PRIX64 ": %s",
+				 xlogreader_state->ReadRecPtr,
 				 errormsg);
 
 	XLogReaderFree(xlogreader_state);
diff --git a/src/bin/pg_waldump/t/001_basic.pl b/src/bin/pg_waldump/t/001_basic.pl
index 5c8fea275bb..0490192f195 100644
--- a/src/bin/pg_waldump/t/001_basic.pl
+++ b/src/bin/pg_waldump/t/001_basic.pl
@@ -41,11 +41,11 @@ command_fails_like(
 	qr/error: resource manager .* does not exist/,
 	'invalid rmgr name');
 command_fails_like(
-	[ 'pg_waldump', '--start' => 'bad' ],
+	[ 'pg_waldump', '--start' => 'hexbad' ],
 	qr/error: invalid WAL location/,
 	'invalid start LSN');
 command_fails_like(
-	[ 'pg_waldump', '--end' => 'bad' ],
+	[ 'pg_waldump', '--end' => 'hexbad' ],
 	qr/error: invalid WAL location/,
 	'invalid end LSN');
 
@@ -242,10 +242,9 @@ command_fails_like(
 {
 	# Construct a new LSN that is one byte past the original
 	# start_lsn.
-	my ($part1, $part2) = split qr{/}, $start_lsn;
-	my $lsn2 = hex $part2;
+	my $lsn2 = hex $start_lsn;
 	$lsn2++;
-	my $new_start = sprintf("%s/%X", $part1, $lsn2);
+	my $new_start = sprintf("%016X", $lsn2);
 
 	my (@cmd, $stdout, $stderr, $result);
 
diff --git a/src/bin/pg_waldump/t/002_save_fullpage.pl b/src/bin/pg_waldump/t/002_save_fullpage.pl
index 17b15e3a649..ac8ec219b21 100644
--- a/src/bin/pg_waldump/t/002_save_fullpage.pl
+++ b/src/bin/pg_waldump/t/002_save_fullpage.pl
@@ -80,7 +80,7 @@ $node->command_ok(
 	'pg_waldump with --save-fullpage runs');
 
 # This regexp will match filenames formatted as:
-# TLI-LSNh-LSNl.TBLSPCOID.DBOID.NODEOID.dd_fork with the components being:
+# TLI-LSN.TBLSPCOID.DBOID.NODEOID.dd_fork with the components being:
 # - Timeline ID in hex format.
 # - WAL LSN in hex format, as two 8-character numbers.
 # - Tablespace OID (0 for global).
@@ -89,7 +89,7 @@ $node->command_ok(
 # - Block number.
 # - Fork this block came from (vm, init, fsm, or main).
 my $file_re =
-  qr/^[0-9A-F]{8}-([0-9A-F]{8})-([0-9A-F]{8})[.][0-9]+[.][0-9]+[.][0-9]+[.][0-9]+(?:_vm|_init|_fsm|_main)?$/;
+  qr/^[0-9A-F]{8}-([0-9A-F]{16})[.][0-9]+[.][0-9]+[.][0-9]+[.][0-9]+(?:_vm|_init|_fsm|_main)?$/;
 
 my $file_count = 0;
 
@@ -101,11 +101,11 @@ for my $fullpath (glob "$tmp_folder/raw/*")
 	like($file, $file_re, "verify filename format for file $file");
 	$file_count++;
 
-	my ($hi_lsn_fn, $lo_lsn_fn) = ($file =~ $file_re);
+	my ($lsn_fn) = ($file =~ $file_re);
 	my ($hi_lsn_bk, $lo_lsn_bk) = get_block_lsn($fullpath, $blocksize);
 
 	# The LSN on the block comes before the file's LSN.
-	ok( $hi_lsn_fn . $lo_lsn_fn gt $hi_lsn_bk . $lo_lsn_bk,
+	ok( $lsn_fn gt $hi_lsn_bk . $lo_lsn_bk,
 		'LSN stored in the file precedes the one stored in the block');
 }
 
diff --git a/src/bin/pg_walsummary/t/002_blocks.pl b/src/bin/pg_walsummary/t/002_blocks.pl
index 27f29a3b0c6..2a8bc514cf6 100644
--- a/src/bin/pg_walsummary/t/002_blocks.pl
+++ b/src/bin/pg_walsummary/t/002_blocks.pl
@@ -79,10 +79,10 @@ my ($tli, $start_lsn, $end_lsn) = split(/\|/, $lines[0]);
 note("examining summary for TLI $tli from $start_lsn to $end_lsn");
 
 # Reconstruct the full pathname for the WAL summary file.
-my $filename = sprintf "%s/pg_wal/summaries/%08s%08s%08s%08s%08s.summary",
+my $filename = sprintf "%s/pg_wal/summaries/%08s%016s%016s.summary",
   $node1->data_dir, $tli,
-  split(m@/@, $start_lsn),
-  split(m@/@, $end_lsn);
+  $start_lsn,
+  $end_lsn;
 ok(-f $filename, "WAL summary file exists");
 
 # Run pg_walsummary on it. We expect exactly two blocks to be modified,
diff --git a/src/bin/psql/t/001_basic.pl b/src/bin/psql/t/001_basic.pl
index 3170bc86856..6d1d1b4f58c 100644
--- a/src/bin/psql/t/001_basic.pl
+++ b/src/bin/psql/t/001_basic.pl
@@ -76,7 +76,7 @@ psql_like($node, '\help SELECT', qr/SELECT/, '\help with argument');
 # Test clean handling of unsupported replication command responses
 psql_fails_like(
 	$node,
-	'START_REPLICATION 0/0',
+	'START_REPLICATION 0000000000000000',
 	qr/unexpected PQresultStatus: 8$/,
 	'handling of unexpected PQresultStatus');
 
diff --git a/src/common/parse_manifest.c b/src/common/parse_manifest.c
index 05858578207..baf881bfa6f 100644
--- a/src/common/parse_manifest.c
+++ b/src/common/parse_manifest.c
@@ -938,11 +938,5 @@ hexdecode_string(uint8 *result, char *input, int nbytes)
 static bool
 parse_xlogrecptr(XLogRecPtr *result, char *input)
 {
-	uint32		hi;
-	uint32		lo;
-
-	if (sscanf(input, "%X/%X", &hi, &lo) != 2)
-		return false;
-	*result = ((uint64) hi) << 32 | lo;
-	return true;
+	return sscanf(input, "%" SCNx64, result) == 1;
 }
diff --git a/src/include/access/rewriteheap.h b/src/include/access/rewriteheap.h
index 99c3f362adc..b9c9f1a5081 100644
--- a/src/include/access/rewriteheap.h
+++ b/src/include/access/rewriteheap.h
@@ -45,13 +45,13 @@ typedef struct LogicalRewriteMappingData
  * components:
  * 1) database oid or InvalidOid for shared relations
  * 2) the oid of the relation
- * 3) upper 32bit of the LSN at which a rewrite started
- * 4) lower 32bit of the LSN at which a rewrite started
- * 5) xid we are mapping for
- * 6) xid of the xact performing the mapping
+ * 3) LSN at which a rewrite started
+ * 4) xid we are mapping for
+ * 5) xid of the xact performing the mapping
  * ---
  */
-#define LOGICAL_REWRITE_FORMAT "map-%x-%x-%X_%X-%x-%x"
+#define LOGICAL_REWRITE_FORMAT "map-%x-%x-%016" PRIX64 "-%x-%x"
+#define LOGICAL_REWRITE_FORMAT_SCANF "map-%x-%x-%" SCNx64 "-%x-%x"
 extern void CheckPointLogicalRewriteHeap(void);
 
 #endif							/* REWRITE_HEAP_H */
diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h
index 9e41c9f6e84..764c724ecca 100644
--- a/src/include/access/xlogdefs.h
+++ b/src/include/access/xlogdefs.h
@@ -25,7 +25,7 @@ typedef uint64 XLogRecPtr;
  * WAL segment, initializing the first WAL page at WAL segment size, so no XLOG
  * record can begin at zero.
  */
-#define InvalidXLogRecPtr	0
+#define InvalidXLogRecPtr	((XLogRecPtr) 0)
 #define XLogRecPtrIsInvalid(r)	((r) == InvalidXLogRecPtr)
 
 /*
@@ -35,13 +35,6 @@ typedef uint64 XLogRecPtr;
  */
 #define FirstNormalUnloggedLSN	((XLogRecPtr) 1000)
 
-/*
- * Handy macro for printing XLogRecPtr in conventional format, e.g.,
- *
- * printf("%X/%X", LSN_FORMAT_ARGS(lsn));
- */
-#define LSN_FORMAT_ARGS(lsn) (AssertVariableIsOfTypeMacro((lsn), XLogRecPtr), (uint32) ((lsn) >> 32)), ((uint32) (lsn))
-
 /*
  * XLogSegNo - physical log file sequence number.
  */
diff --git a/src/test/recovery/t/006_logical_decoding.pl b/src/test/recovery/t/006_logical_decoding.pl
index 9f469101fd4..9eaa5137ca0 100644
--- a/src/test/recovery/t/006_logical_decoding.pl
+++ b/src/test/recovery/t/006_logical_decoding.pl
@@ -33,7 +33,7 @@ $node_primary->safe_psql('postgres',
 # Cover walsender error shutdown code
 my ($result, $stdout, $stderr) = $node_primary->psql(
 	'template1',
-	qq[START_REPLICATION SLOT test_slot LOGICAL 0/0],
+	qq[START_REPLICATION SLOT test_slot LOGICAL 0000000000000000],
 	replication => 'database');
 ok( $stderr =~
 	  m/replication slot "test_slot" was not created in this database/,
@@ -52,7 +52,7 @@ like(
 # decoding should not be allowed.
 ($result, $stdout, $stderr) = $node_primary->psql(
 	'template1',
-	qq[START_REPLICATION SLOT s1 LOGICAL 0/1],
+	qq[START_REPLICATION SLOT s1 LOGICAL 0000000000000001],
 	replication => 'true');
 ok($stderr =~ /ERROR:  logical decoding requires a database connection/,
 	"Logical decoding fails on non-database connection");
diff --git a/src/test/recovery/t/016_min_consistency.pl b/src/test/recovery/t/016_min_consistency.pl
index 9a3b4866fce..e4ccdd43c2a 100644
--- a/src/test/recovery/t/016_min_consistency.pl
+++ b/src/test/recovery/t/016_min_consistency.pl
@@ -39,7 +39,7 @@ sub find_largest_lsn
 	defined($len) or die "read error on $filename: $!";
 	close($fh);
 
-	return sprintf("%X/%X", $max_hi, $max_lo);
+	return sprintf("%08X%08X", $max_hi, $max_lo);
 }
 
 # Initialize primary node
diff --git a/src/test/recovery/t/038_save_logical_slots_shutdown.pl b/src/test/recovery/t/038_save_logical_slots_shutdown.pl
index a47b2d92303..070814b22da 100644
--- a/src/test/recovery/t/038_save_logical_slots_shutdown.pl
+++ b/src/test/recovery/t/038_save_logical_slots_shutdown.pl
@@ -96,13 +96,13 @@ $node_publisher->restart();
 
 # Wait until the walsender creates decoding context
 $node_publisher->wait_for_log(
-	qr/Streaming transactions committing after ([A-F0-9]+\/[A-F0-9]+), reading WAL from ([A-F0-9]+\/[A-F0-9]+)./,
+	qr/Streaming transactions committing after ([A-F0-9]+), reading WAL from ([A-F0-9]+)./,
 	$offset);
 
 # Extract confirmed_flush from the logfile
 my $log_contents = slurp_file($node_publisher->logfile, $offset);
 $log_contents =~
-  qr/Streaming transactions committing after ([A-F0-9]+\/[A-F0-9]+), reading WAL from ([A-F0-9]+\/[A-F0-9]+)./
+  qr/Streaming transactions committing after ([A-F0-9]+), reading WAL from ([A-F0-9]+)./
   or die "could not get confirmed_flush_lsn";
 
 # Ensure that the slot's confirmed_flush LSN is the same as the
diff --git a/src/test/recovery/t/039_end_of_wal.pl b/src/test/recovery/t/039_end_of_wal.pl
index 47f9bb15e03..a25e4c87545 100644
--- a/src/test/recovery/t/039_end_of_wal.pl
+++ b/src/test/recovery/t/039_end_of_wal.pl
@@ -185,7 +185,7 @@ $node->write_wal($TLI, $end_lsn, $WAL_SEGMENT_SIZE,
 $log_size = -s $node->logfile;
 $node->start;
 ok( $node->log_contains(
-		"record with incorrect prev-link 0/DEADBEEF at .*", $log_size),
+		"record with incorrect prev-link 00000000DEADBEEF at .*", $log_size),
 	"xl_prev bad");
 
 # xl_crc check fails.
@@ -249,7 +249,7 @@ $node->write_wal($TLI, start_of_next_page($end_lsn),
 $log_size = -s $node->logfile;
 $node->start;
 ok( $node->log_contains(
-		"unexpected pageaddr 0/BAAAAAAD in .*, LSN .*,", $log_size),
+		"unexpected pageaddr 00000000BAAAAAAD in .*, LSN .*,", $log_size),
 	"xlp_pageaddr bad");
 
 # Good xl_prev, xlp_magic, xlp_pageaddr, but bogus xlp_info.
@@ -339,7 +339,7 @@ $node->write_wal(
 $log_size = -s $node->logfile;
 $node->start;
 ok( $node->log_contains(
-		"unexpected pageaddr 0/BAAAAAAD in .*, LSN .*,", $log_size),
+		"unexpected pageaddr 00000000BAAAAAAD in .*, LSN .*,", $log_size),
 	"xlp_pageaddr bad (split record header)");
 
 # We'll also discover that xlp_rem_len doesn't add up before any
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
index 072d76ce131..d3942d4eebf 100644
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -3860,21 +3860,21 @@ ERROR:  factorial of a negative number is undefined
 -- Tests for pg_lsn()
 --
 SELECT pg_lsn(23783416::numeric);
-  pg_lsn   
------------
- 0/16AE7F8
+      pg_lsn      
+------------------
+ 00000000016AE7F8
 (1 row)
 
 SELECT pg_lsn(0::numeric);
- pg_lsn 
---------
- 0/0
+      pg_lsn      
+------------------
+ 0000000000000000
 (1 row)
 
 SELECT pg_lsn(18446744073709551615::numeric);
-      pg_lsn       
--------------------
- FFFFFFFF/FFFFFFFF
+      pg_lsn      
+------------------
+ FFFFFFFFFFFFFFFF
 (1 row)
 
 SELECT pg_lsn(-1::numeric);
diff --git a/src/test/regress/expected/pg_lsn.out b/src/test/regress/expected/pg_lsn.out
index b27eec7c015..24aa7518ff1 100644
--- a/src/test/regress/expected/pg_lsn.out
+++ b/src/test/regress/expected/pg_lsn.out
@@ -27,23 +27,23 @@ ERROR:  invalid input syntax for type pg_lsn: "/ABCD"
 LINE 1: INSERT INTO PG_LSN_TBL VALUES ('/ABCD');
                                        ^
 -- Also try it with non-error-throwing API
-SELECT pg_input_is_valid('16AE7F7', 'pg_lsn');
+SELECT pg_input_is_valid('G', 'pg_lsn');
  pg_input_is_valid 
 -------------------
  f
 (1 row)
 
-SELECT * FROM pg_input_error_info('16AE7F7', 'pg_lsn');
-                     message                     | detail | hint | sql_error_code 
--------------------------------------------------+--------+------+----------------
- invalid input syntax for type pg_lsn: "16AE7F7" |        |      | 22P02
+SELECT * FROM pg_input_error_info('ZZZ', 'pg_lsn');
+                   message                   | detail | hint | sql_error_code 
+---------------------------------------------+--------+------+----------------
+ invalid input syntax for type pg_lsn: "ZZZ" |        |      | 22P02
 (1 row)
 
 -- Min/Max aggregation
 SELECT MIN(f1), MAX(f1) FROM PG_LSN_TBL;
- min |        max        
------+-------------------
- 0/0 | FFFFFFFF/FFFFFFFF
+       min        |       max        
+------------------+------------------
+ 0000000000000000 | FFFFFFFFFFFFFFFF
 (1 row)
 
 DROP TABLE PG_LSN_TBL;
@@ -85,49 +85,49 @@ SELECT '0/16AE7F8'::pg_lsn - '0/16AE7F7'::pg_lsn;
 (1 row)
 
 SELECT '0/16AE7F7'::pg_lsn + 16::numeric;
- ?column?  
------------
- 0/16AE807
+     ?column?     
+------------------
+ 00000000016AE807
 (1 row)
 
 SELECT 16::numeric + '0/16AE7F7'::pg_lsn;
- ?column?  
------------
- 0/16AE807
+     ?column?     
+------------------
+ 00000000016AE807
 (1 row)
 
 SELECT '0/16AE7F7'::pg_lsn - 16::numeric;
- ?column?  
------------
- 0/16AE7E7
+     ?column?     
+------------------
+ 00000000016AE7E7
 (1 row)
 
 SELECT 'FFFFFFFF/FFFFFFFE'::pg_lsn + 1::numeric;
-     ?column?      
--------------------
- FFFFFFFF/FFFFFFFF
+     ?column?     
+------------------
+ FFFFFFFFFFFFFFFF
 (1 row)
 
 SELECT 'FFFFFFFF/FFFFFFFE'::pg_lsn + 2::numeric; -- out of range error
 ERROR:  pg_lsn out of range
 SELECT '0/1'::pg_lsn - 1::numeric;
- ?column? 
-----------
- 0/0
+     ?column?     
+------------------
+ 0000000000000000
 (1 row)
 
 SELECT '0/1'::pg_lsn - 2::numeric; -- out of range error
 ERROR:  pg_lsn out of range
 SELECT '0/0'::pg_lsn + ('FFFFFFFF/FFFFFFFF'::pg_lsn - '0/0'::pg_lsn);
-     ?column?      
--------------------
- FFFFFFFF/FFFFFFFF
+     ?column?     
+------------------
+ FFFFFFFFFFFFFFFF
 (1 row)
 
 SELECT 'FFFFFFFF/FFFFFFFF'::pg_lsn - ('FFFFFFFF/FFFFFFFF'::pg_lsn - '0/0'::pg_lsn);
- ?column? 
-----------
- 0/0
+     ?column?     
+------------------
+ 0000000000000000
 (1 row)
 
 SELECT '0/16AE7F7'::pg_lsn + 'NaN'::numeric;
@@ -164,107 +164,107 @@ SELECT DISTINCT (i || '/' || j)::pg_lsn f
        generate_series(1, 5) k
   WHERE i <= 10 AND j > 0 AND j <= 10
   ORDER BY f;
-   f   
--------
- 1/1
- 1/2
- 1/3
- 1/4
- 1/5
- 1/6
- 1/7
- 1/8
- 1/9
- 1/10
- 2/1
- 2/2
- 2/3
- 2/4
- 2/5
- 2/6
- 2/7
- 2/8
- 2/9
- 2/10
- 3/1
- 3/2
- 3/3
- 3/4
- 3/5
- 3/6
- 3/7
- 3/8
- 3/9
- 3/10
- 4/1
- 4/2
- 4/3
- 4/4
- 4/5
- 4/6
- 4/7
- 4/8
- 4/9
- 4/10
- 5/1
- 5/2
- 5/3
- 5/4
- 5/5
- 5/6
- 5/7
- 5/8
- 5/9
- 5/10
- 6/1
- 6/2
- 6/3
- 6/4
- 6/5
- 6/6
- 6/7
- 6/8
- 6/9
- 6/10
- 7/1
- 7/2
- 7/3
- 7/4
- 7/5
- 7/6
- 7/7
- 7/8
- 7/9
- 7/10
- 8/1
- 8/2
- 8/3
- 8/4
- 8/5
- 8/6
- 8/7
- 8/8
- 8/9
- 8/10
- 9/1
- 9/2
- 9/3
- 9/4
- 9/5
- 9/6
- 9/7
- 9/8
- 9/9
- 9/10
- 10/1
- 10/2
- 10/3
- 10/4
- 10/5
- 10/6
- 10/7
- 10/8
- 10/9
- 10/10
+        f         
+------------------
+ 0000000100000001
+ 0000000100000002
+ 0000000100000003
+ 0000000100000004
+ 0000000100000005
+ 0000000100000006
+ 0000000100000007
+ 0000000100000008
+ 0000000100000009
+ 0000000100000010
+ 0000000200000001
+ 0000000200000002
+ 0000000200000003
+ 0000000200000004
+ 0000000200000005
+ 0000000200000006
+ 0000000200000007
+ 0000000200000008
+ 0000000200000009
+ 0000000200000010
+ 0000000300000001
+ 0000000300000002
+ 0000000300000003
+ 0000000300000004
+ 0000000300000005
+ 0000000300000006
+ 0000000300000007
+ 0000000300000008
+ 0000000300000009
+ 0000000300000010
+ 0000000400000001
+ 0000000400000002
+ 0000000400000003
+ 0000000400000004
+ 0000000400000005
+ 0000000400000006
+ 0000000400000007
+ 0000000400000008
+ 0000000400000009
+ 0000000400000010
+ 0000000500000001
+ 0000000500000002
+ 0000000500000003
+ 0000000500000004
+ 0000000500000005
+ 0000000500000006
+ 0000000500000007
+ 0000000500000008
+ 0000000500000009
+ 0000000500000010
+ 0000000600000001
+ 0000000600000002
+ 0000000600000003
+ 0000000600000004
+ 0000000600000005
+ 0000000600000006
+ 0000000600000007
+ 0000000600000008
+ 0000000600000009
+ 0000000600000010
+ 0000000700000001
+ 0000000700000002
+ 0000000700000003
+ 0000000700000004
+ 0000000700000005
+ 0000000700000006
+ 0000000700000007
+ 0000000700000008
+ 0000000700000009
+ 0000000700000010
+ 0000000800000001
+ 0000000800000002
+ 0000000800000003
+ 0000000800000004
+ 0000000800000005
+ 0000000800000006
+ 0000000800000007
+ 0000000800000008
+ 0000000800000009
+ 0000000800000010
+ 0000000900000001
+ 0000000900000002
+ 0000000900000003
+ 0000000900000004
+ 0000000900000005
+ 0000000900000006
+ 0000000900000007
+ 0000000900000008
+ 0000000900000009
+ 0000000900000010
+ 0000001000000001
+ 0000001000000002
+ 0000001000000003
+ 0000001000000004
+ 0000001000000005
+ 0000001000000006
+ 0000001000000007
+ 0000001000000008
+ 0000001000000009
+ 0000001000000010
 (100 rows)
 
diff --git a/src/test/regress/expected/subscription.out b/src/test/regress/expected/subscription.out
index 1443e1d9292..28b82a5386d 100644
--- a/src/test/regress/expected/subscription.out
+++ b/src/test/regress/expected/subscription.out
@@ -116,18 +116,18 @@ CREATE SUBSCRIPTION regress_testsub4 CONNECTION 'dbname=regress_doesnotexist' PU
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+ regress_testsub4
-                                                                                                                 List of subscriptions
-       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
-------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | none   | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                     List of subscriptions
+       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | none   | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub4 SET (origin = any);
 \dRs+ regress_testsub4
-                                                                                                                 List of subscriptions
-       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
-------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                     List of subscriptions
+       Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub4 | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub3;
@@ -145,10 +145,10 @@ ALTER SUBSCRIPTION regress_testsub CONNECTION 'foobar';
 ERROR:  invalid connection string syntax: missing "=" after "foobar" in connection info string
 
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET PUBLICATION testpub2, testpub3 WITH (refresh = false);
@@ -157,10 +157,10 @@ ALTER SUBSCRIPTION regress_testsub SET (slot_name = 'newname');
 ALTER SUBSCRIPTION regress_testsub SET (password_required = false);
 ALTER SUBSCRIPTION regress_testsub SET (run_as_owner = true);
 \dRs+
-                                                                                                                     List of subscriptions
-      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           | Skip LSN 
------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | f                 | t             | f        | off                | dbname=regress_doesnotexist2 | 0/0
+                                                                                                                         List of subscriptions
+      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | f                 | t             | f        | off                | dbname=regress_doesnotexist2 | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (password_required = true);
@@ -176,10 +176,10 @@ ERROR:  unrecognized subscription parameter: "create_slot"
 -- ok
 ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/12345');
 \dRs+
-                                                                                                                     List of subscriptions
-      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           | Skip LSN 
------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist2 | 0/12345
+                                                                                                                         List of subscriptions
+      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist2 | 0000000000012345
 (1 row)
 
 -- ok - with lsn = NONE
@@ -188,10 +188,10 @@ ALTER SUBSCRIPTION regress_testsub SKIP (lsn = NONE);
 ALTER SUBSCRIPTION regress_testsub SKIP (lsn = '0/0');
 ERROR:  invalid WAL location (LSN): 0/0
 \dRs+
-                                                                                                                     List of subscriptions
-      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           | Skip LSN 
------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist2 | 0/0
+                                                                                                                         List of subscriptions
+      Name       |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist2 | 0000000000000000
 (1 row)
 
 BEGIN;
@@ -223,10 +223,10 @@ ALTER SUBSCRIPTION regress_testsub_foo SET (synchronous_commit = foobar);
 ERROR:  invalid value for parameter "synchronous_commit": "foobar"
 HINT:  Available values: local, remote_write, remote_apply, on, off.
 \dRs+
-                                                                                                                       List of subscriptions
-        Name         |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           | Skip LSN 
----------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+----------
- regress_testsub_foo | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | t                 | f             | f        | local              | dbname=regress_doesnotexist2 | 0/0
+                                                                                                                           List of subscriptions
+        Name         |           Owner           | Enabled |     Publication     | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |           Conninfo           |     Skip LSN     
+---------------------+---------------------------+---------+---------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+------------------------------+------------------
+ regress_testsub_foo | regress_subscription_user | f       | {testpub2,testpub3} | f      | parallel  | d                | f                | any    | t                 | f             | f        | local              | dbname=regress_doesnotexist2 | 0000000000000000
 (1 row)
 
 -- rename back to keep the rest simple
@@ -255,19 +255,19 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | t      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | t      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (binary = false);
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub;
@@ -279,27 +279,27 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (streaming = parallel);
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (streaming = false);
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 -- fail - publication already exists
@@ -314,10 +314,10 @@ ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub1, testpub2 WITH (refr
 ALTER SUBSCRIPTION regress_testsub ADD PUBLICATION testpub1, testpub2 WITH (refresh = false);
 ERROR:  publication "testpub1" is already in subscription "regress_testsub"
 \dRs+
-                                                                                                                        List of subscriptions
-      Name       |           Owner           | Enabled |         Publication         | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub,testpub1,testpub2} | f      | off       | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                            List of subscriptions
+      Name       |           Owner           | Enabled |         Publication         | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-----------------------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub,testpub1,testpub2} | f      | off       | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 -- fail - publication used more than once
@@ -332,10 +332,10 @@ ERROR:  publication "testpub3" is not in subscription "regress_testsub"
 -- ok - delete publications
 ALTER SUBSCRIPTION regress_testsub DROP PUBLICATION testpub1, testpub2 WITH (refresh = false);
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | off       | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 DROP SUBSCRIPTION regress_testsub;
@@ -371,19 +371,19 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | p                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | p                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 -- we can alter streaming when two_phase enabled
 ALTER SUBSCRIPTION regress_testsub SET (streaming = true);
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -393,10 +393,10 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | on        | p                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
@@ -409,18 +409,18 @@ CREATE SUBSCRIPTION regress_testsub CONNECTION 'dbname=regress_doesnotexist' PUB
 WARNING:  subscription was created, but is not connected
 HINT:  To initiate replication, you must manually create the replication slot, enable the subscription, and refresh the subscription.
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | f                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (disable_on_error = true);
 \dRs+
-                                                                                                                List of subscriptions
-      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           | Skip LSN 
------------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+----------
- regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | t                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0/0
+                                                                                                                    List of subscriptions
+      Name       |           Owner           | Enabled | Publication | Binary | Streaming | Two-phase commit | Disable on error | Origin | Password required | Run as owner? | Failover | Synchronous commit |          Conninfo           |     Skip LSN     
+-----------------+---------------------------+---------+-------------+--------+-----------+------------------+------------------+--------+-------------------+---------------+----------+--------------------+-----------------------------+------------------
+ regress_testsub | regress_subscription_user | f       | {testpub}   | f      | parallel  | d                | t                | any    | t                 | f             | f        | off                | dbname=regress_doesnotexist | 0000000000000000
 (1 row)
 
 ALTER SUBSCRIPTION regress_testsub SET (slot_name = NONE);
diff --git a/src/test/regress/sql/pg_lsn.sql b/src/test/regress/sql/pg_lsn.sql
index 98c869df159..56e838e2764 100644
--- a/src/test/regress/sql/pg_lsn.sql
+++ b/src/test/regress/sql/pg_lsn.sql
@@ -16,8 +16,8 @@ INSERT INTO PG_LSN_TBL VALUES ('ABCD/');
 INSERT INTO PG_LSN_TBL VALUES ('/ABCD');
 
 -- Also try it with non-error-throwing API
-SELECT pg_input_is_valid('16AE7F7', 'pg_lsn');
-SELECT * FROM pg_input_error_info('16AE7F7', 'pg_lsn');
+SELECT pg_input_is_valid('G', 'pg_lsn');
+SELECT * FROM pg_input_error_info('ZZZ', 'pg_lsn');
 
 -- Min/Max aggregation
 SELECT MIN(f1), MAX(f1) FROM PG_LSN_TBL;
diff --git a/src/test/subscription/t/029_on_error.pl b/src/test/subscription/t/029_on_error.pl
index 243662e1240..7225fbbeeff 100644
--- a/src/test/subscription/t/029_on_error.pl
+++ b/src/test/subscription/t/029_on_error.pl
@@ -30,7 +30,7 @@ sub test_skip_lsn
 	# ERROR with its CONTEXT when retrieving this information.
 	my $contents = slurp_file($node_subscriber->logfile, $offset);
 	$contents =~
-	  qr/conflict detected on relation "public.tbl".*\n.*DETAIL:.* Key already exists in unique index "tbl_pkey", modified by .*origin.* transaction \d+ at .*\n.*Key \(i\)=\(\d+\); existing local tuple .*; remote tuple .*\n.*CONTEXT:.* for replication target relation "public.tbl" in transaction \d+, finished at ([[:xdigit:]]+\/[[:xdigit:]]+)/m
+	  qr/conflict detected on relation "public.tbl".*\n.*DETAIL:.* Key already exists in unique index "tbl_pkey", modified by .*origin.* transaction \d+ at .*\n.*Key \(i\)=\(\d+\); existing local tuple .*; remote tuple .*\n.*CONTEXT:.* for replication target relation "public.tbl" in transaction \d+, finished at ([[:xdigit:]]+)/m
 	  or die "could not get error-LSN";
 	my $lsn = $1;
 
@@ -43,7 +43,7 @@ sub test_skip_lsn
 
 	# Wait for the failed transaction to be skipped
 	$node_subscriber->poll_query_until('postgres',
-		"SELECT subskiplsn = '0/0' FROM pg_subscription WHERE subname = 'sub'"
+		"SELECT subskiplsn = '0000000000000000' FROM pg_subscription WHERE subname = 'sub'"
 	);
 
 	# Check the log to ensure that the transaction is skipped, and advance the
-- 
2.48.1

