diff --git a/changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md b/changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md
new file mode 100644
index 0000000000000000000000000000000000000000..71fc747a99c247503222ea630f0f662b5bad5d3b
--- /dev/null
+++ b/changelogs/unreleased/gh-9020-fix-use-after-free-on-fiber-finish.md
@@ -0,0 +1,3 @@
+## bugfix/core
+
+* Fixed a use-after-free bug in fiber recycling code (gh-9020).
diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c
index 3694e0bbdcc72923a78a290def1f2724309f4d82..50ec73c7837d3505da2b45b1603c30336603612a 100644
--- a/src/lib/core/fiber.c
+++ b/src/lib/core/fiber.c
@@ -931,14 +931,13 @@ fiber_recycle(struct fiber *fiber)
 	fiber->storage.lua.fid_ref = FIBER_LUA_NOREF;
 	unregister_fid(fiber);
 	fiber->fid = 0;
-	/* Set before free to disable truncation system area check. */
 	fiber->gc_initial_size = 0;
-	region_free(&fiber->gc);
 #ifdef ENABLE_BACKTRACE
 	fiber->parent_bt = NULL;
 	fiber->first_alloc_bt = NULL;
 	region_set_callbacks(&fiber->gc, NULL, NULL, NULL);
 #endif
+	region_free(&fiber->gc);
 	if (fiber_is_reusable(fiber->flags)) {
 		rlist_move_entry(&cord()->dead, fiber, link);
 	} else {
@@ -1459,8 +1458,9 @@ fiber_destroy(struct cord *cord, struct fiber *f)
 	trigger_destroy(&f->on_stop);
 	rlist_del(&f->state);
 	rlist_del(&f->link);
-	/* Set before free to disable truncation system area check. */
-	f->gc_initial_size = 0;
+#ifdef ENABLE_BACKTRACE
+	region_set_callbacks(&f->gc, NULL, NULL, NULL);
+#endif
 	region_destroy(&f->gc);
 	fiber_stack_destroy(f, &cord->slabc);
 	diag_destroy(&f->diag);