diff --git a/src/box/alter.cc b/src/box/alter.cc
index 4ee8487dbbc192d5bf809b680a3ac0b5e0d24288..19db22a8d315909ab89825fde6a3f9947c09c3ca 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -3001,6 +3001,10 @@ user_def_new_from_tuple(struct tuple *tuple)
 		if (user_def_fill_auth_data(user, auth_data) != 0)
 			return NULL;
 	}
+	if (tuple_field_count(tuple) > BOX_USER_FIELD_LAST_MODIFIED &&
+	    tuple_field_u64(tuple, BOX_USER_FIELD_LAST_MODIFIED,
+			    &user->last_modified) != 0)
+		return NULL;
 	def_guard.is_active = false;
 	return user;
 }
diff --git a/src/box/bootstrap.snap b/src/box/bootstrap.snap
index 150881c170aab7b2c83ff23a8817e09db49f16c0..43701a0dbda46fc857228bee8d58fe35c23a2965 100644
Binary files a/src/box/bootstrap.snap and b/src/box/bootstrap.snap differ
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index ccec0990bfa1595a4985f803b1d9da69ba325699..cd06564e7b2d009fab7d7b4ec16495c63a02cbcb 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -5,6 +5,7 @@ local msgpack = require('msgpack')
 local fun = require('fun')
 local log = require('log')
 local buffer = require('buffer')
+local fiber = require('fiber')
 local session = box.session
 local internal = require('box.internal')
 local utf8 = require('utf8')
@@ -3391,7 +3392,9 @@ end
 local function chpasswd(uid, new_password)
     local _user = box.space[box.schema.USER_ID]
     check_password(new_password)
-    _user:update({uid}, {{"=", 5, prepare_auth_list(new_password)}})
+    _user:update({uid}, {{'=', 5, prepare_auth_list(new_password)},
+                         {'=', 6, {}},
+                         {'=', 7, math.floor(fiber.time())}})
 end
 
 box.schema.user.passwd = function(name, new_password)
@@ -3430,7 +3433,8 @@ box.schema.user.create = function(name, opts)
         auth_list = setmap({})
     end
     local _user = box.space[box.schema.USER_ID]
-    uid = _user:auto_increment{session.euid(), name, 'user', auth_list}.id
+    uid = _user:auto_increment{session.euid(), name, 'user', auth_list, {},
+                               math.floor(fiber.time())}.id
     -- grant role 'public' to the user
     box.schema.user.grant(uid, 'public')
     -- Grant privilege 'alter' on itself, so that it can
@@ -3697,7 +3701,8 @@ box.schema.role.create = function(name, opts)
         return
     end
     local _user = box.space[box.schema.USER_ID]
-    _user:auto_increment{session.euid(), name, 'role', setmap({})}
+    _user:auto_increment{session.euid(), name, 'role', setmap({}), {},
+                         math.floor(fiber.time())}
 end
 
 box.schema.role.drop = function(name, opts)
diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua
index cb6dfba24a3944f115cadb642406aa8613b80c59..2c7da702eb6b07a1c3fc21d02d1d37c6ddbc78ac 100644
--- a/src/box/lua/upgrade.lua
+++ b/src/box/lua/upgrade.lua
@@ -1333,9 +1333,28 @@ local function convert_sql_constraints_to_tuple_constraints()
     end
 end
 
+local function add_user_auth_history_and_last_modified()
+    log.info("add auth_history and last_modified fields to space _user")
+    local _space = box.space[box.schema.SPACE_ID]
+    local _user = box.space[box.schema.USER_ID]
+    local _vuser = box.space[box.schema.VUSER_ID]
+    for _, v in _user:pairs() do
+        if #v == 5 then
+            _user:update(v[1], {{'=', 6, {}}, {'=', 7, 0}})
+        end
+    end
+    local ops = {
+        {'=', '[7][6]', {name = 'auth_history', type = 'array'}},
+        {'=', '[7][7]', {name = 'last_modified', type = 'unsigned'}},
+    }
+    _space:update({_user.id}, ops)
+    _space:update({_vuser.id}, ops)
+end
+
 local function upgrade_to_2_11_0()
     revoke_write_access_on__collation_from_role_public()
     convert_sql_constraints_to_tuple_constraints()
+    add_user_auth_history_and_last_modified()
 end
 --------------------------------------------------------------------------------
 
