diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 8f62e884b1..e6e4f346f1 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1460,20 +1460,21 @@ include_dir 'conf.d'
        <para>
         The command must print the passphrase to the standard output
         and exit with code 0.  It can prompt from the terminal if
-        <option>--authprompt</option> is used.  In the parameter value,
-        <literal>%R</literal> represents the file descriptor number opened
-        to the terminal that started the server.  A file descriptor is only
-        available if enabled at server start.  If <literal>%R</literal>
-        is used and no file descriptor is available, the server will not
-        start.  Value <literal>%p</literal> is replaced by a pre-defined
-        prompt string.  (Write <literal>%%</literal> for a literal
-        <literal>%</literal>.)  Note that the prompt string will probably
-        contain whitespace, so be sure to quote its use adequately.
-        Newlines are stripped from the end of the output if present.
+        <option>--authprompt</option> is used.  In the parameter
+        value, <literal>%R</literal> is replaced by a file descriptor
+        number opened to the terminal that started the server.  A file
+        descriptor is only available if enabled at server start via
+        <option>-R</option>.  If <literal>%R</literal> is specified and
+        no file descriptor is available, the server will not start.  Value
+        <literal>%p</literal> is replaced by a pre-defined prompt string.
+        (Write <literal>%%</literal> for a literal <literal>%</literal>.)
+        Note that the prompt string will probably contain whitespace,
+        so be sure to quote its use adequately.  Newlines are stripped
+        from the end of the output if present.
        </para>
 
        <para>
-        Sample script can be found in
+        Sample scripts can be found in
         <filename>$SHAREDIR/auth_commands</filename>,
         where <literal>$SHAREDIR</literal> means the
         <productname>PostgreSQL</productname> installation's shared-data
@@ -7874,15 +7875,16 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         server start.
        </para>
        <para>
-        The command must print the cluster key to the standard output as
-        64 hexadecimal characters, and exit with code 0.  The command
-        can prompt for the passphrase or PIN from the terminal if
-        <option>--authprompt</option> is used.  In the parameter value,
-        <literal>%R</literal> represents the file descriptor number opened
-        to the terminal that started the server.  A file descriptor is only
-        available if enabled at server start.  If <literal>%R</literal>
-        is used and no file descriptor is available, the server will not
-        start.  Value <literal>%p</literal> is replaced by a pre-defined
+        The command must print the cluster key to the standard
+        output as 64 hexadecimal characters, and exit with code 0.
+        The command can prompt for the passphrase or PIN from the
+        terminal if <option>--authprompt</option> is used.  In the
+        parameter value, <literal>%R</literal> is replaced by a file
+        descriptor number opened to the terminal that started the server.
+        A file descriptor is only available if enabled at server start
+        via <option>-R</option>.  If <literal>%R</literal> is specified
+        and no file descriptor is available, the server will not start.
+        Value <literal>%p</literal> is replaced by a pre-defined
         prompt string.  Value <literal>%d</literal> is replaced by the
         directory containing the keys;  this is useful if the command
         must create files with the keys, e.g., to store a cluster-level
diff --git a/doc/src/sgml/database-encryption.sgml b/doc/src/sgml/database-encryption.sgml
index cb62f1d975..8eece94322 100644
--- a/doc/src/sgml/database-encryption.sgml
+++ b/doc/src/sgml/database-encryption.sgml
@@ -24,8 +24,8 @@
   Key one is used to encrypt write-ahead log (WAL) files.  Two different
   keys are used so that primary and standby servers can use different zero
   (heap/index/temp) keys, but the same one (WAL) key, so that these keys
-  can eventually be rotated by switching the primary to the standby
-  and then changing the WAL key.
+  can (in a future release) be rotated by switching the primary to the
+  standby and then changing the WAL key.
  </para>
 
  <para>
@@ -36,7 +36,10 @@
   each time the server is started.  This key prevents anyone with access
   to the database directories from decrypting the data because they do
   not know the second-level key which encrypted the first-level keys
