WAIT FOR(7)

NAME
WAIT_FOR - wait for WAL to reach a target LSN

SYNOPSIS

WAIT FOR LSN 'lsn'
    [ WITH ( option [, ...] ) ]
where option can be:
    MODE 'mode'
    TIMEOUT 'timeout'
    NO_THROW
and mode can be:
    standby_replay | standby_write | standby_flush | primary_flush

DESCRIPTION

Waits until the specified lsn is reached according to the specified mode, which determines whether to wait for WAL to be written, flushed, or replayed. If no timeout is specified or it is set to zero, this command waits indefinitely for the lsn.

On timeout, an error is emitted unless NO_THROW is specified in the WITH clause. For standby modes (standby_replay, standby_write, standby_flush), an error is also emitted if the server is promoted before the lsn is reached. If NO_THROW is specified, the command returns a status string instead of throwing errors.

The possible return values are success, timeout, and not in recovery.

PARAMETERS

lsn
    Specifies the target LSN to wait for.

WITH ( option [, ...] )
    This clause specifies optional parameters for the wait operation. The following parameters are supported:

    MODE 'mode'
        Specifies the type of LSN processing to wait for. If not specified, the default is standby_replay. The valid modes are:

            • standby_replay: Wait for the LSN to be replayed (applied to the database) on a standby server. After successful completion, pg_last_wal_replay_lsn() will return a value greater than or equal to the target LSN. This mode can only be used during recovery.

            • standby_write: Wait for the WAL containing the LSN to be written to disk on a standby server, but not yet necessarily flushed. This is faster than standby_flush but provides weaker durability guarantees since the data may still be in operating system buffers. This is satisfied by WAL already present on the standby from a base backup, archive restore, or prior streaming, as well as WAL newly received from the primary. This mode can only be used during recovery.

            • standby_flush: Wait for the WAL containing the LSN to be flushed to disk on a standby server. This provides a durability guarantee without waiting for the WAL to be applied. This is satisfied by WAL already present on the standby from a base backup, archive restore, or prior streaming, as well as WAL newly received from the primary. This mode can only be used during recovery.

            • primary_flush: Wait for the WAL containing the LSN to be flushed to disk on a primary server. After successful completion, pg_current_wal_flush_lsn() will return a value greater than or equal to the target LSN. This mode can only be used on a primary server (not during recovery).

    TIMEOUT 'timeout'
        When specified and timeout is greater than zero, the command waits until lsn is reached or the specified timeout has elapsed.

        The timeout might be given as integer number of milliseconds. Also it might be given as string literal with integer number of milliseconds or a number with unit (see Section 19.1.1).

    NO_THROW
        Specify to not throw an error in the case of timeout or running on the primary. In this case the result status can be get from the return value.

OUTPUTS

success
    This return value denotes that we have successfully reached the target lsn.

timeout
    This return value denotes that the timeout happened before reaching the target lsn.

not in recovery
    This return value denotes that the database server is not in a recovery state. This might mean either the database server was not in recovery at the moment of receiving the command (i.e., executed on a primary), or it was promoted before reaching the target lsn. In the promotion case, this status indicates a timeline change occurred, and the application should re-evaluate whether the target LSN is still relevant.

NOTES

WAIT FOR must be executed as a top-level command. It cannot be executed from a function, procedure, or DO block. It also requires that no active or registered snapshot be held, and therefore cannot be used in contexts where such a snapshot must remain active, including transactions running at isolation levels higher than READ COMMITTED.

WAIT FOR waits until the specified lsn is reached according to the specified mode. The standby_replay mode waits for the LSN to be replayed (applied to the database), which is useful to achieve read-your-writes consistency while using an async replica for reads and the primary for writes. The standby_flush mode waits for the WAL to be flushed to durable storage on the replica, or to have already been replayed from WAL present on the standby. The standby_write mode waits for the WAL to be written to the operating system, or to have already been replayed, which is faster than flush for newly received WAL but provides weaker durability guarantees. The primary_flush mode waits for WAL to be flushed on a primary server. In all cases, the LSN of the last modification should be stored on the client application side or the connection pooler side.

The standby modes (standby_replay, standby_write, standby_flush) can only be used during recovery, and primary_flush can only be used on a primary server. Using the wrong mode for the current server state will result in an error. If a standby is promoted while waiting with a standby mode, the command will return not in recovery (or throw an error if NO_THROW is not specified). Promotion creates a new timeline, and the LSN being waited for may refer to WAL from the old timeline.

WAIT FOR compares only the numeric LSN; it has no notion of which timeline a WAL record belongs to. This matters when a standby continues recovery across an upstream timeline switch — for example, a cascading standby whose upstream gets promoted. In that case WAIT FOR will return success as soon as the position used by the selected wait mode reaches or passes the numeric LSN, regardless of which timeline that LSN belongs to. Applications that need to confirm the target refers to the expected timeline must validate the timeline themselves.

On a standby server, WAIT FOR sessions may be interrupted by recovery conflicts. Some recovery conflicts are unavoidable: for example, replaying a tablespace drop resolves conflicts by terminating all backends, regardless of what they are doing. Applications using WAIT FOR on a standby should be prepared to handle such interruptions, for example by retrying the command or falling back to an alternative mechanism.

EXAMPLES

You can use WAIT FOR command to wait for the pg_lsn value. For example, an application could update the movie table and get the lsn after changes just made. This example uses pg_current_wal_insert_lsn on primary server to get the lsn given that synchronous_commit could be set to off.

    postgres=# UPDATE movie SET genre = 'Dramatic' WHERE genre = 'Drama';
    UPDATE 100
    postgres=# SELECT pg_current_wal_insert_lsn();
     pg_current_wal_insert_lsn
    ---------------------------
     0/306EE20
    (1 row)

Then an application could run WAIT FOR with the lsn obtained from primary. After that the changes made on primary should be guaranteed to be visible on replica.

    postgres=# WAIT FOR LSN '0/306EE20';
     status
    ---------
     success
    (1 row)
    postgres=# SELECT * FROM movie WHERE genre = 'Drama';
     genre
    -------
    (0 rows)

Wait for flush (data durable on replica):

    postgres=# WAIT FOR LSN '0/306EE20' WITH (MODE 'standby_flush');
     status
    ---------
     success
    (1 row)

Wait for write with timeout:

    postgres=# WAIT FOR LSN '0/306EE20' WITH (MODE 'standby_write', TIMEOUT '100ms', NO_THROW);
     status
    ---------
     success
    (1 row)

Wait for flush on primary:

    postgres=# WAIT FOR LSN '0/306EE20' WITH (MODE 'primary_flush');
     status
    ---------
     success
    (1 row)

If the target LSN is not reached before the timeout, an error is thrown:

    postgres=# WAIT FOR LSN '0/306EE20' WITH (TIMEOUT '0.1s');
    ERROR:  timed out while waiting for target LSN 0/306EE20 to be replayed; current replay LSN 0/306EA60

The same example uses WAIT FOR with NO_THROW option:

    postgres=# WAIT FOR LSN '0/306EE20' WITH (TIMEOUT '100ms', NO_THROW);
     status
    ---------
     timeout
    (1 row)