diff --git a/src/box/schema_def.h b/src/box/schema_def.h
index cf7fc7ece80f2382e478ef648fd3182adb338881..39fd94fe3ff973a990cab7710a19932ef5264e4c 100644
--- a/src/box/schema_def.h
+++ b/src/box/schema_def.h
@@ -154,6 +154,8 @@ enum {
 	BOX_USER_FIELD_NAME = 2,
 	BOX_USER_FIELD_TYPE = 3,
 	BOX_USER_FIELD_AUTH = 4,
+	BOX_USER_FIELD_AUTH_HISTORY = 5,
+	BOX_USER_FIELD_LAST_MODIFIED = 6,
 };
 
 /** _priv fields. */
diff --git a/src/box/user_def.c b/src/box/user_def.c
index db3d719861148826666f44a9dc0d8df20c5b7ac6..4f5806e4273c44994cbcb2d3bc700712223b93a7 100644
--- a/src/box/user_def.c
+++ b/src/box/user_def.c
@@ -53,6 +53,7 @@ user_def_new(uint32_t uid, uint32_t owner, enum schema_object_type type,
 	def->owner = owner;
 	def->type = type;
 	def->auth = NULL;
+	def->last_modified = 0;
 	def->name = grp_alloc_create_str(&all, name, name_len);
 	assert(grp_alloc_size(&all) == 0);
 	return def;
diff --git a/src/box/user_def.h b/src/box/user_def.h
index efeb9774cdcfd5bdeebd9ec34166e9b61c9c84e2..7acc525b6af7b0e7a5eee3a0a8ca6b7d42cda82d 100644
--- a/src/box/user_def.h
+++ b/src/box/user_def.h
@@ -146,6 +146,11 @@ struct user_def {
 	 * reside in the user struct.
 	 */
 	struct authenticator *auth;
+	/**
+	 * Last modification timestamp (seconds since UNIX epoch)
+	 * or 0 if unknown.
+	 */
+	uint64_t last_modified;
 	/** User name - for error messages and debugging */
 	char *name;
 };
diff --git a/test/box-luatest/upgrade/2.10.4/00000000000000000009.snap b/test/box-luatest/upgrade/2.10.4/00000000000000000009.snap
new file mode 100644
index 0000000000000000000000000000000000000000..d21bba921962fc4a1602f651e9af35e1d361bebb
Binary files /dev/null and b/test/box-luatest/upgrade/2.10.4/00000000000000000009.snap differ
diff --git a/test/box-luatest/user_auth_history_last_modified_upgrade_test.lua b/test/box-luatest/user_auth_history_last_modified_upgrade_test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..d834907e3d250ed91ad8dfd8b4e766454187093f
--- /dev/null
+++ b/test/box-luatest/user_auth_history_last_modified_upgrade_test.lua
@@ -0,0 +1,99 @@
+local server = require('luatest.server')
+local t = require('luatest')
+
+local g = t.group()
+
+g.before_all(function(cg)
+    t.tarantool.skip_if_not_debug()
+    cg.server = server:new({
+        alias = 'master',
+        datadir = 'test/box-luatest/upgrade/2.10.4',
+        env = {ERRINJ_AUTO_UPGRADE = 'true'},
+    })
+    cg.server:start()
+end)
+
+g.after_all(function(cg)
+    cg.server:drop()
+end)
+
+g.test_upgrade = function(cg)
+    cg.server:exec(function()
+        local t = require('luatest')
+        local fiber = require('fiber')
+        t.assert_equals(box.space._user:select(), {
+            {0, 1, 'guest', 'user',
+             {['chap-sha1'] = 'vhvewKp0tNyweZQ+cFKAlsyphfg='}},
+            {1, 1, 'admin', 'user', {}},
+            {2, 1, 'public', 'role', {}},
+            {3, 1, 'replication', 'role', {}},
+            {31, 1, 'super', 'role', {}},
+            {32, 1, 'eve', 'user', {}},
+            {33, 1, 'bob', 'user',
+             {['chap-sha1'] = 'FOZVZ6vbUTXQz9mnCzAywXmknuc='}},
+            {34, 1, 'test', 'role', {}},
+        })
+        box.schema.user.create('alice')
+        box.schema.user.create('sarah', {password = 'SARAH'})
+        box.schema.user.passwd('bob', 'BOB')
+        box.schema.role.create('dev')
+        t.assert_equals(box.space._user:select(), {
+            {0, 1, 'guest', 'user',
+             {['chap-sha1'] = 'vhvewKp0tNyweZQ+cFKAlsyphfg='}},
+            {1, 1, 'admin', 'user', {}},
+            {2, 1, 'public', 'role', {}},
+            {3, 1, 'replication', 'role', {}},
+            {31, 1, 'super', 'role', {}},
+            {32, 1, 'eve', 'user', {}},
+            {33, 1, 'bob', 'user',
+             {['chap-sha1'] = 'Ll5w6uuDmXlEaz2b8kmjHZu1SLg='}, {},
+             box.space._user:get(33)[7]},
+            {34, 1, 'test', 'role', {}},
+            {35, 0, 'alice', 'user', {}, {},
+             box.space._user:get(35)[7]},
+            {36, 0, 'sarah', 'user',
+             {['chap-sha1'] = '973rCIFsYhe7gupdgOPCSJoPRNU='}, {},
+             box.space._user:get(36)[7]},
+            {37, 0, 'dev', 'role', {}, {},
+             box.space._user:get(37)[7]},
+        })
+        local time = fiber.time()
+        local margin = 60
+        t.assert_almost_equals(box.space._user:get(33)[7], time, margin)
+        t.assert_almost_equals(box.space._user:get(35)[7], time, margin)
+        t.assert_almost_equals(box.space._user:get(36)[7], time, margin)
+        t.assert_almost_equals(box.space._user:get(37)[7], time, margin)
+        box.schema.upgrade()
+        local format = {
+            {name = "id", type = "unsigned"},
+            {name = "owner", type = "unsigned"},
+            {name = "name", type = "string"},
+            {name = "type", type = "string"},
+            {name = "auth", type = "map"},
+            {name = "auth_history", type = "array"},
+            {name = "last_modified", type = "unsigned"},
+        }
+        t.assert_equals(box.space._user:format(), format)
+        t.assert_equals(box.space._vuser:format(), format)
+        t.assert_equals(box.space._user:select(), {
+            {0, 1, 'guest', 'user',
+             {['chap-sha1'] = 'vhvewKp0tNyweZQ+cFKAlsyphfg='}, {}, 0},
+            {1, 1, 'admin', 'user', {}, {}, 0},
+            {2, 1, 'public', 'role', {}, {}, 0},
+            {3, 1, 'replication', 'role', {}, {}, 0},
+            {31, 1, 'super', 'role', {}, {}, 0},
+            {32, 1, 'eve', 'user', {}, {}, 0},
+            {33, 1, 'bob', 'user',
+             {['chap-sha1'] = 'Ll5w6uuDmXlEaz2b8kmjHZu1SLg='}, {},
+             box.space._user:get(33)[7]},
+            {34, 1, 'test', 'role', {}, {}, 0},
+            {35, 0, 'alice', 'user', {}, {},
+             box.space._user:get(35)[7]},
+            {36, 0, 'sarah', 'user',
+             {['chap-sha1'] = '973rCIFsYhe7gupdgOPCSJoPRNU='}, {},
+             box.space._user:get(36)[7]},
+            {37, 0, 'dev', 'role', {}, {},
+             box.space._user:get(37)[7]},
+        })
+    end)
+end
diff --git a/test/box-py/bootstrap.result b/test/box-py/bootstrap.result
index d24b5f0474a3ba15f17595c0fd78637b314ddd49..13101dec7caa8707794dc708ae4477aa699fb260 100644
--- a/test/box-py/bootstrap.result
+++ b/test/box-py/bootstrap.result
@@ -73,10 +73,12 @@ box.space._space:select{}
         'type': 'string'}, {'name': 'last_altered', 'type': 'string'}]]
   - [304, 1, '_user', 'memtx', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'owner',
         'type': 'unsigned'}, {'name': 'name', 'type': 'string'}, {'name': 'type',
-        'type': 'string'}, {'name': 'auth', 'type': 'map'}]]
+        'type': 'string'}, {'name': 'auth', 'type': 'map'}, {'name': 'auth_history',
+        'type': 'array'}, {'name': 'last_modified', 'type': 'unsigned'}]]
   - [305, 1, '_vuser', 'sysview', 0, {}, [{'name': 'id', 'type': 'unsigned'}, {'name': 'owner',
         'type': 'unsigned'}, {'name': 'name', 'type': 'string'}, {'name': 'type',
-        'type': 'string'}, {'name': 'auth', 'type': 'map'}]]
+        'type': 'string'}, {'name': 'auth', 'type': 'map'}, {'name': 'auth_history',
+        'type': 'array'}, {'name': 'last_modified', 'type': 'unsigned'}]]
   - [312, 1, '_priv', 'memtx', 0, {}, [{'name': 'grantor', 'type': 'unsigned'}, {
         'name': 'grantee', 'type': 'unsigned'}, {'name': 'object_type', 'type': 'string'},
       {'name': 'object_id', 'type': 'scalar'}, {'name': 'privilege', 'type': 'unsigned'}]]
