<!--
doc/src/sgml/ref/wait_for.sgml
PostgreSQL documentation
-->

<refentry id="sql-wait-for">
 <indexterm zone="sql-wait-for">
  <primary>WAIT FOR</primary>
 </indexterm>

 <refmeta>
  <refentrytitle>WAIT FOR</refentrytitle>
  <manvolnum>7</manvolnum>
  <refmiscinfo>SQL - Language Statements</refmiscinfo>
 </refmeta>

 <refnamediv>
  <refname>WAIT FOR</refname>
  <refpurpose>wait for WAL to reach a target <acronym>LSN</acronym></refpurpose>
 </refnamediv>

 <refsynopsisdiv>
<synopsis>
WAIT FOR LSN '<replaceable class="parameter">lsn</replaceable>'
    [ WITH ( <replaceable class="parameter">option</replaceable> [, ...] ) ]

<phrase>where <replaceable class="parameter">option</replaceable> can be:</phrase>

    MODE '<replaceable class="parameter">mode</replaceable>'
    TIMEOUT '<replaceable class="parameter">timeout</replaceable>'
    NO_THROW

<phrase>and <replaceable class="parameter">mode</replaceable> can be:</phrase>

    standby_replay | standby_write | standby_flush | primary_flush
</synopsis>
 </refsynopsisdiv>

 <refsect1>
  <title>Description</title>

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

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

  <para>
   The possible return values are <literal>success</literal>,
   <literal>timeout</literal>, and <literal>not in recovery</literal>.
  </para>
 </refsect1>

 <refsect1>
  <title>Parameters</title>

  <variablelist>
   <varlistentry>
    <term><replaceable class="parameter">lsn</replaceable></term>
    <listitem>
     <para>
      Specifies the target <acronym>LSN</acronym> to wait for.
     </para>
    </listitem>
   </varlistentry>

   <varlistentry>
    <term><literal>WITH ( <replaceable class="parameter">option</replaceable> [, ...] )</literal></term>
    <listitem>
     <para>
      This clause specifies optional parameters for the wait operation.
      The following parameters are supported:

      <variablelist>
       <varlistentry>
        <term><literal>MODE</literal> '<replaceable class="parameter">mode</replaceable>'</term>
        <listitem>
         <para>
          Specifies the type of LSN processing to wait for. If not specified,
          the default is <literal>standby_replay</literal>. The valid modes are:
         </para>
         <itemizedlist>
          <listitem>
           <para>
            <literal>standby_replay</literal>: Wait for the LSN to be replayed
            (applied to the database) on a standby server. After successful
            completion, <function>pg_last_wal_replay_lsn()</function> will
            return a value greater than or equal to the target LSN. This mode
            can only be used during recovery.
           </para>
          </listitem>
          <listitem>
           <para>
            <literal>standby_write</literal>: Wait for the WAL containing the
            LSN to be received from the primary and written to disk on a
            standby server, but not yet flushed. This is faster than
            <literal>standby_flush</literal> but provides weaker durability
            guarantees since the data may still be in operating system
            buffers. After successful completion, the
            <structfield>written_lsn</structfield> column in
            <link linkend="monitoring-pg-stat-wal-receiver-view">
            <structname>pg_stat_wal_receiver</structname></link> will show
            a value greater than or equal to the target LSN. This mode can
            only be used during recovery.
           </para>
          </listitem>
          <listitem>
           <para>
            <literal>standby_flush</literal>: Wait for the WAL containing the
            LSN to be received from the primary and flushed to disk on a
            standby server. This provides a durability guarantee without
            waiting for the WAL to be applied. After successful completion,
            <function>pg_last_wal_receive_lsn()</function> will return a
            value greater than or equal to the target LSN. This value is
            also available as the <structfield>flushed_lsn</structfield>
            column in <link linkend="monitoring-pg-stat-wal-receiver-view">
            <structname>pg_stat_wal_receiver</structname></link>. This mode
            can only be used during recovery.
           </para>
          </listitem>
          <listitem>
           <para>
            <literal>primary_flush</literal>: Wait for the WAL containing the
            LSN to be flushed to disk on a primary server. After successful
            completion, <function>pg_current_wal_flush_lsn()</function> 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).
           </para>
          </listitem>
         </itemizedlist>
        </listitem>
       </varlistentry>

       <varlistentry>
        <term><literal>TIMEOUT</literal> '<replaceable class="parameter">timeout</replaceable>'</term>
        <listitem>
         <para>
          When specified and <parameter>timeout</parameter> is greater than zero,
          the command waits until <parameter>lsn</parameter> is reached or
          the specified <parameter>timeout</parameter> has elapsed.
         </para>
         <para>
          The <parameter>timeout</parameter> 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 <xref linkend="config-setting-names-values"/>).
         </para>
        </listitem>
       </varlistentry>

       <varlistentry>
        <term><literal>NO_THROW</literal></term>
        <listitem>
         <para>
          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.
         </para>
        </listitem>
       </varlistentry>
      </variablelist>
     </para>
    </listitem>
   </varlistentry>
  </variablelist>
 </refsect1>

 <refsect1>
  <title>Outputs</title>

  <variablelist>
   <varlistentry>
    <term><literal>success</literal></term>
    <listitem>
     <para>
      This return value denotes that we have successfully reached
      the target <parameter>lsn</parameter>.
     </para>
    </listitem>
   </varlistentry>

   <varlistentry>
    <term><literal>timeout</literal></term>
    <listitem>
     <para>
      This return value denotes that the timeout happened before reaching
      the target <parameter>lsn</parameter>.
     </para>
    </listitem>
   </varlistentry>

   <varlistentry>
    <term><literal>not in recovery</literal></term>
    <listitem>
     <para>
      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 <parameter>lsn</parameter>.
      In the promotion case, this status indicates a timeline change occurred,
      and the application should re-evaluate whether the target LSN is still
      relevant.
     </para>
    </listitem>
   </varlistentry>
  </variablelist>
 </refsect1>

 <refsect1>
  <title>Notes</title>

  <para>
   <command>WAIT FOR</command> waits until the specified
   <parameter>lsn</parameter> is reached according to the specified
   <parameter>mode</parameter>. The <literal>standby_replay</literal> 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
   <literal>standby_flush</literal> mode waits for the WAL to be flushed
   to durable storage on the replica, providing a durability guarantee
   without waiting for replay. The <literal>standby_write</literal> mode
   waits for the WAL to be written to the operating system, which is
   faster than flush but provides weaker durability guarantees. The
   <literal>primary_flush</literal> mode waits for WAL to be flushed on
   a primary server. In all cases, the <acronym>LSN</acronym> of the last
   modification should be stored on the client application side or the
   connection pooler side.
  </para>

  <para>
   The standby modes (<literal>standby_replay</literal>,
   <literal>standby_write</literal>, <literal>standby_flush</literal>)
   can only be used during recovery, and <literal>primary_flush</literal>
   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
   <literal>not in recovery</literal> (or throw an error if
   <literal>NO_THROW</literal> is not specified). Promotion creates a new
   timeline, and the LSN being waited for may refer to WAL from the old
   timeline.
  </para>

</refsect1>

 <refsect1>
  <title>Examples</title>

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

   <programlisting>
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)
</programlisting>

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

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

  <para>
   Wait for flush (data durable on replica):

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

  <para>
   Wait for write with timeout:

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

  <para>
   Wait for flush on primary:

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

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

<programlisting>
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
</programlisting>
  </para>

  <para>
   The same example uses <command>WAIT FOR</command> with
   <parameter>NO_THROW</parameter> option:

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