diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index d6c057a..f5a537c 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -252,6 +252,7 @@ static char *archiveCleanupCommand = NULL;
 static RecoveryTargetType recoveryTarget = RECOVERY_TARGET_UNSET;
 static bool recoveryTargetInclusive = true;
 static RecoveryTargetAction recoveryTargetAction = RECOVERY_TARGET_ACTION_PAUSE;
+static RecoveryTargetIncomplete recoveryTargetIncomplete = RECOVERY_TARGET_INCOMPLETE_PROMOTE;
 static TransactionId recoveryTargetXid;
 static TimestampTz recoveryTargetTime;
 static char *recoveryTargetName;
@@ -789,10 +790,12 @@ static MemoryContext walDebugCxt = NULL;
 #endif
 
 static void readRecoveryCommandFile(void);
+static void recoveryStartsHere(void);
 static void exitArchiveRecovery(TimeLineID endTLI, XLogRecPtr endOfLog);
 static bool recoveryStopsBefore(XLogReaderState *record);
 static bool recoveryStopsAfter(XLogReaderState *record);
 static void recoveryPausesHere(void);
+static void IncompleteRecoveryPause(void);
 static bool recoveryApplyDelay(XLogReaderState *record);
 static void SetLatestXTime(TimestampTz xtime);
 static void SetCurrentChunkStartTime(TimestampTz xtime);
@@ -4949,7 +4952,6 @@ readRecoveryCommandFile(void)
 			   *tail = NULL;
 	bool		recoveryTargetActionSet = false;
 
-
 	fd = AllocateFile(RECOVERY_COMMAND_FILE, "r");
 	if (fd == NULL)
 	{
@@ -5014,6 +5016,26 @@ readRecoveryCommandFile(void)
 
 			recoveryTargetActionSet = true;
 		}
+		else if (strcmp(item->name, "recovery_target_incomplete") == 0)
+		{
+			if (strcmp(item->value, "pause") == 0)
+				recoveryTargetIncomplete = RECOVERY_TARGET_INCOMPLETE_PAUSE;
+			else if (strcmp(item->value, "promote") == 0)
+				recoveryTargetIncomplete = RECOVERY_TARGET_INCOMPLETE_PROMOTE;
+			else if (strcmp(item->value, "shutdown") == 0)
+				recoveryTargetIncomplete = RECOVERY_TARGET_INCOMPLETE_SHUTDOWN;
+			else
+				ereport(ERROR,
+						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+				errmsg("invalid value for recovery parameter \"%s\": \"%s\"",
+					   "recovery_target_incomplete",
+					   item->value),
+						 errhint("Valid values are \"pause\", \"promote\", and \"shutdown\".")));
+
+			ereport(DEBUG2,
+					(errmsg_internal("recovery_target_incomplete = '%s'",
+									 item->value)));
+		}
 		else if (strcmp(item->name, "recovery_target_timeline") == 0)
 		{
 			rtliGiven = true;
@@ -5395,6 +5417,60 @@ getRecordTimestamp(XLogReaderState *record, TimestampTz *recordXtime)
 	return false;
 }
 