@@ -166,11 +168,11 @@ box.space._index:select{}
 ...
 box.space._user:select{}
 ---
-- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}]
-  - [1, 1, 'admin', 'user', {}]
-  - [2, 1, 'public', 'role', {}]
-  - [3, 1, 'replication', 'role', {}]
-  - [31, 1, 'super', 'role', {}]
+- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}, [], 0]
+  - [1, 1, 'admin', 'user', {}, [], 0]
+  - [2, 1, 'public', 'role', {}, [], 0]
+  - [3, 1, 'replication', 'role', {}, [], 0]
+  - [31, 1, 'super', 'role', {}, [], 0]
 ...
 for _, v in box.space._func:pairs{} do r = {} table.insert(r, v:update({{"=", 18, ""}, {"=", 19, ""}})) return r end
 ---
diff --git a/test/box/access.result b/test/box/access.result
index f70289caf4f8a0c35717d322f21060cde520f2b8..8148fd97d4daddf7af6e106445c4d580e8c08c20 100644
--- a/test/box/access.result
+++ b/test/box/access.result
@@ -74,6 +74,21 @@ test_run:cmd("setopt delimiter ';'")
 ---
 - true
 ...
+function delete_user(uid_or_name)
+    local t
+    if type(uid_or_name) == 'string' then
+        t = box.space._user.index.name:delete({uid_or_name})
+    else
+        t = box.space._user:delete({uid_or_name})
+    end
+    if box.tuple.is(t) and type(t[7]) == 'number' then
+        t = t:totable()
+        t[7] = 0
+    end
+    return t
+end;
+---
+...
 function usermax()
     local i = 1
     while true do
