diff --git a/src/executor/engine/cartridge.rs b/src/executor/engine/cartridge.rs
index 633d055e7dabcd18c137133f29e927f78ef4f164..d183d78332b29a21be21080709d3d24a74b27ad0 100644
--- a/src/executor/engine/cartridge.rs
+++ b/src/executor/engine/cartridge.rs
@@ -258,10 +258,62 @@ impl Runtime {
         buckets: &Buckets,
     ) -> Result<BoxExecuteFormat, QueryPlannerError> {
         let lua = tarantool::lua_state();
-        match lua.exec(
-            r#"local vshard = require('vshard')
+
+        let exec_sql: LuaFunction<_> = lua.get("execute_sql").ok_or_else(|| {
+            QueryPlannerError::LuaError("Lua function `execute_sql` not found".into())
+        })?;
+
+        let lua_buckets = match buckets {
+            Buckets::All => vec![],
+            Buckets::Filtered(list) => list.iter().copied().collect(),
+        };
+
+        let waiting_timeout = &self.metadata().get_exec_waiting_timeout();
+        let res: BoxExecuteFormat =
+            match exec_sql.call_with_args((query, lua_buckets, waiting_timeout)) {
+                Ok(v) => v,
+                Err(e) => {
+                    say(
+                        SayLevel::Error,
+                        file!(),
+                        line!().try_into().unwrap_or(0),
+                        Option::from("exec_query"),
+                        &format!("{:?}", e),
+                    );
+                    return Err(QueryPlannerError::LuaError(format!("Lua error: {:?}", e)));
+                }
+            };
+
+        Ok(res)
+    }
+}
+
+/// Extra lua functions loader. It is necessary for query execution.
+///
+/// # Errors
+/// - Failed to load lua code.
+pub fn load_extra_function() -> Result<(), QueryPlannerError> {
+    let lua = tarantool::lua_state();
+
+    match lua.exec(
+        r#"local vshard = require('vshard')
     local yaml = require('yaml')
     local log = require('log')
+    local cartridge = require('cartridge')
+
+    function get_schema()
+        return cartridge.get_schema()
+    end
+
+    function get_waiting_timeout()
+        local cfg = cartridge.config_get_readonly()
+
+        if cfg["executor_waiting_timeout"] == nil then
+            return 0
+        end
+
+        return cfg["executor_waiting_timeout"]
+    end
 
     ---get_uniq_replicaset_for_buckets - gets unique set of replicaset by bucket list
     ---@param buckets table - list of buckets.
@@ -325,48 +377,20 @@ impl Runtime {
     return result
     end
 "#,
-        ) {
-            Ok(_) => {}
-            Err(e) => {
-                say(
-                    SayLevel::Error,
-                    file!(),
-                    line!().try_into().unwrap_or(0),
-                    Option::from("exec_query"),
-                    &format!("{:?}", e),
-                );
-                return Err(QueryPlannerError::LuaError(format!(
-                    "Failed lua code loading: {:?}",
-                    e
-                )));
-            }
+    ) {
+        Ok(_) => Ok(()),
+        Err(e) => {
+            say(
+                SayLevel::Error,
+                file!(),
+                line!().try_into().unwrap_or(0),
+                Option::from("exec_query"),
+                &format!("{:?}", e),
+            );
+            Err(QueryPlannerError::LuaError(format!(
+                "Failed lua code loading: {:?}",
+                e
+            )))
         }
-
-        let exec_sql: LuaFunction<_> = lua.get("execute_sql").ok_or_else(|| {
-            QueryPlannerError::LuaError("Lua function `execute_sql` not found".into())
-        })?;
-
-        let lua_buckets = match buckets {
-            Buckets::All => vec![],
-            Buckets::Filtered(list) => list.iter().copied().collect(),
-        };
-
-        let waiting_timeout = &self.metadata().get_exec_waiting_timeout();
-        let res: BoxExecuteFormat =
-            match exec_sql.call_with_args((query, lua_buckets, waiting_timeout)) {
-                Ok(v) => v,
-                Err(e) => {
-                    say(
-                        SayLevel::Error,
-                        file!(),
-                        line!().try_into().unwrap_or(0),
-                        Option::from("exec_query"),
-                        &format!("{:?}", e),
-                    );
-                    return Err(QueryPlannerError::LuaError(format!("Lua error: {:?}", e)));
-                }
-            };
-
-        Ok(res)
     }
 }
diff --git a/src/executor/result.rs b/src/executor/result.rs
index b1d4ac2dfef0aba26ea39e354feadd7b45c2b98f..efedaa69266f2ebdaab80a53faf78e853317ab9f 100644
--- a/src/executor/result.rs
+++ b/src/executor/result.rs
@@ -179,7 +179,7 @@ impl Default for BoxExecuteFormat {
 
 impl BoxExecuteFormat {
     /// Create empty query result set
-    #[allow(dead_code)]
+    #[must_use]
     pub fn new() -> Self {
         BoxExecuteFormat {
             metadata: Vec::new(),
diff --git a/src/parser.rs b/src/parser.rs
index 563ba05a72e214bf7e30e4ad6e2c8a7a15a75930..103da88577a70b6c226eabcc29431f71a063062d 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -1,5 +1,3 @@
-mod extargs;
-
 use std::cell::RefCell;
 use std::convert::TryInto;
 use std::os::raw::c_int;
@@ -10,11 +8,14 @@ use tarantool::log::{say, SayLevel};
 use tarantool::tuple::{AsTuple, FunctionArgs, FunctionCtx, Tuple};
 
 use crate::errors::QueryPlannerError;
+use crate::executor::engine::cartridge::load_extra_function;
 use crate::executor::engine::{cartridge, Engine};
 use crate::executor::Query;
 
 use self::extargs::{BucketCalcArgs, BucketCalcArgsDict};
 
+mod extargs;
+
 thread_local!(static QUERY_ENGINE: RefCell<cartridge::Runtime> = RefCell::new(cartridge::Runtime::new().unwrap()));
 
 #[derive(Serialize, Deserialize)]
@@ -37,6 +38,19 @@ pub extern "C" fn invalidate_caching_schema(ctx: FunctionCtx, _: FunctionArgs) -
     0
 }
 
+#[no_mangle]
+pub extern "C" fn load_lua_extra_function(ctx: FunctionCtx, _: FunctionArgs) -> c_int {
+    match load_extra_function() {
+        Ok(_) => {
+            ctx.return_mp(&true).unwrap();
+            0
+        }
+        Err(e) => {
+            tarantool::set_error!(TarantoolErrorCode::ProcC, "{}", e.to_string())
+        }
+    }
+}
+
 #[no_mangle]
 pub extern "C" fn calculate_bucket_id(ctx: FunctionCtx, args: FunctionArgs) -> c_int {
     let args: Tuple = args.into();
diff --git a/test_app/README.md b/test_app/README.md
index 191d131681cf9706a2c75cbae3c2ab201e2227ab..e135a56850b9ac3eaa45e31a1f0d99f326c7f580 100644
--- a/test_app/README.md
+++ b/test_app/README.md
@@ -34,6 +34,8 @@ The `storage` role has the `insert_map(space, values_map)` function, which inser
 
 ## General observations
 
+`Sbroad` library uses internal lua functions in the cartridge executor and preloads them with `load_lua_extra_function` call in the `init` cartridge function.
+
 As the `sbroad` library caches the cluster cartridge schema internally, any `sbroad` function that is called checks the internal cluster schema, and if that is empty it loads the schema from the main app. If the app schema was updated then the internal cache needs to be cleared. To clear the cache we need to add the `invalidate_caching_schema` call to the `apply_config` cartridge function.
 
 ## Local load testing
diff --git a/test_app/app/roles/api.lua b/test_app/app/roles/api.lua
index 24357557115da6ef209a22b88eeee82e22d8e54b..28b15dd970981527eba2c70a9a8c1f8c08d5c410 100644
--- a/test_app/app/roles/api.lua
+++ b/test_app/app/roles/api.lua
@@ -88,6 +88,12 @@ local function init(opts) -- luacheck: no unused args
             if_not_exists = true, language = 'C' 
     })
 
+    box.schema.func.create('sbroad.load_lua_extra_function', {
+        if_not_exists = true, language = 'C'
+    })
+
+    box.func["sbroad.load_lua_extra_function"]:call({})
+
     return true
 end