-  which encrypted the database cluster files.
+  which encrypted the database cluster files.  This key can be easily
+  changed via <command>pg_alterckey</command> without requiring any
+  changes to the the data files or <command>WAL</command> files, which
+  are encrypted with the data keys.
  </para>
 
  <sect1 id="encryption-file-encryption">
@@ -54,7 +57,7 @@
    <filename>postgresql.conf</filename> must match for the database
    cluster to start. Note that the cluster key command
    passed to <command>initdb</command> must return a key of
-   64 hexadecimal characters. For example.
+   64 hexadecimal characters. For example:
 <programlisting>
 initdb -D dbname --cluster-key-command='ckey_passphrase.sh'
 </programlisting>
@@ -71,7 +74,8 @@ initdb -D dbname --cluster-key-command='ckey_passphrase.sh'
    the key encryption key (KEK) supplied by the cluster key command before
    being stored in the database directory.  The key or passphrase that
    derives the key must be supplied from the terminal or stored in a
-   trusted key store, such as key vault software, hardware security module.
+   trusted key store, such as key vault software or a hardware security
+   module.
   </para>
 
   <para>
@@ -81,17 +85,22 @@ initdb -D dbname --cluster-key-command='ckey_passphrase.sh'
    <varname>cluster_key_command</varname> command will be executed
    and the cluster key retrieved.  The data encryption keys in the
    <filename>pg_cryptokeys</filename> directory will then be decrypted
-   using the supplied key and integrity-checked to ensure it
-   matches the initdb-supplied key.  If this check fails, the
-   server will refuse to start.
+   using the supplied key and integrity-checked to ensure it matches the
+   initdb-supplied key.  (If this check fails, the server will refuse
+   to start.)  The cluster encryption key will then be removed from
+   system memory.  The decrypted data encryption keys will remain in
+   shared memory until the server is stopped.
   </para>
 
   <para>
-   The data encryption keys are randomly generated and can be 128, 192,
-   or 256-bits in length.  They are encrypted by the key encryption key
-   (KEK) using Advanced Encryption Standard (<acronym>AES256</acronym>)
-   encryption in Key Wrap Padded Mode, which also provides KEK
-   authentication.
+   The data encryption keys are randomly generated and can be
+   128, 192, or 256-bits in length.  They are encrypted by the
+   key encryption key (KEK) using Advanced Encryption Standard
+   (<acronym>AES256</acronym>) encryption in Key Wrap Padded
+   Mode, which also provides KEK authentication;  see <ulink
+   url="https://tools.ietf.org/html/rfc5649">RFC 5649</ulink>. While
+   128-bit encryption is sufficient for most sites, 256-bit encryption
+   is thought to be more immune to future quantum cryptographic attacks.
   </para>
  </sect1>
 </chapter>
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 4e9504e11b..92bad3150c 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -189,7 +189,6 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY values             SYSTEM "values.sgml">
 
 <!-- applications and utilities -->
-<!ENTITY pgalterckey        SYSTEM "pg_alterckey.sgml">
 <!ENTITY clusterdb          SYSTEM "clusterdb.sgml">
 <!ENTITY createdb           SYSTEM "createdb.sgml">
 <!ENTITY createuser         SYSTEM "createuser.sgml">
@@ -197,6 +196,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY dropuser           SYSTEM "dropuser.sgml">
 <!ENTITY ecpgRef            SYSTEM "ecpg-ref.sgml">
 <!ENTITY initdb             SYSTEM "initdb.sgml">
+<!ENTITY pgalterckey        SYSTEM "pg_alterckey.sgml">
 <!ENTITY pgarchivecleanup   SYSTEM "pgarchivecleanup.sgml">
 <!ENTITY pgBasebackup       SYSTEM "pg_basebackup.sgml">
 <!ENTITY pgbench            SYSTEM "pgbench.sgml">
diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml
index 25342d1c19..4596489146 100644
--- a/doc/src/sgml/ref/initdb.sgml
+++ b/doc/src/sgml/ref/initdb.sgml
@@ -242,7 +242,7 @@ PostgreSQL documentation
       <listitem>
        <para>
         Specifies the number of bits for the file encryption keys.  The