@@ -125,14 +140,14 @@ box.schema.func.create('dummy')
 session.su('admin')
 ---
 ...
-box.space['_user']:delete{uid}
+delete_user(uid)
 ---
 - error: 'Failed to drop user or role ''rich'': the user has objects'
 ...
 box.schema.func.drop('dummy')
 ---
 ...
-box.space['_user']:delete{uid}
+delete_user(uid)
 ---
 - error: 'Failed to drop user or role ''rich'': the user has objects'
 ...
@@ -155,9 +170,9 @@ box.schema.user.disable("rich")
 box.schema.user.disable("rich")
 ---
 ...
-box.space['_user']:delete{uid}
+delete_user(uid)
 ---
-- [33, 1, 'rich', 'user', {}]
+- [33, 1, 'rich', 'user', {}, [], 0]
 ...
 box.schema.user.drop('test')
 ---
@@ -353,6 +368,48 @@ box.snapshot()
 - ok
 ...
 test_run:cmd('restart server default')
+test_run:cmd("setopt delimiter ';'")
+---
+- true
+...
+function delete_user(uid_or_name)
+    local t
+    if type(uid_or_name) == 'string' then
+        t = box.space._user.index.name:delete({uid_or_name})
+    else
+        t = box.space._user:delete({uid_or_name})
+    end
+    if box.tuple.is(t) and type(t[7]) == 'number' then
+        t = t:totable()
+        t[7] = 0
+    end
+    return t
+end;
+---
+...
+function select_user(uid_or_name)
+    local ret
+    if type(uid_or_name) == 'string' then
+        ret = box.space._user.index.name:select({uid_or_name})
+    else
+        ret = box.space._user:select({uid_or_name})
+    end
+    local ret2 = {}
+    for _, t in ipairs(ret) do
+        if box.tuple.is(t) and type(t[7]) == 'number' then
+            t = t:totable()
+            t[7] = 0
+        end
+        table.insert(ret2, t)
+    end
+    return ret2
+end;
+---
+...
+test_run:cmd("setopt delimiter ''");
+---
+- true
+...
 net = require('net.box')
 ---
 ...
@@ -449,11 +506,11 @@ box.schema.user.drop('grantor')
 session.su('guest')
 ---
 ...
-box.space._user:select{0}
+select_user(0)
 ---
 - error: Read access to space '_user' is denied for user 'guest'
 ...
-box.space._user:select{1}
+select_user(1)
 ---
 - error: Read access to space '_user' is denied for user 'guest'
 ...
@@ -467,9 +524,9 @@ session.su('admin')
 box.schema.user.create('user1')
 ---
 ...
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 ---
-- - [32, 1, 'user1', 'user', {}]
+- - [32, 1, 'user1', 'user', {}, [], 0]
 ...
 session.su('user1')
 ---
