diff --git a/src/luamod.lua b/src/luamod.lua
index 167472c963780e3c542982438eb04710daccb011..847c8b7fe5dffbce634110cd7ee567aa4c453da5 100644
--- a/src/luamod.lua
+++ b/src/luamod.lua
@@ -97,8 +97,7 @@ Params:
     2. password (string)
     3. opts (table)
         - if_not_exists (boolean), if true, do nothing if user with given name already exists
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -112,6 +111,9 @@ function pico.create_user(user, password, opts)
         box.internal.check_param(password, 'password', 'string')
         box.internal.check_param_table(opts, { if_not_exists = 'boolean', timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -145,7 +147,7 @@ function pico.create_user(user, password, opts)
         }
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 help.change_password = [[
@@ -166,8 +168,7 @@ Params:
     1. user (string), username
     2. password (string)
     3. opts (table)
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -181,6 +182,9 @@ function pico.change_password(user, password, opts)
         box.internal.check_param(password, 'password', 'string')
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -205,7 +209,7 @@ function pico.change_password(user, password, opts)
         }
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 help.drop_user = [[
@@ -227,8 +231,7 @@ Params:
     1. user (string), username
     2. opts (table)
         - if_exists (boolean), if true do nothing if user with given name doesn't exist
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -241,6 +244,9 @@ function pico.drop_user(user, opts)
         box.internal.check_param(user, 'user', 'string')
         box.internal.check_param_table(opts, { if_exists = 'boolean', timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -263,7 +269,7 @@ function pico.drop_user(user, opts)
         schema_version = next_schema_version(),
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 help.create_role = [[
@@ -281,8 +287,7 @@ Params:
     1. name (string), role name
     2. opts (table)
         - if_not_exists (boolean), if true, do nothing if role with given name already exists
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -295,6 +300,9 @@ function pico.create_role(role, opts)
         box.internal.check_param(role, 'role', 'string')
         box.internal.check_param_table(opts, { if_not_exists = 'boolean', timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -322,7 +330,7 @@ function pico.create_role(role, opts)
         }
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 help.drop_role = [[
@@ -340,8 +348,7 @@ Params:
     1. role (string), role name
     2. opts (table)
         - if_exists (boolean), if true do nothing if role with given name doesn't exist
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -354,6 +361,9 @@ function pico.drop_role(role, opts)
         box.internal.check_param(role, 'role', 'string')
         box.internal.check_param_table(opts, { if_exists = 'boolean', timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -376,7 +386,7 @@ function pico.drop_role(role, opts)
         schema_version = next_schema_version(),
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 -- A lookup map
@@ -571,8 +581,7 @@ Params:
         entire class of entities, see examples below.
 
     5. opts (table)
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -606,6 +615,9 @@ function pico.grant_privilege(grantee, privilege, object_type, object_name, opts
         box.internal.check_param(object_name, 'object_name', 'string')
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -645,7 +657,7 @@ function pico.grant_privilege(grantee, privilege, object_type, object_name, opts
         },
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 help.revoke_privilege = [[
@@ -678,8 +690,7 @@ Params:
         entire class of entities, see pico.help("pico.grant_privilege") for details.
 
     5. opts (table)
-        - timeout (number), wait for this many seconds for the proposed entry
-            to be applied locally, default: 3 seconds
+        - timeout (number), seconds
 
 Returns:
 
@@ -696,6 +707,9 @@ function pico.revoke_privilege(grantee, privilege, object_type, object_name, opt
         box.internal.check_param(object_name, 'object_name', 'string')
         box.internal.check_param_table(opts, { timeout = 'number' })
         opts = opts or {}
+        if not opts.timeout then
+            box.error(box.error.ILLEGAL_PARAMS, 'opts.timeout is mandatory')
+        end
     end)
     if not ok then
         return nil, err
@@ -735,7 +749,7 @@ function pico.revoke_privilege(grantee, privilege, object_type, object_name, opt
         },
     }
 
-    return pico._prepare_schema_change(op, opts.timeout or 3)
+    return pico._prepare_schema_change(op, opts.timeout)
 end
 
 help.drop_space = [[
diff --git a/test/int/test_acl.py b/test/int/test_acl.py
index d1c72d25294984d793c03c766d4cf6bf5d2ae788..4ebba6752fa1a99cd1041b41660496ead491364d 100644
--- a/test/int/test_acl.py
+++ b/test/int/test_acl.py
@@ -19,15 +19,15 @@ def test_acl_lua_api(cluster: Cluster):
         i1.call("pico.create_user", "Dave")
 
     # This is probably not ok.
-    i1.call("pico.create_user", "Dave", "")
+    i1.call("pico.create_user", "Dave", "", dict(timeout=3))
 
     # Already exists -> error.
     with pytest.raises(ReturnError, match="User 'Dave' already exists"):
-        i1.call("pico.create_user", "Dave", "")
+        i1.call("pico.create_user", "Dave", "", dict(timeout=3))
 
     # Role already exists -> error.
     with pytest.raises(ReturnError, match="Role 'super' already exists"):
-        i1.call("pico.create_user", "super", "")
+        i1.call("pico.create_user", "super", "", dict(timeout=3))
 
     #
     # pico.create_role
@@ -38,15 +38,15 @@ def test_acl_lua_api(cluster: Cluster):
         i1.call("pico.create_role")
 
     # Ok.
-    i1.call("pico.create_role", "Parent")
+    i1.call("pico.create_role", "Parent", dict(timeout=3))
 
     # Already exists -> error.
     with pytest.raises(ReturnError, match="Role 'Parent' already exists"):
-        i1.call("pico.create_role", "Parent")
+        i1.call("pico.create_role", "Parent", dict(timeout=3))
 
     # User already exists -> error.
     with pytest.raises(ReturnError, match="User 'Dave' already exists"):
-        i1.call("pico.create_role", "Dave")
+        i1.call("pico.create_role", "Dave", dict(timeout=3))
 
     #
     # pico.grant_privilege / pico.revoke_privilege parameter verification
@@ -57,27 +57,27 @@ def test_acl_lua_api(cluster: Cluster):
         with pytest.raises(ReturnError, match="grantee should be a string"):
             i1.call(f"pico.{f}")
 
-        # No such user -> error.
-        with pytest.raises(ReturnError, match="User 'User is not found' is not found"):
-            i1.call(f"pico.{f}", "User is not found", "execute", "universe")
-
         # No privilege -> error.
         with pytest.raises(ReturnError, match="privilege should be a string"):
             i1.call(f"pico.{f}", "Dave")
 
+        # No such user -> error.
+        with pytest.raises(ReturnError, match="User 'User is not found' is not found"):
+            i1.call(f"pico.{f}", "User is not found", "execute", "universe", None, dict(timeout=3))
+
         # No such privilege -> error.
         with pytest.raises(
             ReturnError,
             match=rf"unsupported privilege 'boogie', see pico.help\('{f}'\) for details",
         ):
-            i1.call(f"pico.{f}", "Dave", "boogie", "universe")
+            i1.call(f"pico.{f}", "Dave", "boogie", "universe", None, dict(timeout=3))
 
         # Comma separated list of privileges -> error.
         with pytest.raises(
             ReturnError,
             match=rf"unsupported privilege 'read,write', see pico.help\('{f}'\) for details",
         ):
-            i1.call(f"pico.{f}", "Dave", "read,write", "universe")
+            i1.call(f"pico.{f}", "Dave", "read,write", "universe", None, dict(timeout=3))
 
         # No object_type -> error.
         with pytest.raises(ReturnError, match="object_type should be a string"):
@@ -85,32 +85,32 @@ def test_acl_lua_api(cluster: Cluster):
 
         # No such object_type -> error.
         with pytest.raises(ReturnError, match="Unknown object type 'bible'"):
-            i1.call(f"pico.{f}", "Dave", "read", "bible")
+            i1.call(f"pico.{f}", "Dave", "read", "bible", None, dict(timeout=3))
 
         # Wrong combo -> error.
         with pytest.raises(ReturnError, match="Unsupported space privilege 'grant'"):
-            i1.call(f"pico.{f}", "Dave", "grant", "space")
+            i1.call(f"pico.{f}", "Dave", "grant", "space", None, dict(timeout=3))
 
         # No such role -> error.
         with pytest.raises(ReturnError, match="Role 'Joker' is not found"):
-            i1.call(f"pico.{f}", "Dave", "execute", "role", "Joker")
+            i1.call(f"pico.{f}", "Dave", "execute", "role", "Joker", dict(timeout=3))
 
     #
     # pico.grant_privilege semantics verification
     #
 
     # Grant privilege to user -> Ok.
-    i1.call("pico.grant_privilege", "Dave", "read", "space", "_pico_property")
+    i1.call("pico.grant_privilege", "Dave", "read", "space", "_pico_property", dict(timeout=3))
 
     # Already granted -> error.
     with pytest.raises(
         ReturnError,
         match="User 'Dave' already has read access on space '_pico_property'",
     ):
-        i1.call("pico.grant_privilege", "Dave", "read", "space", "_pico_property")
+        i1.call("pico.grant_privilege", "Dave", "read", "space", "_pico_property", dict(timeout=3))
 
     # Grant privilege to role -> Ok.
-    i1.call("pico.grant_privilege", "Parent", "write", "space", "_pico_property")
+    i1.call("pico.grant_privilege", "Parent", "write", "space", "_pico_property", dict(timeout=3))
 
     # Already granted -> error.
     # FIXME: tarantool says User instead of Role.
@@ -118,33 +118,33 @@ def test_acl_lua_api(cluster: Cluster):
         ReturnError,
         match="User 'Parent' already has write access on space '_pico_property'",
     ):
-        i1.call("pico.grant_privilege", "Parent", "write", "space", "_pico_property")
+        i1.call("pico.grant_privilege", "Parent", "write", "space", "_pico_property", dict(timeout=3))
 
     # Assign role to user -> Ok.
-    i1.call("pico.grant_privilege", "Dave", "execute", "role", "Parent")
+    i1.call("pico.grant_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3))
 
     # Already assigned role to user -> error.
     with pytest.raises(
         ReturnError, match="User 'Dave' already has execute access on role 'Parent'"
     ):
-        i1.call("pico.grant_privilege", "Dave", "execute", "role", "Parent")
+        i1.call("pico.grant_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3))
 
     #
     # pico.revoke_privilege semantics verification
     #
 
     # Revoke privilege to user -> Ok.
-    i1.call("pico.revoke_privilege", "Dave", "read", "space", "_pico_property")
+    i1.call("pico.revoke_privilege", "Dave", "read", "space", "_pico_property", dict(timeout=3))
 
     # Already revoked -> error.
     with pytest.raises(
         ReturnError,
         match="User 'Dave' does not have read access on space '_pico_property'",
     ):
-        i1.call("pico.revoke_privilege", "Dave", "read", "space", "_pico_property")
+        i1.call("pico.revoke_privilege", "Dave", "read", "space", "_pico_property", dict(timeout=3))
 
     # Revoke privilege to role -> Ok.
-    i1.call("pico.revoke_privilege", "Parent", "write", "space", "_pico_property")
+    i1.call("pico.revoke_privilege", "Parent", "write", "space", "_pico_property", dict(timeout=3))
 
     # Already revoked -> error.
     # FIXME: tarantool says User instead of Role.
@@ -152,16 +152,16 @@ def test_acl_lua_api(cluster: Cluster):
         ReturnError,
         match="User 'Parent' does not have write access on space '_pico_property'",
     ):
-        i1.call("pico.revoke_privilege", "Parent", "write", "space", "_pico_property")
+        i1.call("pico.revoke_privilege", "Parent", "write", "space", "_pico_property", dict(timeout=3))
 
     # Revoke role to user -> Ok.
-    i1.call("pico.revoke_privilege", "Dave", "execute", "role", "Parent")
+    i1.call("pico.revoke_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3))
 
     # Already revoked role to user -> error.
     with pytest.raises(
         ReturnError, match="User 'Dave' does not have execute access on role 'Parent'"
     ):
-        i1.call("pico.revoke_privilege", "Dave", "execute", "role", "Parent")
+        i1.call("pico.revoke_privilege", "Dave", "execute", "role", "Parent", dict(timeout=3))
 
     #
     # pico.drop_user
@@ -169,18 +169,18 @@ def test_acl_lua_api(cluster: Cluster):
 
     # No user -> error.
     with pytest.raises(ReturnError, match="user should be a string"):
-        i1.call("pico.drop_user")
+        i1.call("pico.drop_user", dict(timeout=3))
 
     # No such user -> error.
     with pytest.raises(ReturnError, match="User 'User is not found' is not found"):
-        i1.call("pico.drop_user", "User is not found")
+        i1.call("pico.drop_user", "User is not found", dict(timeout=3))
 
     # Ok.
-    i1.call("pico.drop_user", "Dave")
+    i1.call("pico.drop_user", "Dave", dict(timeout=3))
 
     # Repeat drop -> error.
     with pytest.raises(ReturnError, match="User 'Dave' is not found"):
-        i1.call("pico.drop_user", "Dave")
+        i1.call("pico.drop_user", "Dave", dict(timeout=3))
 
     #
     # pico.drop_role
@@ -192,14 +192,14 @@ def test_acl_lua_api(cluster: Cluster):
 
     # No such role -> error.
     with pytest.raises(ReturnError, match="Role 'Role is not found' is not found"):
-        i1.call("pico.drop_role", "Role is not found")
+        i1.call("pico.drop_role", "Role is not found", dict(timeout=3))
 
     # Ok.
-    i1.call("pico.drop_role", "Parent")
+    i1.call("pico.drop_role", "Parent", dict(timeout=3))
 
     # Repeat drop -> error.
     with pytest.raises(ReturnError, match="Role 'Parent' is not found"):
-        i1.call("pico.drop_role", "Parent")
+        i1.call("pico.drop_role", "Parent", dict(timeout=3))
 
     #
     # Options validation
@@ -219,6 +219,12 @@ def test_acl_lua_api(cluster: Cluster):
     ):
         i1.call("pico.create_user", "Dave", "pass", dict(timeout="3s"))
 
+    # No timeout -> error.
+    with pytest.raises(
+        ReturnError, match="opts.timeout is mandatory"
+    ):
+        i1.call("pico.create_user", "Dave", "pass")
+
 
 def test_acl_basic(cluster: Cluster):
     i1, *_ = cluster.deploy(instance_count=4, init_replication_factor=2)
@@ -235,7 +241,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Create user.
-    index = i1.call("pico.create_user", user, password)
+    index = i1.call("pico.create_user", user, password, dict(timeout=3))
     cluster.raft_wait_index(index)
     v += 1
 
@@ -270,11 +276,11 @@ def test_acl_basic(cluster: Cluster):
     # Grant some privileges.
     # Doing anything via remote function execution requires execute access
     # to the "universe"
-    index = i1.call("pico.grant_privilege", user, "execute", "universe")
+    index = i1.call("pico.grant_privilege", user, "execute", "universe", None, dict(timeout=3))
     cluster.raft_wait_index(index)
     v += 1
 
-    index = i1.call("pico.grant_privilege", user, "read", "space", "money")
+    index = i1.call("pico.grant_privilege", user, "read", "space", "money", dict(timeout=3))
     cluster.raft_wait_index(index)
     v += 1
 
@@ -320,7 +326,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Revoke the privilege.
-    index = i1.call("pico.revoke_privilege", user, "read", "space", "money")
+    index = i1.call("pico.revoke_privilege", user, "read", "space", "money", dict(timeout=3))
     cluster.raft_wait_index(index)
     v += 1
 
@@ -337,7 +343,7 @@ def test_acl_basic(cluster: Cluster):
     # Change user's password.
     old_password = password
     new_password = "$3kr3T"
-    index = i1.call("pico.change_password", user, new_password)
+    index = i1.call("pico.change_password", user, new_password, dict(timeout=3))
     cluster.raft_wait_index(index)
     v += 1
 
@@ -355,7 +361,7 @@ def test_acl_basic(cluster: Cluster):
     #
     #
     # Drop user.
-    index = i1.call("pico.drop_user", user)
+    index = i1.call("pico.drop_user", user, dict(timeout=3))
 
     for i in cluster.instances:
         i.raft_wait_index(index)
@@ -390,12 +396,12 @@ def test_acl_roles_basic(cluster: Cluster):
     password = "1234"
 
     # Create user.
-    index = i1.call("pico.create_user", user, password)
+    index = i1.call("pico.create_user", user, password, dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Doing anything via remote function execution requires execute access
     # to the "universe"
-    index = i1.call("pico.grant_privilege", user, "execute", "universe")
+    index = i1.call("pico.grant_privilege", user, "execute", "universe", None, dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Try reading from space on behalf of the user.
@@ -410,15 +416,15 @@ def test_acl_roles_basic(cluster: Cluster):
     #
     # Create role.
     role = "PropertyReader"
-    index = i1.call("pico.create_role", role)
+    index = i1.call("pico.create_role", role, dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Grant the role read access.
-    index = i1.call("pico.grant_privilege", role, "read", "space", "_pico_property")
+    index = i1.call("pico.grant_privilege", role, "read", "space", "_pico_property", dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Assign role to user.
-    index = i1.call("pico.grant_privilege", user, "execute", "role", role)
+    index = i1.call("pico.grant_privilege", user, "execute", "role", role, dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Try reading from space on behalf of the user again. Now succeed.
@@ -427,7 +433,7 @@ def test_acl_roles_basic(cluster: Cluster):
         assert len(rows) > 0
 
     # Revoke read access from the role.
-    index = i1.call("pico.revoke_privilege", role, "read", "space", "_pico_property")
+    index = i1.call("pico.revoke_privilege", role, "read", "space", "_pico_property", dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Try reading from space on behalf of the user yet again, which fails again.
@@ -439,7 +445,7 @@ def test_acl_roles_basic(cluster: Cluster):
             i.call("box.space._pico_property:select", user=user, password=password)
 
     # Drop the role.
-    index = i1.call("pico.drop_role", role)
+    index = i1.call("pico.drop_role", role, dict(timeout=3))
     cluster.raft_wait_index(index)
 
     # Nothing changed here.