diff --git a/src/box/alter.cc b/src/box/alter.cc
index 1a46a8177313f7c76d4f24206d95ded54ba683c0..4938b0d223221330aecd8d3f3da0d986d21ada22 100644
--- a/src/box/alter.cc
+++ b/src/box/alter.cc
@@ -260,7 +260,8 @@ alter_space_commit(struct trigger *trigger, void * /* event */)
 			space_swap_index(alter->old_space,
 					 alter->new_space,
 					 index_id(old_index),
-					 index_id(new_index));
+					 index_id(new_index),
+					 false);
 		}
 	}
 	/*
@@ -563,7 +564,7 @@ ModifyIndex::commit(struct alter_space *alter)
 {
 	/* Move the old index to the new place but preserve */
 	space_swap_index(alter->old_space, alter->new_space,
-			 old_key_def->iid, new_key_def->iid);
+			 old_key_def->iid, new_key_def->iid, true);
 }
 
 ModifyIndex::~ModifyIndex()
diff --git a/src/box/box_lua.cc b/src/box/box_lua.cc
index 01959b2f5ae5f75abef5b9aa2887dba279b7567e..868ec4fd93724fde3d6a7162a5fc628ba87a235f 100644
--- a/src/box/box_lua.cc
+++ b/src/box/box_lua.cc
@@ -714,7 +714,7 @@ static int
 lbox_index_tostring(struct lua_State *L)
 {
 	Index *index = lua_checkindex(L, 1);
-	lua_pushfstring(L, "index %d", (int) index_id(index));
+	lua_pushfstring(L, " index %d", (int) index_id(index));
 	return 1;
 }
 
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index 07d4b248261e3bcb41ba65c1cfe91f83926e5488..f224c7d013743c460a2f4d5c6ed2684ce458b096 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -45,7 +45,7 @@ key_def_new(uint32_t space_id, uint32_t iid, const char *name,
 		tnt_raise(LoggedError, ER_MEMORY_ISSUE,
 			  sz, "struct key_def", "malloc");
 	}
-	int n = snprintf(def->name, sizeof(def->name) - 1, "%s", name);
+	int n = snprintf(def->name, sizeof(def->name), "%s", name);
 	if (n >= sizeof(def->name)) {
 		free(def);
 		tnt_raise(LoggedError, ER_MODIFY_INDEX,
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index af74cdf35872c55bf07a1ed443f0eab5de575b29..744a4fb7fdeca3110e5343ab97b741342624b17f 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -93,7 +93,29 @@ box.schema.index.drop = function(space_id, index_id)
 end
 box.schema.index.rename = function(space_id, index_id, name)
     local _index = box.space[box.schema.INDEX_ID]
-    _index:update({space_id, index_id}, "=p", 3, name)
+    _index:update({space_id, index_id}, "=p", 2, name)
+end
+box.schema.index.alter = function(space_id, index_id, options)
+    if options == nil then
+        return
+    end
+    local ops = ""
+    local args = {}
+    local function add_op(op, opno)
+        if op then
+            ops = ops.."=p"
+            table.insert(args, opno)
+            table.insert(args, op)
+        end
+    end
+    add_op(options.id, 1)
+    add_op(options.name, 2)
+    add_op(options.type, 3)
+    if options.unique ~= nil then
+        add_op(options.unique and 1 or 0, 4)
+    end
+    local _index = box.space[box.schema.INDEX_ID]
+    _index:update({space_id, index_id}, ops, unpack(args))
 end
 
 function box.schema.space.bless(space)
@@ -165,6 +187,12 @@ function box.schema.space.bless(space)
     index_mt.drop = function(index)
         return box.schema.index.drop(index.n, index.id)
     end
+    index_mt.rename = function(index, name)
+        return box.schema.index.rename(index.n, index.id, name)
+    end
+    index_mt.alter= function(index, options)
+        return box.schema.index.alter(index.n, index.id, options)
+    end
     --
     local space_mt = {}
     space_mt.len = function(space) return space.index[0]:len() end
diff --git a/src/box/space.cc b/src/box/space.cc
index 849053f1ffa54009e35f79799a66b63710a17e42..644f279fe105a2954a7ae6d811cf6fdc8978f01c 100644
--- a/src/box/space.cc
+++ b/src/box/space.cc
@@ -307,11 +307,17 @@ space_dump_def(const struct space *space, struct rlist *key_list)
 
 void
 space_swap_index(struct space *lhs, struct space *rhs, uint32_t lhs_id,
-		 uint32_t rhs_id)
+		 uint32_t rhs_id, bool keep_key_def)
 {
 	Index *tmp = lhs->index_map[lhs_id];
 	lhs->index_map[lhs_id] = rhs->index_map[rhs_id];
 	rhs->index_map[rhs_id] = tmp;
+	if (keep_key_def) {
+		struct key_def *tmp = lhs->index_map[lhs_id]->key_def;
+		lhs->index_map[lhs_id]->key_def =
+			rhs->index_map[rhs_id]->key_def;
+		rhs->index_map[rhs_id]->key_def = tmp;
+	}
 }
 
 extern "C" void
diff --git a/src/box/space.h b/src/box/space.h
index 4932abf478943d2b192337da9ec126d81a178056..98ba9fb211440270bbd56e56e645a9514ce6810e 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -259,7 +259,7 @@ space_dump_def(const struct space *space, struct rlist *key_list);
  */
 void
 space_swap_index(struct space *lhs, struct space *rhs, uint32_t lhs_id,
-		 uint32_t rhs_id);
+		 uint32_t rhs_id, bool keep_key_def);
 
 /** Rebuild index map in a space after a series of swap index. */
 void