@@ -480,16 +537,16 @@ box.schema.user.passwd('new_password')
 session.su('admin')
 ---
 ...
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 ---
-- - [32, 1, 'user1', 'user', {'chap-sha1': 'CRO/LiziDOIb+xlhrxJNSSBFjl8='}]
+- - [32, 1, 'user1', 'user', {'chap-sha1': 'CRO/LiziDOIb+xlhrxJNSSBFjl8='}, [], 0]
 ...
 box.schema.user.passwd('user1', 'extra_new_password')
 ---
 ...
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 ---
-- - [32, 1, 'user1', 'user', {'chap-sha1': 'nMc3F1oaUtz37IYbgGYYPZawmfE='}]
+- - [32, 1, 'user1', 'user', {'chap-sha1': 'nMc3F1oaUtz37IYbgGYYPZawmfE='}, [], 0]
 ...
 box.schema.user.passwd('invalid_user', 'some_password')
 ---
@@ -513,7 +570,7 @@ session.su('admin')
 box.schema.user.drop('user1')
 ---
 ...
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 ---
 - []
 ...
@@ -595,11 +652,11 @@ box.space._priv:select{id}
 utils = require('utils')
 ---
 ...
-box.space._user:insert{10, 1, 'name', 'strange-object-type', utils.setmap({})}
+box.space._user:insert{10, 1, 'name', 'strange-object-type', utils.setmap({}), {}, 0}
 ---
 - error: 'Failed to create user ''name'': unknown user type'
 ...
-box.space._user:insert{10, 1, 'name', 'role', utils.setmap{'password'}}
+box.space._user:insert{10, 1, 'name', 'role', utils.setmap{'password'}, {}, 0}
 ---
 - error: 'Failed to create role ''name'': authentication data can not be set for a
     role'
@@ -806,11 +863,11 @@ box.schema.role.drop('guest')
 ---
 - error: Role 'guest' is not found
 ...
-box.space._user.index.name:delete{'guest'}
+delete_user('guest')
 ---
 - error: 'Failed to drop user or role ''guest'': the user or the role is a system'
 ...
-box.space._user:delete{box.schema.GUEST_ID}
+delete_user(box.schema.GUEST_ID)
 ---
 - error: 'Failed to drop user or role ''guest'': the user or the role is a system'
 ...
@@ -826,11 +883,11 @@ box.schema.role.drop('admin')
 ---
 - error: Role 'admin' is not found
 ...
-box.space._user.index.name:delete{'admin'}
+delete_user('admin')
 ---
 - error: 'Failed to drop user or role ''admin'': the user or the role is a system'
 ...
-box.space._user:delete{box.schema.ADMIN_ID}
+delete_user(box.schema.ADMIN_ID)
 ---
 - error: 'Failed to drop user or role ''admin'': the user or the role is a system'
 ...
@@ -846,11 +903,11 @@ box.schema.role.drop('public')
 ---
 - error: 'Failed to drop user or role ''public'': the user or the role is a system'
 ...
-box.space._user.index.name:delete{'public'}
+delete_user('public')
 ---
 - error: 'Failed to drop user or role ''public'': the user or the role is a system'
 ...
-box.space._user:delete{box.schema.PUBLIC_ROLE_ID}
+delete_user(box.schema.PUBLIC_ROLE_ID)
 ---
 - error: 'Failed to drop user or role ''public'': the user or the role is a system'
 ...
@@ -866,11 +923,11 @@ box.schema.user.drop('super')
 ---
 - error: User 'super' is not found
 ...
-box.space._user.index.name:delete{'super'}
+delete_user('super')
 ---
 - error: 'Failed to drop user or role ''super'': the user or the role is a system'
 ...
-box.space._user:delete{box.schema.SUPER_ROLE_ID}
+delete_user(box.schema.SUPER_ROLE_ID)
 ---
 - error: 'Failed to drop user or role ''super'': the user or the role is a system'
 ...
@@ -2035,16 +2092,16 @@ box.schema.user.grant("user1", "write", "space", "_user")
 box.schema.user.grant("user1", "read", "space", "_user")
 ---
 ...
-box.space._user:select{}
+select_user()
 ---
-- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}]
-  - [1, 1, 'admin', 'user', {}]
-  - [2, 1, 'public', 'role', {}]
-  - [3, 1, 'replication', 'role', {}]
-  - [31, 1, 'super', 'role', {}]
-  - [32, 1, 'user1', 'user', {}]
-  - [33, 1, 'user2', 'user', {}]
-  - [34, 1, 'user3', 'user', {}]
+- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}, [], 0]
+  - [1, 1, 'admin', 'user', {}, [], 0]
+  - [2, 1, 'public', 'role', {}, [], 0]
+  - [3, 1, 'replication', 'role', {}, [], 0]
+  - [31, 1, 'super', 'role', {}, [], 0]
+  - [32, 1, 'user1', 'user', {}, [], 0]
+  - [33, 1, 'user2', 'user', {}, [], 0]
+  - [34, 1, 'user3', 'user', {}, [], 0]
 ...
 box.session.su("user1")
 ---
