diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+# v0.5.3
+
+* It now delays a response if it fails to resolve the range specified by `ByIndex`
+
 # v0.5.2
 
 * Fixed the undesirable behaviour that causes an empty response when `BySeqNum (-1)` is specified
diff --git a/franz.cabal b/franz.cabal
--- a/franz.cabal
+++ b/franz.cabal
@@ -1,5 +1,5 @@
 cabal-version:  2.0
-version:        0.5.2
+version:        0.5.3
 name:           franz
 description:    Please see the README on GitHub at <https://github.com/tsurucapital/franz#readme>
 homepage:       https://github.com/tsurucapital/franz#readme
diff --git a/src/Database/Franz/Internal/Reader.hs b/src/Database/Franz/Internal/Reader.hs
--- a/src/Database/Franz/Internal/Reader.hs
+++ b/src/Database/Franz/Internal/Reader.hs
@@ -312,33 +312,36 @@
           | i < 0 = finalOffset + i
           | otherwise = i
     begin <- case begin_ of
-      BySeqNum i -> pure $ rotate i
+      BySeqNum i -> pure $ Just $ rotate i
       ByIndex index val -> case HM.lookup index indices of
         Nothing -> throwSTM $ IndexNotFound index $ HM.keys indices
         Just v -> do
           m <- readTVar v
           let (_, wing) = splitR val m
-          return $! maybe maxBound fst $ IM.minView wing
+          return $! fst <$> IM.minView wing
     end <- case end_ of
-      BySeqNum i -> pure $ rotate i
+      BySeqNum i -> pure $ Just $ rotate i
       ByIndex index val -> case HM.lookup index indices of
         Nothing -> throwSTM $ IndexNotFound index $ HM.keys indices
         Just v -> do
           m <- readTVar v
           let (body, lastItem, _) = IM.splitLookup val m
           let body' = maybe id (IM.insert val) lastItem body
-          return $! maybe minBound fst $ IM.maxView body'
-    return $! case range begin end rt allOffsets of
-      (ready, result)
-        -- When BySeqNum (-1) is specified, the client expects at least one item.
-        -- More concretely, (ByIndex "time" t, BySeqNum (-1)) should resolve ByIndex
-        -- until there's an item with a timestamp later than t.
-        -- Perhaps there should be a special constructor for ItemRef that points to
-        -- the latest item at transaction, and redefine "Nth-from-end" semantics
-        -- where the "end" is frozen at the reception of the query.
-        | BySeqNum i <- end_, i < 0, isEmptyResult result -> Nothing
-        | ready -> Just result
-        | otherwise -> Nothing
+          return $! fst <$> IM.maxView body'
+    return $! do
+      b <- begin
+      e <- end
+      case range b e rt allOffsets of
+        (ready, result)
+          -- When BySeqNum (-1) is specified, the client expects at least one item.
+          -- More concretely, (ByIndex "time" t, BySeqNum (-1)) should resolve ByIndex
+          -- until there's an item with a timestamp later than t.
+          -- Perhaps there should be a special constructor for ItemRef that points to
+          -- the latest item at transaction, and redefine "Nth-from-end" semantics
+          -- where the "end" is frozen at the reception of the query.
+          | BySeqNum i <- end_, i < 0, isEmptyResult result -> Nothing
+          | ready -> Just result
+          | otherwise -> Nothing
   where
     acquire = join $ atomically $ do
       allStreams <- readTVar vStreams