diff --git a/test/box/alter_limits.result b/test/box/alter_limits.result
index 0d958152857e473625e986c6e107cfc23e9cae98..85dbf7a9cbe6550c21167b07ffde72606c124e7b 100644
--- a/test/box/alter_limits.result
+++ b/test/box/alter_limits.result
@@ -133,7 +133,7 @@ s:select(0)
 ...
 s:select_range(0, 0, 0)
 ---
-- error: '[string "-- schema.lua (internal file)..."]:174: attempt to index a nil
+- error: '[string "-- schema.lua (internal file)..."]:202: attempt to index a nil
     value'
 ...
 s:delete(0)
@@ -504,12 +504,169 @@ s:drop()
 ---
 ...
 -- index name, name manipulation
--- box.schema.create_space(string.rep('t', box.schema.NAME_MAX)..'_')
--- s = box.schema.create_space(string.rep('t', box.schema.NAME_MAX - 1)..'_')
--- s.name
--- s:drop()
--- s = box.schema.create_space(string.rep('t', box.schema.NAME_MAX - 2)..'_')
+s = box.schema.create_space('test')
+---
+...
+s:create_index('primary', 'hash')
+---
+...
+-- space cache is updated correctly
+s.index[0].name
+---
+- primary
+...
+s.index[0].id
+---
+- 0
+...
+s.index[0].type
+---
+- HASH
+...
+s.index['primary'].name
+---
+- primary
+...
+s.index['primary'].id
+---
+- 0
+...
+s.index['primary'].type
+---
+- HASH
+...
+s.index.primary.name
+---
+- primary
+...
+s.index.primary.id
+---
+- 0
+...
+-- other properties are preserved
+s.index.primary.type
+---
+- HASH
+...
+s.index.primary.unique
+---
+- true
+...
+s.index.primary:rename('new')
+---
+...
+s.index[0].name
+---
+- new
+...
+s.index.primary
+---
+- null
+...
+s.index.new.name
+---
+- new
+...
+-- too long name
+s.index[0]:rename(string.rep('t', box.schema.NAME_MAX)..'_')
+---
+- error: 'Can''t create or modify index 0 in space 512: index name is too long'
+...
+s.index[0].name
+---
+- new
+...
+s.index[0]:rename(string.rep('t', box.schema.NAME_MAX - 1)..'_')
+---
+...
+s.index[0].name
+---
+- ttttttttttttttttttttttttttttttt_
+...
+s.index[0]:rename(string.rep('t', box.schema.NAME_MAX - 2)..'_')
+---
+...
+s.index[0].name
+---
+- tttttttttttttttttttttttttttttt_
+...
+s.index[0]:rename('primary')
+---
+...
+s.index.primary.name
+---
+- primary
+...
+-- cleanup
+s:drop()
+---
+...
 -- modify index