@@ -2060,16 +2117,16 @@ box.schema.user.passwd("user2", "abcd")
 box.session.su("admin")
 ---
 ...
-box.space._user:select{}
+select_user()
 ---
-- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}]
-  - [1, 1, 'admin', 'user', {}]
-  - [2, 1, 'public', 'role', {}]
-  - [3, 1, 'replication', 'role', {}]
-  - [31, 1, 'super', 'role', {}]
-  - [32, 1, 'user1', 'user', {'chap-sha1': 'oVTFJWXp5/lL/Aih/nAmJO2O/9o='}]
-  - [33, 1, 'user2', 'user', {}]
-  - [34, 1, 'user3', 'user', {}]
+- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}, [], 0]
+  - [1, 1, 'admin', 'user', {}, [], 0]
+  - [2, 1, 'public', 'role', {}, [], 0]
+  - [3, 1, 'replication', 'role', {}, [], 0]
+  - [31, 1, 'super', 'role', {}, [], 0]
+  - [32, 1, 'user1', 'user', {'chap-sha1': 'oVTFJWXp5/lL/Aih/nAmJO2O/9o='}, [], 0]
+  - [33, 1, 'user2', 'user', {}, [], 0]
+  - [34, 1, 'user3', 'user', {}, [], 0]
 ...
 box.schema.user.grant("user1", "alter", "user", "user2")
 ---
@@ -2088,16 +2145,16 @@ box.schema.user.passwd("user3", "qewr")
 box.session.su("admin")
 ---
 ...
-box.space._user:select{}
+select_user()
 ---
-- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}]
-  - [1, 1, 'admin', 'user', {}]
-  - [2, 1, 'public', 'role', {}]
-  - [3, 1, 'replication', 'role', {}]
-  - [31, 1, 'super', 'role', {}]
-  - [32, 1, 'user1', 'user', {'chap-sha1': 'oVTFJWXp5/lL/Aih/nAmJO2O/9o='}]
-  - [33, 1, 'user2', 'user', {'chap-sha1': 'oVTFJWXp5/lL/Aih/nAmJO2O/9o='}]
-  - [34, 1, 'user3', 'user', {}]
+- - [0, 1, 'guest', 'user', {'chap-sha1': 'vhvewKp0tNyweZQ+cFKAlsyphfg='}, [], 0]
+  - [1, 1, 'admin', 'user', {}, [], 0]
+  - [2, 1, 'public', 'role', {}, [], 0]
+  - [3, 1, 'replication', 'role', {}, [], 0]
+  - [31, 1, 'super', 'role', {}, [], 0]
+  - [32, 1, 'user1', 'user', {'chap-sha1': 'oVTFJWXp5/lL/Aih/nAmJO2O/9o='}, [], 0]
+  - [33, 1, 'user2', 'user', {'chap-sha1': 'oVTFJWXp5/lL/Aih/nAmJO2O/9o='}, [], 0]
+  - [34, 1, 'user3', 'user', {}, [], 0]
 ...
 box.schema.user.drop("user1")
 ---
diff --git a/test/box/access.test.lua b/test/box/access.test.lua
index b9608f2142bedf30f5bd3ea4b50e805aa655a2f3..9c81b11aa86f4b042d59a637a78ced33591c4737 100644
--- a/test/box/access.test.lua
+++ b/test/box/access.test.lua
@@ -33,6 +33,19 @@ session.su('admin')
 box.schema.user.grant('test', 'write', 'space', '_space')
 
 test_run:cmd("setopt delimiter ';'")
+function delete_user(uid_or_name)
+    local t
+    if type(uid_or_name) == 'string' then
+        t = box.space._user.index.name:delete({uid_or_name})
+    else
+        t = box.space._user:delete({uid_or_name})
+    end
+    if box.tuple.is(t) and type(t[7]) == 'number' then
+        t = t:totable()
+        t[7] = 0
+    end
+    return t
+end;
 function usermax()
     local i = 1
     while true do
@@ -57,9 +70,9 @@ session.su('rich')
 uid = session.uid()
 box.schema.func.create('dummy')
 session.su('admin')
-box.space['_user']:delete{uid}
+delete_user(uid)
 box.schema.func.drop('dummy')
