diff --git a/src/tarantool_lua.m b/src/tarantool_lua.m
index 37c5a25abb569c0df85a53687323b27ed3fa7aab..b50de35e53b8c07e163b6cd6026ed31e9fa85d87 100644
--- a/src/tarantool_lua.m
+++ b/src/tarantool_lua.m
@@ -902,6 +902,12 @@ tarantool_lua_register_type(struct lua_State *L, const char *type_name,
 	lua_pop(L, 1);
 }
 
+/**
+ * Remember the LuaJIT FFI extension reference index
+ * to protect it from being garbage collected.
+ */
+static int ffi_ref = 0;
+
 struct lua_State *
 tarantool_lua_init()
 {
@@ -914,6 +920,8 @@ tarantool_lua_init()
 	lua_pushstring(L, "ffi");
 	if (lua_pcall(L, 1, 0, 0) != 0)
 		panic("%s", lua_tostring(L, -1));
+	lua_getglobal(L, "ffi");
+	ffi_ref = luaL_ref(L, LUA_REGISTRYINDEX);
 	lua_pushnil(L);
 	lua_setglobal(L, "ffi");
 	luaL_register(L, boxlib_name, boxlib);
@@ -932,6 +940,7 @@ tarantool_lua_init()
 void
 tarantool_lua_close(struct lua_State *L)
 {
+	luaL_unref(L, LUA_REGISTRYINDEX, ffi_ref);
 	lua_close(L); /* collects garbage, invoking userdata gc */
 }
 
diff --git a/test/box/lua.result b/test/box/lua.result
index 074507d8ca1e834ccb88e0ac29e52e8a7cb5bcef..5047914c75ba7a64f06a7cfcd4bda1489a887cca 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -1138,3 +1138,10 @@ lua box.update_ol(0, ops_list, 1)
 lua box.space[0]:truncate()
 ---
 ...
+
+# test that ffi extension is inaccessible
+
+lua ffi
+---
+ - nil
+...
diff --git a/test/box/lua.test b/test/box/lua.test
index 82b31d21ddc7986137578e9ac2212b1662337255..d895f2de731cd4acebac631d83f7f2bcf839b90f 100644
--- a/test/box/lua.test
+++ b/test/box/lua.test
@@ -374,3 +374,9 @@ exec admin "lua table.insert(ops_list, box.upd.insert(1, 4))"
 exec admin "lua box.update_ol(0, ops_list, 1)"
 
 exec admin "lua box.space[0]:truncate()"
+
+print """
+# test that ffi extension is inaccessible
+"""
+
+exec admin "lua ffi"