+/* When performing point-in-time-recovery, this function identifies if
+ * the specified recovery target (recovery_target_time, recovery_target_lsn and recovery_target_xid) is prior to that of the backup.
+ * Which means, recovery cannot proceed if the recovery target point is prior to backup start point.
+ */
+
+static void
+recoveryStartsHere(void)
+{
+	/*
+	 * Check if the recovery target xid is older than the oldest xid of the
+	 * backup
+	 */
+
+	if (recoveryTarget == RECOVERY_TARGET_XID)
+	{
+		if (TransactionIdPrecedes(recoveryTargetXid,
+								  ControlFile->checkPointCopy.oldestXid))
+		{
+			ereport(FATAL,
+					(errmsg("recovery_target_xid %u is older that backup's Xid %u", recoveryTargetXid, ControlFile->checkPointCopy.oldestXid),
+					 errhint("This means that the backup being used is much later than the recovery target position."
+							 "You might need to use a backup taken prior to the recovery target point.")));
+		}
+	}
+
+	/* Check if the recovery target lsn is prior to the latest checkpoint redo position of the backup */
+
+	if (recoveryTarget == RECOVERY_TARGET_LSN)
+	{
+		if (recoveryTargetLSN < ControlFile->checkPointCopy.redo)
+		{
+			ereport(FATAL,
+					(errmsg("recovery_target_lsn \"%X/%X\" is older than backup start LSN \"%X/%X\"",
+							(uint32) (recoveryTargetLSN >> 32),
+							(uint32) recoveryTargetLSN, (uint32) (ControlFile->checkPointCopy.redo >> 32), (uint32) ControlFile->checkPointCopy.redo),
+					 errhint("This means that the backup being used is much later than the recovery target position."
+							 "You might need to use a backup taken prior to the recovery target point.")));
+		}
+	}
+
+	/* Check if the recovery target time is prior to the current timestamp of the backup */
+
+	if (recoveryTarget == RECOVERY_TARGET_TIME)
+	{
+		if (recoveryTargetTime < ControlFile->checkPointCopy.time)
+		{
+			ereport(FATAL,
+					(errmsg("recovery_target_time %s is older than backup start time %s", timestamptz_to_str(recoveryTargetTime), timestamptz_to_str(ControlFile->checkPointCopy.time)),
+					 errhint("This means that the backup being used is much later than the recovery target position."
+							 "You might need to use a backup taken prior to the recovery target point.")));
+		}
+	}
+}
+
 /*
  * For point-in-time recovery, this function decides whether we want to
  * stop applying the XLOG before the current record.
@@ -5740,6 +5816,23 @@ SetRecoveryPause(bool recoveryPause)
 	SpinLockRelease(&XLogCtl->info_lck);
 }
 
+static void
+IncompleteRecoveryPause(void)
+{
+	/* Pause recovery at end-of-the-wal when recovery target is not reached */
+	ereport(LOG,
+			(errmsg("recovery has paused"),
+			 errhint("Execute pg_xlog_replay_resume() to continue.")));
+
+	while (RecoveryIsPaused())
+	{
+		pg_usleep(1000000L);	/* 1000 ms */
+		HandleStartupProcInterrupts();
+	}
+}
+
+
+
 /*
  * When recovery_min_apply_delay is set, we wait long enough to make sure
  * certain record types are applied at least that interval behind the master.
@@ -6128,6 +6221,9 @@ StartupXLOG(void)
 					(errmsg("starting archive recovery")));
 	}
 
+	/* Check if archive recovery can start at all */
+	recoveryStartsHere();
+
 	/*
 	 * Take ownership of the wakeup latch if we're going to sleep during
 	 * recovery.
@@ -7040,6 +7136,46 @@ StartupXLOG(void)
 						break;
 				}
 			}
+			else
+			{
+				ereport(LOG,
+						(errmsg("recovery has reached end-of-the-wal and has not reached the recovery target yet"),
+				errhint("This could be due to corrupt or missing WAL files.\n"
+						"All the WAL files needed for the recovery must be available to proceed to the recovery target "
+				"Or you might need to choose an earlier recovery target.")));
+
+				/*
+				 * This is the position where we can choose to shutdown, pause
+				 * or promote at the end-of-the-wal if the intended recovery
+				 * target is not reached
+				 */
+
+				switch (recoveryTargetIncomplete)
+				{
+
+					case RECOVERY_TARGET_INCOMPLETE_SHUTDOWN:
+
+						/*
+						 * exit with special return code to request shutdown
+						 * of postmaster.  Log messages issued from
+						 * postmaster.
+						 */
+						ereport(LOG,
+								(errmsg("shutdown at end-of-the-wal")));
+
+						proc_exit(2);
+
+					case RECOVERY_TARGET_INCOMPLETE_PAUSE:
+
+						SetRecoveryPause(true);
+						IncompleteRecoveryPause();
+
+						/* drop into promote */
+
+					case RECOVERY_TARGET_INCOMPLETE_PROMOTE:
+						break;
+				}
+			}
 
 			/* Allow resource managers to do any required cleanup. */
 			for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index ceb0462..799ddc2 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -256,6 +256,18 @@ typedef enum
 } RecoveryTargetAction;
 
 /*
+ * Recovery target incomplete.
+ */
+
+typedef enum
+{
+	RECOVERY_TARGET_INCOMPLETE_PAUSE,
+	RECOVERY_TARGET_INCOMPLETE_PROMOTE,
+	RECOVERY_TARGET_INCOMPLETE_SHUTDOWN
+}	RecoveryTargetIncomplete;
+
+
+/*
  * Method table for resource managers.
  *
  * This struct must be kept in sync with the PG_RMGR definition in