+s = box.schema.create_space('test')
+---
+...
+s:create_index('primary', 'hash')
+---
+...
+s.index.primary:alter({unique=false})
+---
+- error: 'Can''t create or modify index 0 in space 512: HASH index must be unique'
+...
+s.index.primary:alter({type='tree', unique=false, name='pk'})
+---
+...
+s.index.primary
+---
+- null
+...
+s.index.pk.type
+---
+- TREE
+...
+s.index.pk.unique
+---
+- false
+...
+s.index.pk:rename('primary')
+---
+...
+s:create_index('second', 'tree', { parts = {  1, 'str' } })
+---
+...
+s.index.second.id
+---
+- 1
+...
+s:create_index('third', 'hash', { parts = {  2, 'num64' } })
+---
+...
+s.index.third:rename('second')
+---
+- error: Duplicate key exists in unique index 1
+...
+s.index.third.id
+---
+- 2
+...
+s.index.second:drop()
+---
+...
+s.index.third:alter({id = 1, name = 'second'})
+---
+...
+s.index.third
+---
+- null
+...
+s.index.second.name
+---
+- second
+...
+s.index.second.id
+---
+- 1
+...
+--
 -- ------------
 --     - alter unique -> non unique
 --     - alter index type
diff --git a/test/box/alter_limits.test.lua b/test/box/alter_limits.test.lua
index d57cfff7a54d914341e9c89447c803a226080fd6..53465d0540178936446799bfe0ba284164ac9b5f 100644
--- a/test/box/alter_limits.test.lua
+++ b/test/box/alter_limits.test.lua
@@ -191,13 +191,55 @@ s.index[0]:drop()
 -- cleanup
 s:drop()
 -- index name, name manipulation
-
--- box.schema.create_space(string.rep('t', box.schema.NAME_MAX)..'_')
--- s = box.schema.create_space(string.rep('t', box.schema.NAME_MAX - 1)..'_')
--- s.name
--- s:drop()
--- s = box.schema.create_space(string.rep('t', box.schema.NAME_MAX - 2)..'_')
+s = box.schema.create_space('test')
+s:create_index('primary', 'hash')
+-- space cache is updated correctly
+s.index[0].name
+s.index[0].id
+s.index[0].type
+s.index['primary'].name
+s.index['primary'].id
+s.index['primary'].type
+s.index.primary.name
+s.index.primary.id
+-- other properties are preserved
+s.index.primary.type
+s.index.primary.unique
+s.index.primary:rename('new')
+s.index[0].name
+s.index.primary
+s.index.new.name
+-- too long name
+s.index[0]:rename(string.rep('t', box.schema.NAME_MAX)..'_')
+s.index[0].name
+s.index[0]:rename(string.rep('t', box.schema.NAME_MAX - 1)..'_')
+s.index[0].name
+s.index[0]:rename(string.rep('t', box.schema.NAME_MAX - 2)..'_')
+s.index[0].name
+s.index[0]:rename('primary')
+s.index.primary.name
+-- cleanup
+s:drop()
 -- modify index
+s = box.schema.create_space('test')
+s:create_index('primary', 'hash')
+s.index.primary:alter({unique=false})
+s.index.primary:alter({type='tree', unique=false, name='pk'})
+s.index.primary
+s.index.pk.type
+s.index.pk.unique
+s.index.pk:rename('primary')
+s:create_index('second', 'tree', { parts = {  1, 'str' } })
+s.index.second.id
+s:create_index('third', 'hash', { parts = {  2, 'num64' } })
+s.index.third:rename('second')
+s.index.third.id
+s.index.second:drop()
+s.index.third:alter({id = 1, name = 'second'})
+s.index.third
+s.index.second.name
+s.index.second.id
+--
 -- ------------
 --     - alter unique -> non unique
 --     - alter index type
diff --git a/test/box/lua.result b/test/box/lua.result
index fc98c621d4cfbe7455675b1fa361ac60435823c4..2ffce19b70815ba544b3d4268a8d683a68b81958 100644
--- a/test/box/lua.result
+++ b/test/box/lua.result
@@ -545,7 +545,7 @@ box.index.bind(0, 1)
 ...
 box.index.bind(0, 0)
 ---
--index 0
+- index 0
 ...
 #box.index.bind(0,0)
 ---