# LSN to WAL file

Which WAL segment file holds an LSN, and how many bytes into it.

> Canonical URL: https://sudohulk.com/tools/lsn
> Agrees with: `pg_walfile_name_offset()`, PostgreSQL 18.3, and is tested against its output
> WebMCP tool: `lsn_to_wal_file`

---

Inputs: `lsn` (default 16/B374D848), `timeline` (default 1), `segment_mb` (default 16).

For example, LSN 16/B374D848, timeline 1, 16 MB segments: WAL file 0000000100000016000000B3, offset 7657544.

## How it is worked out

```text
segment = lsn / segment_size
offset  = lsn % segment_size
file    = %08X of timeline
        + %08X of segment / (2^32 / segment_size)
        + %08X of segment % (2^32 / segment_size)
```

An LSN is a byte position in the WAL, 64 bits wide, printed as its high and low 32 bits in hex: `16/B374D848` is 0x16B374D848.

With 16 MB segments the file name is the timeline, then the high 32 bits, then the next 8: `16/B374D848` is in `0000000100000016000000B3`.

An LSN exactly on a boundary, such as `0/1000000`, names the file that starts there, at offset 0.

The server uses the timeline it is inserting on and the `wal_segment_size` initdb chose, 16 MB unless `--wal-segsize` said otherwise. On a standby it refuses, with `recovery is in progress`.

The same answer from a server:

```sql
SELECT * FROM pg_walfile_name_offset('16/B374D848');
```