-box.space['_user']:delete{uid}
+delete_user(uid)
 box.schema.user.revoke('rich', 'public')
 box.schema.user.revoke('rich', 'read,write', 'space', '_func')
 box.schema.user.revoke('rich', 'alter', 'user', 'rich')
@@ -67,7 +80,7 @@ box.schema.user.revoke('rich', 'create', 'function')
 box.schema.user.disable("rich")
 -- test double disable is a no op
 box.schema.user.disable("rich")
-box.space['_user']:delete{uid}
+delete_user(uid)
 box.schema.user.drop('test')
 
 -- gh-944 name is too long
@@ -156,6 +169,38 @@ box.schema.user.grant('testus', 'write', 'space', 'admin_space')
 s:drop()
 box.snapshot()
 test_run:cmd('restart server default')
+test_run:cmd("setopt delimiter ';'")
+function delete_user(uid_or_name)
+    local t
+    if type(uid_or_name) == 'string' then
+        t = box.space._user.index.name:delete({uid_or_name})
+    else
+        t = box.space._user:delete({uid_or_name})
+    end
+    if box.tuple.is(t) and type(t[7]) == 'number' then
+        t = t:totable()
+        t[7] = 0
+    end
+    return t
+end;
+function select_user(uid_or_name)
+    local ret
+    if type(uid_or_name) == 'string' then
+        ret = box.space._user.index.name:select({uid_or_name})
+    else
+        ret = box.space._user:select({uid_or_name})
+    end
+    local ret2 = {}
+    for _, t in ipairs(ret) do
+        if box.tuple.is(t) and type(t[7]) == 'number' then
+            t = t:totable()
+            t[7] = 0
+        end
+        table.insert(ret2, t)
+    end
+    return ret2
+end;
+test_run:cmd("setopt delimiter ''");
 net = require('net.box')
 box.schema.user.drop('testus')
 -- ------------------------------------------------------------
@@ -199,21 +244,21 @@ box.schema.user.drop('grantor')
 -- guest can't read _user table, add a test case
 -- ----------------------------------------------------------
 session.su('guest')
-box.space._user:select{0}
-box.space._user:select{1}
+select_user(0)
+select_user(1)
 session.su('admin')
 -- ----------------------------------------------------------
 -- A test case for gh-358 Change user does not work from lua
 -- Correct the update syntax in schema.lua
 -- ----------------------------------------------------------
 box.schema.user.create('user1')
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 session.su('user1')
 box.schema.user.passwd('new_password')
 session.su('admin')
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 box.schema.user.passwd('user1', 'extra_new_password')
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 box.schema.user.passwd('invalid_user', 'some_password')
 box.schema.user.passwd()
 session.su('user1')
@@ -221,7 +266,7 @@ session.su('user1')
 box.schema.user.passwd('admin', 'xxx')
 session.su('admin')
 box.schema.user.drop('user1')
-box.space._user.index.name:select{'user1'}
+select_user('user1')
 -- ----------------------------------------------------------
 -- A test case for gh-421 Granting a privilege revokes an
 -- existing grant
@@ -246,8 +291,8 @@ box.space._priv:select{id}
 -- Be a bit more rigorous in what is accepted in space _user
 -- -----------------------------------------------------------
 utils = require('utils')
-box.space._user:insert{10, 1, 'name', 'strange-object-type', utils.setmap({})}
-box.space._user:insert{10, 1, 'name', 'role', utils.setmap{'password'}}
+box.space._user:insert{10, 1, 'name', 'strange-object-type', utils.setmap({}), {}, 0}
+box.space._user:insert{10, 1, 'name', 'role', utils.setmap{'password'}, {}, 0}
 session = nil
 -- -----------------------------------------------------------
 -- admin can't manage grants on not owned objects
@@ -317,23 +362,23 @@ box.schema.user.passwd('guest', 'sesame')
 -- gh-1205 box.schema.user.info fails
 box.schema.user.drop('guest')
 box.schema.role.drop('guest')
-box.space._user.index.name:delete{'guest'}
-box.space._user:delete{box.schema.GUEST_ID}
+delete_user('guest')
+delete_user(box.schema.GUEST_ID)
 #box.schema.user.info('guest') > 0
 box.schema.user.drop('admin')
 box.schema.role.drop('admin')
-box.space._user.index.name:delete{'admin'}
-box.space._user:delete{box.schema.ADMIN_ID}
+delete_user('admin')
+delete_user(box.schema.ADMIN_ID)
 #box.schema.user.info('admin') > 0
 box.schema.user.drop('public')
 box.schema.role.drop('public')
