diff --git a/changelogs/unreleased/fix-is-recovering-function b/changelogs/unreleased/fix-is-recovering-function
new file mode 100644
index 0000000000000000000000000000000000000000..ff2117d58894223496505ef732b78ec93d00e715
--- /dev/null
+++ b/changelogs/unreleased/fix-is-recovering-function
@@ -0,0 +1,4 @@
+## bugfix/core
+
+* Fix lbox_ctl_is_recovery_finished(): in some cases it might return true
+  even if recovery was still in the progress.
diff --git a/src/box/lua/ctl.c b/src/box/lua/ctl.c
index b44474b124dc9cfa68b032037f2f7df46d07fa2a..b81199662be1dcb7a069bbf2f15743455959dcec 100644
--- a/src/box/lua/ctl.c
+++ b/src/box/lua/ctl.c
@@ -94,7 +94,7 @@ lbox_ctl_is_recovery_finished(struct lua_State *L)
 	struct memtx_engine *memtx;
 	memtx = (struct memtx_engine *)engine_by_name("memtx");
 	lua_pushboolean(L, (memtx ?
-		(memtx->state < MEMTX_FINAL_RECOVERY ? 0 : 1) : 0));
+		(memtx->state < MEMTX_OK ? 0 : 1) : 0));
 	return 1;
 }
 
diff --git a/src/box/memtx_space.h b/src/box/memtx_space.h
index 68e6264adb32b9625f5ce58d8fe0ce0faf904679..a13dae7145af91fe31dfb22cfe77c6e16a9940c9 100644
--- a/src/box/memtx_space.h
+++ b/src/box/memtx_space.h
@@ -93,7 +93,7 @@ memtx_space_is_recovering(struct space *space)
 {
 	assert(space_is_memtx(space));
 	struct memtx_engine *memtx = (struct memtx_engine *)space->engine;
-	return memtx->state < MEMTX_FINAL_RECOVERY;
+	return memtx->state < MEMTX_OK;
 }
 
 #if defined(__cplusplus)
diff --git a/test/box/gh-5304-insert_during_recovery.lua b/test/box/gh-5304-insert_during_recovery.lua
index c8b6c5cfb788b76d025968967071727f985b49f0..2d84a95e308fd3d5be8d663cbd95b7ec850afbec 100644
--- a/test/box/gh-5304-insert_during_recovery.lua
+++ b/test/box/gh-5304-insert_during_recovery.lua
@@ -32,13 +32,15 @@ end
 
 if arg[2] == 'is_recovery_finished' then
     box.ctl.on_schema_init(function()
-        if box.ctl.is_recovery_finished() then
-            box.space._user:on_replace(trigger)
-        end
+        box.space._index:on_replace(function(old_space, new_space)
+            if box.ctl.is_recovery_finished() then
+                trigger(old_space, new_space)
+            end
+        end)
     end)
 else
     box.ctl.on_schema_init(function()
-        box.space._user:on_replace(trigger)
+        box.space._index:on_replace(trigger)
     end)
 end
 
diff --git a/test/box/gh-5304-insert_during_recovery.result b/test/box/gh-5304-insert_during_recovery.result
index 19823c71fd8cfc6cf58a5e310284fa936f66b2a5..deec6ee04d11c2f1d19ac3a848eafd123d91180e 100644
--- a/test/box/gh-5304-insert_during_recovery.result
+++ b/test/box/gh-5304-insert_during_recovery.result
@@ -61,6 +61,42 @@ test_run:cmd('start server test with args="replace is_recovery_finished"')
  | ---
  | - true
  | ...
+test_run:cmd('switch test')
+ | ---
+ | - true
+ | ...
+box.space.temp:select()
+ | ---
+ | - []
+ | ...
+box.space.loc:select()
+ | ---
+ | - []
+ | ...
+-- Creating a new space and index invokes on_replace trigger in _index space,
+-- which inserts tuples in temp and loc spaces (see gh-5304-insert_during_recovery.lua)!
+s0 = box.schema.space.create('test')
+ | ---
+ | ...
+i0 = s0:create_index('test')
+ | ---
+ | ...
+box.space.temp:select()
+ | ---
+ | - - [1]
+ | ...
+box.space.loc:select()
+ | ---
+ | - - [1]
+ | ...
+s0:drop()
+ | ---
+ | ...
+
+test_run:cmd('switch default')
+ | ---
+ | - true
+ | ...
 test_run:cmd('stop server test')
  | ---
  | - true
