diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c
index d133ddcccb81f7ca75459127d0a77d162ed402d9..ba0715616359055c5be02ff69552672f6f27770a 100644
--- a/src/lib/core/fiber.c
+++ b/src/lib/core/fiber.c
@@ -2357,6 +2357,12 @@ fiber_set_system(struct fiber *f, bool yesno)
 	}
 }
 
+void
+fiber_set_managed_shutdown(struct fiber *f)
+{
+	f->flags |= FIBER_MANAGED_SHUTDOWN;
+}
+
 int
 fiber_shutdown(double timeout)
 {
@@ -2364,6 +2370,8 @@ fiber_shutdown(double timeout)
 	cord()->is_shutdown = true;
 	struct fiber *fiber;
 	rlist_foreach_entry(fiber, &cord()->alive, link) {
+		if (fiber->flags & FIBER_MANAGED_SHUTDOWN)
+			fiber_set_system(fiber, false);
 		if (!(fiber->flags & FIBER_IS_SYSTEM))
 			fiber_cancel(fiber);
 	}
diff --git a/src/lib/core/fiber.h b/src/lib/core/fiber.h
index 2f0885ba60512f7b2172e5f56897bc108a503512..4abdb92847e8fb9963c2c0f2c31bc5687df96e74 100644
--- a/src/lib/core/fiber.h
+++ b/src/lib/core/fiber.h
@@ -175,6 +175,11 @@ enum {
 	 * once again nor can its joinability be changed.
 	 */
 	FIBER_JOIN_BEEN_INVOKED = 1 << 9,
+	/**
+	 * Makes sense only for system fibers. If flag is set then fiber
+	 * will be finished on fiber_shutdown().
+	 */
+	FIBER_MANAGED_SHUTDOWN = 1 << 10,
 	FIBER_DEFAULT_FLAGS	= 0
 };
 
@@ -1245,6 +1250,14 @@ fiber_lua_state(struct fiber *f);
 void
 fiber_set_system(struct fiber *f, bool yesno);
 
+/**
+ * Turn managed shutdown on for system fiber. See FIBER_MANAGED_SHUTDOWN.
+ * It is should be used after fiber creation. Using it during shutdown does not
+ * work.
+ */
+void
+fiber_set_managed_shutdown(struct fiber *f);
+
 /**
  * Cancel all client (non system) fibers and wait until they finished.
  *
diff --git a/src/lua/fiber.c b/src/lua/fiber.c
index 88ea0fad35419b2e07b65877b771e6b9136c3daf..d66f59d314e41446958bee302457bee3345d620a 100644
--- a/src/lua/fiber.c
+++ b/src/lua/fiber.c
@@ -938,6 +938,20 @@ lbox_fiber_set_system(struct lua_State *L)
 	return 0;
 }
 
+/** Turn managed shutdown for fiber. Takes the fiber as single argument. */
+static int
+lbox_fiber_set_managed_shutdown(struct lua_State *L)
+{
+	if (lua_gettop(L) != 1) {
+		diag_set(IllegalParams,
+			 "fiber.set_managed_shutdown(id): bad arguments");
+		luaT_error(L);
+	}
+	struct fiber *fiber = lbox_checkfiber(L, 1);
+	fiber_set_managed_shutdown(fiber);
+	return 0;
+}
+
 /** Helper for fiber slice parsing. */
 static struct fiber_slice
 lbox_fiber_slice_parse(struct lua_State *L, int idx)
@@ -1085,6 +1099,7 @@ static const struct luaL_Reg fiberlib[] = {
 	/* Internal functions, to hide in fiber.lua. */
 	{"stall", lbox_fiber_stall},
 	{"set_system", lbox_fiber_set_system},
+	{"set_managed_shutdown", lbox_fiber_set_managed_shutdown},
 	{NULL, NULL}
 };
 
diff --git a/src/lua/fiber.lua b/src/lua/fiber.lua
index 48eda368add5746260531311c840834a8faf50cd..44470e8043ae914c284857cd9f2d4f159c28bc5f 100644
--- a/src/lua/fiber.lua
+++ b/src/lua/fiber.lua
@@ -74,8 +74,10 @@ fiber.clock64 = fiber_clock64
 
 local stall = fiber.stall
 local fiber_set_system = fiber.set_system
+local fiber_set_managed_shutdown = fiber.set_managed_shutdown
 fiber.stall = nil
 fiber.set_system = nil
+fiber.set_managed_shutdown = nil
 
 local worker_next_task = nil
 local worker_last_task
@@ -134,6 +136,7 @@ end
 fiber._internal = fiber._internal or {}
 fiber._internal.schedule_task = worker_schedule_task
 fiber._internal.set_system = fiber_set_system
+fiber._internal.set_managed_shutdown = fiber_set_managed_shutdown
 
 setmetatable(fiber, {__serialize = function(self)
     local res = table.copy(self)
diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc
index 36cd59b7420e895f29de97b1de82e5fd38c148df..5daf5975296d11074b4025b6b64cf4fe9b87632f 100644
--- a/test/unit/fiber.cc
+++ b/test/unit/fiber.cc
@@ -695,6 +695,10 @@ fiber_test_shutdown(void)
 	struct fiber *fiber4 = fiber_new("fiber4", new_fiber_on_shudown_f);
 	fail_unless(fiber4 != NULL);
 	fiber_set_joinable(fiber4, true);
+	struct fiber *fiber6 = fiber_new_system("fiber6", wait_cancel_f);
+	fail_unless(fiber6 != NULL);
+	fiber_set_managed_shutdown(fiber6);
+	fiber_set_joinable(fiber6, true);
 
 	int rc = fiber_shutdown(1000.0);
 	fail_unless(rc == 0);
@@ -703,9 +707,11 @@ fiber_test_shutdown(void)
 	fail_unless((fiber2->flags & FIBER_IS_DEAD) == 0);
 	fail_unless((fiber3->flags & FIBER_IS_DEAD) == 0);
 	fail_unless((fiber4->flags & FIBER_IS_DEAD) != 0);
+	fail_unless((fiber6->flags & FIBER_IS_DEAD) != 0);
 
 	fiber_join(fiber1);
 	fiber_join(fiber4);
+	fiber_join(fiber6);
 
 	fiber_set_joinable(fiber2, true);
 	fiber_cancel(fiber2);