diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c
index ab4ef62..434fffb 100644
--- a/src/backend/storage/ipc/standby.c
+++ b/src/backend/storage/ipc/standby.c
@@ -86,6 +86,58 @@ InitRecoveryTransactionEnvironment(void)
 	vxid.localTransactionId = GetNextLocalTransactionId();
 	VirtualXactLockTableInsert(vxid);
 
+	/*
+	 * We can only move directly to STANDBY_SNAPSHOT_READY at startup if we
+	 * start from a shutdown checkpoint. In the case of starting from an
+	 * online checkpoint the situation is more complex and requires a two
+	 * or sometimes a three stage process.
+	 *
+	 * standbyState starts here at STANDBY_INITIALIZED and changes state to
+	 * either STANDBY_SNAPSHOT_PENDING or STANDBY_SNAPSHOT_READY. If we are
+	 * at STANDBY_SNAPSHOT_PENDING state we can only change to
+	 * STANDBY_SNAPSHOT_READY at which we stay until shutdown.
+	 * 
+	 * The initial snapshot must contain all running xids and all current
+	 * AccessExclusiveLocks at a point in time on the standby. Assembling
+	 * that information requires many and various LWLocks, so we choose to
+	 * derive that information piece by piece and then re-assemble that info
+	 * on the standby. When that information is fully assembled we move to
+	 * STANDBY_SNAPSHOT_READY.
+	 *
+	 * Since locking on the primary when we derive the information is not
+	 * strict, we note that there is a time window between the derivation and
+	 * writing to WAL of the derived information. That allows race conditions
+	 * that we must resolve, since xids and locks may enter or leave the
+	 * snapshot during that window. This creates the issue that an xid or
+	 * lock may start *after* the snapshot has been derived yet *before* the
+	 * snapshot is logged in the running xacts WAL record. We resolve this by
+	 * starting to accumulate changes at a point immediately before we derive
+	 * the snapshot on the primary and ignore duplicates when we later apply
+	 * the snapshot from the running xacts record. This is implemented during
+	 * CreateCheckpoint() where we use the logical checkpoint location as
+	 * our starting point and then write the running xacts record immediately
+	 * before writing the main checkpoint WAL record. Since we always start
+	 * up from a checkpoint and we are immediately at our starting point, so
+	 * we unconditionally move to STANDBY_INITIALIZED. After this point we
+	 * must do 4 things: 
+	 *  * move shared nextXid forwards as we see new xids
+	 *  * extend the clog and subtrans with the new xid
+	 *  * keep track of uncommitted known assigned xids
+	 *  * keep track of uncommitted AccessExclusiveLocks
+	 *
+	 * When we see a commit/abort we must remove known assigned xids and locks
+	 * from the completing transaction. Attempted removals that cannot locate
+	 * an entry are expected and must not cause an error when we are in state
+	 * STANDBY_INITIALIZED. This is implemented in StandbyReleaseLocks() and
+	 * KnownAssignedXidsRemove().
+	 * 
+	 * Later, when we apply the running xact data we must be careful to ignore
+	 * transactions already committed, since those commits raced ahead when
+	 * making WAL entries.
+	 *
+	 * XXX We can further optimize LWlocking by keeping track of whether any
+	 * AccessExclusiveLocks exist.
+	 */
 	standbyState = STANDBY_INITIALIZED;
 }
 