-        default is 128 bits.
+        value values are 128 (the default), 192, and 256.
        </para>
       </listitem>
      </varlistentry>
diff --git a/doc/src/sgml/ref/pg_alterckey.sgml b/doc/src/sgml/ref/pg_alterckey.sgml
index f80946dcc6..867c439b8e 100644
--- a/doc/src/sgml/ref/pg_alterckey.sgml
+++ b/doc/src/sgml/ref/pg_alterckey.sgml
@@ -78,14 +78,14 @@ PostgreSQL documentation
   </para>
 
   <para>
-   Technically, <command>pg_alterckey</command> changes the key
-   encryption key (<acronym>KEK</acronym>) which encrypts the data
-   encryption keys;  it does not change the data encryption keys.  It does
-   this by decrypting each data encryption key using the <replaceable
+   <command>pg_alterckey</command> changes the key encryption key
+   (<acronym>KEK</acronym>) which encrypts the data encryption keys;
+   it does not change the data encryption keys.  It does this by
+   decrypting each data encryption key using the <replaceable
    class="parameter">old_cluster_key_command</replaceable>,
    re-encrypting it using the <replaceable
-   class="parameter">new_cluster_key_command</replaceable>, and
-   then writes the result back to the cluster directory.
+   class="parameter">new_cluster_key_command</replaceable>, and then
+   writes the result back to the cluster directory.
   </para>
 
   <para>
@@ -95,13 +95,26 @@ PostgreSQL documentation
    arguments to specify retrieval of the old or new key.
   </para>
 
+  <para>
+   <command>pg_alterckey</command> manages data encryption keys,
+   which are critical to allowing Postgres to access its decrypted
+   data.  For this reason, it is very careful to preserve these
+   keys in most possible failure conditions, e.g., operating system
+   failure during cluster encryption key rotation.
+  </para>
+
   <para>
    When started, <command>pg_alterckey</command> repairs any files that
-   remain from previous <command>pg_alterckey</command> failures before
-   altering the cluster key.  To perform only the repair task,
-   use the <option>--repair</option> option.  The server will not start
-   if repair is needed, though a running server is unaffected by an
-   unrepaired cluster key configuration.
+   remain from previous failures before altering the cluster encryption
+   key.  During this repair phase, <command>pg_alterckey</command> will
+   either roll back the cluster key or roll forward the changes that
+   were previously requested.  The server will not start if repair is
+   needed, though a running server is unaffected by an unrepaired cluster
+   key configuration.  Therefore, if <command>pg_alterckey</command>
+   fails for any reason, it is recommended you run the command with
+   <option>--repair</option> to simply roll back or forward any previous
+   changes.  This will report if it rolled the cluster key back or forward,
+   and then run the command again to change the cluster key if needed.
   </para>
 
   <para>
diff --git a/src/bin/pg_alterckey/pg_alterckey.c b/src/bin/pg_alterckey/pg_alterckey.c
index 6a809037b8..50e168306a 100644
--- a/src/bin/pg_alterckey/pg_alterckey.c
+++ b/src/bin/pg_alterckey/pg_alterckey.c
@@ -325,7 +325,7 @@ create_lockfile(void)
 		if (repair_mode)
 			printf("old lock file removed\n");
 
-		/*
+		/* ----------
 		 * pid is no longer running, so remove the lock file.
 		 * This is not 100% safe from concurrent access, e.g.:
 		 *
@@ -343,6 +343,7 @@ create_lockfile(void)
 		 * even more error-prone, especially since this might happen
 		 * on server start.  Many PG tools seem to have problems with
 		 * concurrent access.
+		 * ----------
 		 */
 		unlink(pid_path);
 
@@ -380,6 +381,7 @@ create_lockfile(void)
 }
 
 /*
+ * ----------
  *	recover_failure
  *
  * A previous pg_alterckey might have failed, so it might need recovery.
@@ -406,6 +408,7 @@ create_lockfile(void)
  *    remove old and new           X               X               X
  *
  * We don't handle the abnormal cases, just report an error.
+ * ----------
  */
 static void
 recover_failure(void)