@@ -69,6 +105,44 @@ test_run:cmd('start server test with args="insert is_recovery_finished"')
  | ---
  | - true
  | ...
+test_run:cmd('switch test')
+ | ---
+ | - true
+ | ...
+box.space.temp:select()
+ | ---
+ | - []
+ | ...
+box.space.loc:select()
+ | ---
+ | - - [1]
+ | ...
+-- Creating a new space and index invoke on_replace trigger in _index space.
+-- Here we get error during insert tuple in loc space, because the tuple
+-- with the same primary key is already in the loc space
+s0 = box.schema.space.create('test')
+ | ---
+ | ...
+i0 = s0:create_index('test')
+ | ---
+ | - error: Duplicate key exists in unique index 'test' in space 'loc'
+ | ...
+box.space.temp:select()
+ | ---
+ | - []
+ | ...
+box.space.loc:select()
+ | ---
+ | - - [1]
+ | ...
+s0:drop()
+ | ---
+ | ...
+
+test_run:cmd('switch default')
+ | ---
+ | - true
+ | ...
 test_run:cmd('stop server test')
  | ---
  | - true
@@ -77,6 +151,40 @@ test_run:cmd('start server test with args="upsert is_recovery_finished"')
  | ---
  | - true
  | ...
+test_run:cmd('switch test')
+ | ---
+ | - true
+ | ...
+box.space.temp:select()
+ | ---
+ | - []
+ | ...
+box.space.loc:select()
+ | ---
+ | - - [1]
+ | ...
+s0 = box.schema.space.create('test')
+ | ---
+ | ...
+i0 = s0:create_index('test')
+ | ---
+ | ...
+box.space.temp:select()
+ | ---
+ | - - [1]
+ | ...
+box.space.loc:select()
+ | ---
+ | - - [1]
+ | ...
+s0:drop()
+ | ---
+ | ...
+
+test_run:cmd('switch default')
+ | ---
+ | - true
+ | ...
 test_run:cmd('stop server test')
  | ---
  | - true
diff --git a/test/box/gh-5304-insert_during_recovery.test.lua b/test/box/gh-5304-insert_during_recovery.test.lua
index 97171e96419d6825a24a8793198f306122d5c820..2846499c7f0023c772c5b17fc73435a8955c5ba2 100644
--- a/test/box/gh-5304-insert_during_recovery.test.lua
+++ b/test/box/gh-5304-insert_during_recovery.test.lua
@@ -18,10 +18,45 @@ test_run:cmd('start server test with args="replace" with crash_expected=True')
 test_run:cmd('start server test with args="insert" with crash_expected=True')
 test_run:cmd('start server test with args="upsert" with crash_expected=True')
 test_run:cmd('start server test with args="replace is_recovery_finished"')
+test_run:cmd('switch test')
+box.space.temp:select()
+box.space.loc:select()
+-- Creating a new space and index invokes on_replace trigger in _index space,
+-- which inserts tuples in temp and loc spaces (see gh-5304-insert_during_recovery.lua)!
+s0 = box.schema.space.create('test')
+i0 = s0:create_index('test')
+box.space.temp:select()
+box.space.loc:select()
+s0:drop()
+
+test_run:cmd('switch default')
 test_run:cmd('stop server test')
 test_run:cmd('start server test with args="insert is_recovery_finished"')
+test_run:cmd('switch test')
+box.space.temp:select()
+box.space.loc:select()
+-- Creating a new space and index invoke on_replace trigger in _index space.
+-- Here we get error during insert tuple in loc space, because the tuple
+-- with the same primary key is already in the loc space
+s0 = box.schema.space.create('test')
+i0 = s0:create_index('test')
+box.space.temp:select()
+box.space.loc:select()
+s0:drop()
+
+test_run:cmd('switch default')
 test_run:cmd('stop server test')
 test_run:cmd('start server test with args="upsert is_recovery_finished"')
+test_run:cmd('switch test')
+box.space.temp:select()
+box.space.loc:select()
+s0 = box.schema.space.create('test')
+i0 = s0:create_index('test')
+box.space.temp:select()
+box.space.loc:select()
+s0:drop()
+
+test_run:cmd('switch default')
 test_run:cmd('stop server test')
 test_run:cmd('cleanup server test')
 test_run:cmd('delete server test')