October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run ScanOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk6 min

PostgreSQL 19 WAIT FOR LSN from PHP: Read Your Writes on a Replica—and Four Pitfalls

To read a committed PHP write from an asynchronous PostgreSQL replica, wait for a WAL position that covers its commit record, then read only if standby replay succeeds. Learn the PDO caveats and four failure modes.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To make a PostgreSQL asynchronous replica show a write made moments earlier by PHP, capture a WAL location that covers the committed write on the primary, send it to the replica, run WAIT FOR LSN in standby_replay mode, and read only if the wait succeeds. This provides read-your-writes consistency for that request; it does not eliminate replication lag or guarantee that every replica read is current.

What WAIT FOR LSN guarantees

PostgreSQL 19’s WAIT FOR LSN can pause a standby until it reaches a specified WAL position. For a query that must see a recent write, use the default standby_replay mode: it waits until the WAL at the target position has been replayed, or applied, on the standby. On success, pg_last_wal_replay_lsn() is at least the requested LSN.

As an Amazon Associate I earn from qualifying purchases.

The target matters as much as the wait. PostgreSQL’s documentation says the target must be at or after the end of the relevant transaction’s COMMIT record on the primary. Otherwise, the standby can successfully reach the requested position without having applied the write you care about. See the PostgreSQL 19 WAIT documentation for the command’s semantics and constraints.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Choose the mode for the result you need

Mode Waits for What it means for reads
standby_replay WAL replayed and applied on the standby Use this for read-your-writes query visibility.
standby_flush WAL flushed to durable storage on the standby Durability is not the same as application; a query may not yet see the changes.
standby_write WAL written to the standby’s operating-system buffers Weaker still; it does not promise the changes are query-visible.
primary_flush WAL flushed on a primary Not a standby visibility wait.

Standby modes require a server in recovery; primary_flush requires a primary. PostgreSQL’s official read-your-writes pattern is to commit on the primary, obtain a suitable LSN, pass it to the client or connection-pooler layer, wait on the standby, and then read. The documentation’s example uses pg_current_wal_insert_lsn() to account for synchronous_commit possibly being off.

A practical PHP request flow

After the write transaction commits on the primary, capture and carry the LSN as text. For synchronous commit, the PHP article discussed below uses pg_current_wal_flush_lsn(); when synchronous_commit is off, it recommends an insert LSN because the flush position may still precede the commit record. Select a position that covers the transaction’s commit record, then wait on the replica before issuing the read.

-- Primary: after the write transaction has committed (synchronous commit on)
SELECT pg_current_wal_flush_lsn();

-- Replica: outside a transaction, before the read
WAIT FOR LSN '0/0306EE20' WITH (MODE 'standby_replay', TIMEOUT '50ms', NO_THROW);

-- Only if WAIT reports success:
SELECT ...;

The LSN above is illustrative syntax, not a value to reuse. In PHP, route to the replica only when the command returns success; otherwise use an explicit fallback policy such as reading from the primary, retrying within a bounded budget, or returning a consistency delay. A successful wait proves the requested LSN was reached, not that an incorrectly chosen LSN covered the write.

Four pitfalls to handle

1. Native PDO placeholders may not work in WAIT

Szj’s PHP article reports that native PDO prepared statements reject a parameter placeholder in this utility statement. PostgreSQL documents the SQL syntax, but does not specify a PHP driver’s binding behavior, so treat this as a PDO-specific report rather than a universal driver rule. The article’s workaround validates the LSN as uppercase hexadecimal digits, a slash, then hexadecimal digits, and only then interpolates it into the SQL. Never interpolate arbitrary input. The article also mentions emulated prepares, but its shown sample uses validation.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

2. WAIT must run before a transaction snapshot or held locks

WAIT must be a top-level command: it cannot run inside a function, procedure, or DO block. It cannot run while the session holds a snapshot, and it may be rejected if the session holds a lock while the requested position has not yet been reached. Run it outside a transaction block, or as the transaction’s first statement, before statements that take locks. A lock can otherwise hold up replay while the waiting session itself blocks on replay, a cycle ordinary deadlock detection does not break. Calling it before opening a transaction is the safer PHP request pattern.

A test may not reveal this restriction if the replica has already reached the target and the wait returns immediately; it becomes relevant when a wait is actually needed.

3. An insert-LSN page-boundary timeout was reported, but its cause is unproven

In an idle test, Szj reports 5 timeouts among 5,000 waits using an insert LSN. The observed target positions ended at offset 0x18 (24 bytes). The author hypothesizes that a position after a WAL page header may leave the standby waiting for future WAL, but labels this as an inference. PostgreSQL’s documentation supports use of an insert LSN in its pattern; it does not confirm this proposed page-boundary mechanism. Use a finite timeout and inspect the result rather than assuming any wait will complete promptly.

4. With synchronous_commit off, a flush LSN may be too early

Szj reports that in an experiment with synchronous_commit = off, waiting for the flush LSN returned success quickly but was followed by stale reads in all 300 attempts. Waiting for the insert LSN produced correct reads in that sample, with a reported median wait of 201 milliseconds and 8 timeouts among 300 attempts. These are the author’s test results, not a PostgreSQL guarantee or production forecast. The underlying issue is target selection: a wait can succeed for its LSN even when that position does not include the write’s commit record.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Bound the wait and handle its outcomes

A timeout of zero is the default and means wait indefinitely. Set a positive timeout to bound request latency. NO_THROW is useful when timeout and role-state outcomes are expected: inspect the returned status and proceed to the replica only for success. It does not set a timeout or suppress malformed-input, invalid-mode, or invalid-state errors. A promoted server can return not in recovery; promotion creates a new timeline, so reassess whether the old target describes the history you intend to read.

  1. Commit the write on the primary.
  2. Capture an LSN at or beyond the transaction’s commit record and pass it to the PHP request or routing layer.
  3. On the replica, execute WAIT FOR LSN before opening a transaction or taking locks, with a positive timeout and (if desired) NO_THROW.
  4. Check the result. Read from the replica only on success; otherwise follow the application’s defined fallback or retry policy.

What the reported measurements do—and do not—show

Szj’s September 30, 2026 DEV Community article reports a test using PostgreSQL 19 Beta 4, PHP 8.5.10, and PDO. The author says the setup ran the primary, standby, PHP, and pgbench together on one vCPU, cautions that a real network adds a round trip, and recommends treating ratios rather than microseconds as the point. These figures describe that author’s setup; they are not portable latency expectations or independently verified results.

Test reported by Szj Reported result
Immediate reads on an idle asynchronous replica 5,000 stale reads out of 5,000 attempts
Immediate reads under the author’s write load 1,496 stale reads out of 1,500 attempts
Reads after adding WAIT, idle test 0 stale reads in 5,000 attempts; 315 microseconds median reported wait
Reads after adding WAIT, write-load test 0 stale reads in 1,500 attempts; 1.2 milliseconds median reported wait
Idle waits with insert LSN 5 timeouts in 5,000 attempts
Waits with flush LSN and synchronous commit on 0 timeouts in 5,000 reported attempts
Asynchronous commit experiment: flush-LSN waits 300 stale reads in 300 attempts
Asynchronous commit experiment: insert-LSN waits Correct reads in the reported sample; 201 milliseconds median wait and 8 timeouts in 300 attempts

The PostgreSQL 19 documentation page currently marks that version as unsupported. The article’s measurements used Beta 4 and explicitly cautions that details could change before final release; verify the behavior against the PostgreSQL release and PHP driver you deploy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.