-box.space._user.index.name:delete{'public'}
-box.space._user:delete{box.schema.PUBLIC_ROLE_ID}
+delete_user('public')
+delete_user(box.schema.PUBLIC_ROLE_ID)
 #box.schema.role.info('public') > 0
 box.schema.role.drop('super')
 box.schema.user.drop('super')
-box.space._user.index.name:delete{'super'}
-box.space._user:delete{box.schema.SUPER_ROLE_ID}
+delete_user('super')
+delete_user(box.schema.SUPER_ROLE_ID)
 #box.schema.role.info('super') > 0
 
 -- gh-944 name is too long
@@ -785,20 +830,20 @@ box.schema.user.create("user2")
 box.schema.user.create("user3")
 box.schema.user.grant("user1", "write", "space", "_user")
 box.schema.user.grant("user1", "read", "space", "_user")
-box.space._user:select{}
+select_user()
 box.session.su("user1")
 -- can alter itself, but can't alter others without privileges.
 box.schema.user.passwd("user1", "abcd")
 box.schema.user.passwd("user2", "abcd")
 box.session.su("admin")
-box.space._user:select{}
+select_user()
 box.schema.user.grant("user1", "alter", "user", "user2")
 box.session.su("user1")
 box.schema.user.passwd("user2", "abcd")
 -- still fails
 box.schema.user.passwd("user3", "qewr")
 box.session.su("admin")
-box.space._user:select{}
+select_user()
 box.schema.user.drop("user1")
 box.schema.user.drop("user2")
 box.schema.user.drop("user3")
diff --git a/test/box/access_bin.result b/test/box/access_bin.result
index 7c720192ffac9a2deb0d2c520ec5ca625cd41abf..3028a5f1ea85ac86c33caa4550a882a27ac39d59 100644
--- a/test/box/access_bin.result
+++ b/test/box/access_bin.result
@@ -210,7 +210,7 @@ c:close()
 ...
 box.space._user:replace(u)
 ---
-- [1, 1, 'admin', 'user', {}]
+- [1, 1, 'admin', 'user', {}, [], 0]
 ...
 --
 -- gh-2763: test that universal access of an authenticated session
diff --git a/test/box/access_misc.result b/test/box/access_misc.result
index 1678641df389a191c63c15f1edde5b050c741131..34606bf2b89f2493ae9b6b3b579ea7308590ca0c 100644
--- a/test/box/access_misc.result
+++ b/test/box/access_misc.result
@@ -270,7 +270,7 @@ box.space.admin_space:select()
 ...
 box.space._user:select(1)
 ---
-- - [1, 1, 'admin', 'user', {}]
+- - [1, 1, 'admin', 'user', {}, [], 0]
 ...
 box.space._space:select(280)
 ---
@@ -367,7 +367,7 @@ box.space._user:select(1)
 ---
 - error: Read access to space '_user' is denied for user 'testuser'
 ...
-uid = box.space._user:insert{maxuid+1, session.uid(), 'someone', 'user', EMPTY_MAP}[1]
+uid = box.space._user:insert{maxuid+1, session.uid(), 'someone', 'user', EMPTY_MAP, {}, 0}[1]
 ---
 ...
 _ = box.space._user:delete(uid)
@@ -378,7 +378,7 @@ session.su('admin')
 ...
 box.space._user:select(1)
 ---
-- - [1, 1, 'admin', 'user', {}]
+- - [1, 1, 'admin', 'user', {}, [], 0]
 ...
 _ = box.space._user:delete(testuser_uid)
 ---
@@ -402,7 +402,7 @@ _  = box.space._user:delete(2)
 ...
 box.space._user:select(1)
 ---
-- - [1, 1, 'admin', 'user', {}]
+- - [1, 1, 'admin', 'user', {}, [], 0]
 ...
 box.space._user:insert{uid, session.uid(), 'someone2', 'user'}
 ---
diff --git a/test/box/access_misc.test.lua b/test/box/access_misc.test.lua
index 683babd7cd045c99a924d90a7001f5ff9c8d7477..28df5263c739937ebe6ea98a7bba141770e4fadd 100644
--- a/test/box/access_misc.test.lua
+++ b/test/box/access_misc.test.lua
@@ -152,7 +152,7 @@ session.su('testuser')
 testuser_uid = session.uid()
 _ = box.space._user:delete(2)
 box.space._user:select(1)
-uid = box.space._user:insert{maxuid+1, session.uid(), 'someone', 'user', EMPTY_MAP}[1]
+uid = box.space._user:insert{maxuid+1, session.uid(), 'someone', 'user', EMPTY_MAP, {}, 0}[1]
 _ = box.space._user:delete(uid)
 
 session.su('admin')