diff --git a/src/box/applier.cc b/src/box/applier.cc
index fecdb7d79a879e9baeccd3224b1910475d01b290..455a42fb80c504dd2eaa721961b48f9b6137c6ed 100644
--- a/src/box/applier.cc
+++ b/src/box/applier.cc
@@ -46,6 +46,7 @@
 #include "version.h"
 #include "trigger.h"
 #include "xrow_io.h"
+#include "error.h"
 
 /* TODO: add configuration options */
 static const int RECONNECT_DELAY = 1;
diff --git a/src/box/box.cc b/src/box/box.cc
index 411b94122b0a1242edade2c6eadc52c3cb8b9bfd..750d355d3e3de9953358779c9dc71f5bd3c9f2de 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -768,7 +768,7 @@ box_register_server(uint32_t id, const struct tt_uuid *uuid)
 {
 	boxk(IPROTO_INSERT, BOX_CLUSTER_ID, "%u%s",
 	     (unsigned) id, tt_uuid_str(uuid));
-	assert(vclock_has(&recovery->vclock, id));
+	assert(server_by_uuid(uuid) != NULL);
 }
 
 /**
@@ -1224,9 +1224,6 @@ engine_init()
 static void
 bootstrap_cluster(void)
 {
-	/* Add a surrogate server id for snapshot rows */
-	vclock_add_server(&recovery->vclock, 0);
-
 	/* Process bootstrap.bin */
 	struct xstream bootstrap_stream;
 	xstream_create(&bootstrap_stream, apply_row);
@@ -1256,9 +1253,6 @@ bootstrap_cluster(void)
 
 	/* Ugly hack: bootstrap always starts from scratch */
 	vclock_create(&recovery->vclock);
-	server_foreach(server)
-		vclock_add_server(&recovery->vclock, server->id);
-	assert(vclock_sum(&recovery->vclock) == 0);
 }
 
 /**
@@ -1289,9 +1283,6 @@ bootstrap_from_master(struct server *master)
 	 */
 	engine_begin_join();
 
-	/* Add a surrogate server id for snapshot rows */
-	vclock_add_server(&recovery->vclock, 0);
-
 	applier_resume_to_state(applier, APPLIER_FINAL_JOIN, TIMEOUT_INFINITY);
 
 	/*
@@ -1371,8 +1362,6 @@ box_init(void)
 		recovery = recovery_new(cfg_gets("wal_dir"),
 					cfg_geti("panic_on_wal_error"),
 					&checkpoint_vclock);
-		/* Add a surrogate server id for snapshot rows */
-		vclock_add_server(&recovery->vclock, 0);
 		/* Tell Sophia engine LSN it must recover to. */
 		engine_recover_to_checkpoint(lsn);
 		/* Replace server vclock using the data from snapshot */
diff --git a/src/box/cluster.cc b/src/box/cluster.cc
index e7fc0455d9b3e8e873e1a5c9f52411fb63ef7812..05a0b78b1b046c2cba332ab0c5733f0d458aed6d 100644
--- a/src/box/cluster.cc
+++ b/src/box/cluster.cc
@@ -40,6 +40,8 @@
 #include "recovery.h"
 #include "wal.h"
 #include "applier.h"
+#include "error.h"
+#include "vclock.h" /* VCLOCK_MAX */
 
 /**
  * Globally unique identifier of this cluster.
@@ -149,20 +151,12 @@ cluster_add_server(uint32_t server_id, const struct tt_uuid *server_uuid)
 void
 server_set_id(struct server *server, uint32_t server_id)
 {
+	assert(server_id < VCLOCK_MAX);
 	assert(server->id == SERVER_ID_NIL); /* server id is read-only */
 	server->id = server_id;
 
 	/* Add server */
 	struct recovery *r = ::recovery;
-	/*
-	 * Add a new server into vclock if the specified server_id has never
-	 * been registered in the cluster. A fresh server starts from
-	 * LSN = 0 (i.e. a first request is LSN = 1). LSN starts from the
-	 * last known value in case server was registered and then
-	 * unregistered somewhere in the past.
-	 */
-	if (!vclock_has(&r->vclock, server_id))
-		vclock_add_server_nothrow(&r->vclock, server_id);
 
 	if (tt_uuid_is_equal(&SERVER_UUID, &server->uuid)) {
 		/* Assign local server id */
diff --git a/src/box/lua/info.c b/src/box/lua/info.c
index 42a7067498987b58de7c4ecff41b39ed3353a00c..3e14d99215e2d945bd4e20b6bc03f91c3d6a64e9 100644
--- a/src/box/lua/info.c
+++ b/src/box/lua/info.c
@@ -138,7 +138,12 @@ lbox_info_server(struct lua_State *L)
 	lua_pushlstring(L, tt_uuid_str(&SERVER_UUID), UUID_STR_LEN);
 	lua_settable(L, -3);
 	lua_pushliteral(L, "lsn");
-	luaL_pushint64(L, vclock_get(&recovery->vclock, recovery->server_id));
+	if (recovery->server_id != SERVER_ID_NIL) {
+		luaL_pushint64(L, vclock_get(&recovery->vclock,
+					     recovery->server_id));
+	} else {
+		luaL_pushint64(L, -1);
+	}
 	lua_settable(L, -3);
 	lua_pushliteral(L, "ro");
 	lua_pushboolean(L, box_is_ro());
diff --git a/src/box/memtx_engine.cc b/src/box/memtx_engine.cc
index 16ae1df7f55898a113f996a67adb6ca5122ccaf9..65847547e9891e66a7cb92d18803cb51fba52608 100644
--- a/src/box/memtx_engine.cc
+++ b/src/box/memtx_engine.cc
@@ -615,8 +615,10 @@ MemtxEngine::MemtxEngine(const char *snap_dirname, bool panic_on_snap_error,
 	struct vclock *vclock = vclockset_last(&m_snap_dir.index);
 	if (vclock) {
 		vclock_copy(&m_last_checkpoint, vclock);
+		m_has_checkpoint = true;
 	} else {
 		vclock_create(&m_last_checkpoint);
+		m_has_checkpoint = false;
 	}
 }
 
@@ -629,10 +631,12 @@ MemtxEngine::~MemtxEngine()
 int64_t
 MemtxEngine::lastCheckpoint(struct vclock *vclock)
 {
-	if (vclock)
-		vclock_copy(vclock, &m_last_checkpoint);
+	if (!m_has_checkpoint)
+		return -1;
+	assert(vclock);
+	vclock_copy(vclock, &m_last_checkpoint);
 	/* Return the lsn of the last checkpoint. */
-	return vclock_size(&m_last_checkpoint) ? vclock_sum(&m_last_checkpoint) : -1;
+	return vclock->signature;
 }
 
 void
@@ -1263,6 +1267,7 @@ MemtxEngine::commitCheckpoint()
 		panic("can't rename .snap.inprogress");
 
 	vclock_copy(&m_last_checkpoint, &m_checkpoint->vclock);
+	m_has_checkpoint = true;
 	checkpoint_destroy(m_checkpoint);
 	m_checkpoint = 0;
 }
@@ -1302,6 +1307,15 @@ MemtxEngine::abortCheckpoint()
 void
 MemtxEngine::join(struct xstream *stream)
 {
+	/*
+	 * The only case when the directory index is empty is
+	 * when someone has deleted a snapshot and tries to join
+	 * as a replica. Our best effort is to not crash in such
+	 * case: raise ER_MISSING_SNAPSHOT.
+	 */
+	if (!m_has_checkpoint)
+		tnt_raise(ClientError, ER_MISSING_SNAPSHOT);
+
 	struct xdir dir;
 	struct xlog *snap = NULL;
 	/*
@@ -1309,20 +1323,12 @@ MemtxEngine::join(struct xstream *stream)
 	 * safe to use in another thread.
 	 */
 	xdir_create(&dir, m_snap_dir.dirname, SNAP, &SERVER_UUID);
-
 	auto guard = make_scoped_guard([&]{
 		xdir_destroy(&dir);
 		if (snap)
 			xlog_close(snap);
 	});
-	/*
-	 * The only case when the directory index is empty is
-	 * when someone has deleted a snapshot and tries to join
-	 * as a replica. Our best effort is to not crash in such
-	 * case: xlog_open_xc will throw "file not found" error.
-	 */
 	struct vclock *last = &m_last_checkpoint;
-	assert(vclock_size(last));
 	snap = xlog_open_xc(&dir, vclock_sum(last));
 	struct xlog_cursor cursor;
 	xlog_cursor_open(&cursor, snap);
diff --git a/src/box/memtx_engine.h b/src/box/memtx_engine.h
index 6ca9201794a3dfb5c18eb883df02644af6a6c21f..b585fcb63d2ef45dee0c1a151000bd76197bc9d5 100644
--- a/src/box/memtx_engine.h
+++ b/src/box/memtx_engine.h
@@ -91,6 +91,7 @@ struct MemtxEngine: public Engine {
 	/** Limit disk usage of checkpointing (bytes per second). */
 	uint64_t m_snap_io_rate_limit;
 	struct vclock m_last_checkpoint;
+	bool m_has_checkpoint;
 	bool m_panic_on_wal_error;
 };
 
diff --git a/src/box/recovery.cc b/src/box/recovery.cc
index 46a94bf38f3dfad6c226149409e52821e9df8066..becf5ce94fc2582398e4dc2b567b3b1d1dedc16f 100644
--- a/src/box/recovery.cc
+++ b/src/box/recovery.cc
@@ -106,7 +106,8 @@ recovery_fill_lsn(struct recovery *r, struct xrow_header *row)
 		row->lsn = vclock_inc(&r->vclock, r->server_id);
 	} else {
 		/* Replication request. */
-		if (!vclock_has(&r->vclock, row->server_id)) {
+		if (server_id_is_reserved(row->server_id) ||
+		    row->server_id >= VCLOCK_MAX) {
 			/*
 			 * A safety net, this can only occur
 			 * if we're fed a strangely broken xlog.
diff --git a/src/box/vclock.c b/src/box/vclock.c
index 35969af8d56862834a6cbcfb0cb1463b78792d2e..92f99dea9dd44a87ce9fde83526e31b9ce7eec8d 100644
--- a/src/box/vclock.c
+++ b/src/box/vclock.c
@@ -48,7 +48,7 @@ vclock_follow(struct vclock *vclock, uint32_t server_id, int64_t lsn)
 		      (long long) prev_lsn, (long long) lsn);
 	}
 	/* Easier add each time than check. */
-	vclock_add_server_nothrow(vclock, server_id);
+	vclock->map |= 1 << server_id;
 	vclock->lsn[server_id] = lsn;
 	vclock->signature += lsn - prev_lsn;
 	return prev_lsn;
@@ -162,9 +162,9 @@ vclock_from_string(struct vclock *vclock, const char *str)
 			errno = 0;
 			lsn = strtoll(p, (char **)  &p, 10);
 			if (errno != 0 || lsn < 0 || lsn > INT64_MAX ||
-			    vclock_has(vclock, server_id))
+			    server_id >= VCLOCK_MAX || vclock->lsn[server_id] > 0)
 				goto error;
-			vclock_add_server_nothrow(vclock, server_id);
+			vclock->map |= 1 << server_id;
 			vclock->lsn[server_id] = lsn;
 			goto comma;
 		}
diff --git a/src/box/vclock.h b/src/box/vclock.h
index e04d89bccea5a61c595b06073d8cfc051a7cf27e..500679b6e3ee14e7bfcba4acd9d9d18893e45520 100644
--- a/src/box/vclock.h
+++ b/src/box/vclock.h
@@ -100,22 +100,19 @@ vclock_create(struct vclock *vclock)
 	memset(vclock, 0, sizeof(*vclock));
 }
 
-static inline bool
-vclock_has(const struct vclock *vclock, uint32_t server_id)
-{
-	return server_id < VCLOCK_MAX && (vclock->map & (1 << server_id));
-}
-
 static inline int64_t
 vclock_get(const struct vclock *vclock, uint32_t server_id)
 {
-	return vclock_has(vclock, server_id) ? vclock->lsn[server_id] : -1;
+	if (server_id >= VCLOCK_MAX)
+		return 0;
+	return vclock->lsn[server_id];
 }
 
 static inline int64_t
 vclock_inc(struct vclock *vclock, uint32_t server_id)
 {
-	assert(vclock_has(vclock, server_id));
+	/* Easier add each time than check. */
+	vclock->map |= 1 << server_id;
 	vclock->signature++;
 	return ++vclock->lsn[server_id];
 }
@@ -149,20 +146,6 @@ vclock_sum(const struct vclock *vclock)
 	return vclock->signature;
 }
 
-/**
- * Add a new server to vclock.
- *
- * Please never, ever, ever remove servers with LSN > 0 from vclock!
- * The vclock_sum() must always grow, it is a core invariant of the recovery
- * subsystem!
- */
-static inline void
-vclock_add_server_nothrow(struct vclock *vclock, uint32_t server_id)
-{
-	assert(server_id < VCLOCK_MAX);
-	vclock->map |= 1 << server_id;
-}
-
 int64_t
 vclock_follow(struct vclock *vclock, uint32_t server_id, int64_t lsn);
 
@@ -266,18 +249,6 @@ vclockset_match(vclockset_t *set, struct vclock *key)
 
 #if defined(__cplusplus)
 } /* extern "C" */
-
-#include "error.h"
-
-static inline void
-vclock_add_server(struct vclock *vclock, uint32_t server_id)
-{
-	if (server_id >= VCLOCK_MAX)
-		tnt_raise(LoggedError, ER_REPLICA_MAX, server_id);
-	assert(! vclock_has(vclock, server_id));
-	vclock_add_server_nothrow(vclock, server_id);
-}
-
 #endif /* defined(__cplusplus) */
 
 #endif /* INCLUDES_TARANTOOL_VCLOCK_H */
diff --git a/src/box/xlog.cc b/src/box/xlog.cc
index ea78e22fc83c69e036feab00d6de47c13b569e1b..b489b15c246ef1922234d4cc5bc3d11667e582e2 100644
--- a/src/box/xlog.cc
+++ b/src/box/xlog.cc
@@ -40,6 +40,8 @@
 #include "third_party/tarantool_eio.h"
 #include <msgpuck.h>
 #include "scoped_guard.h"
+
+#include "error.h"
 #include "xrow.h"
 #include "iproto_constants.h"
 
diff --git a/src/box/xrow.cc b/src/box/xrow.cc
index f8d42024d697a4b1b4d13fd3c89d77517ddb1b4e..caef497d8779e7e948a7a44882e39fe25714db6c 100644
--- a/src/box/xrow.cc
+++ b/src/box/xrow.cc
@@ -36,6 +36,7 @@
 #include "fiber.h"
 #include "version.h"
 
+#include "error.h"
 #include "vclock.h"
 #include "scramble.h"
 #include "iproto_constants.h"
@@ -359,7 +360,6 @@ xrow_decode_subscribe(struct xrow_header *row, struct tt_uuid *cluster_uuid,
 		if (mp_typeof(*d) != MP_UINT)
 			goto map_error;
 		int64_t lsn = (int64_t) mp_decode_uint(&d);
-		vclock_add_server(vclock, id);
 		if (lsn > 0)
 			vclock_follow(vclock, id, lsn);
 	}
diff --git a/test/replication-py/cluster.result b/test/replication-py/cluster.result
index 1a9561e514a281c12d29576d192db271b1a517d6..658bd8172a1294ec2d005bbe4228f568d20fe71f 100644
--- a/test/replication-py/cluster.result
+++ b/test/replication-py/cluster.result
@@ -57,7 +57,7 @@ box.space._cluster:insert{5, '0d5bd431-7f3e-4695-a5c2-82de0a9cbc95'}
 ---
 - [5, '0d5bd431-7f3e-4695-a5c2-82de0a9cbc95']
 ...
-box.info.vclock[5] == 0
+box.info.vclock[5] == nil
 ---
 - true
 ...
@@ -77,7 +77,7 @@ box.space._cluster:delete(5)
 ---
 - [5, '0d5bd431-7f3e-4695-a5c2-82de0a9cbc95', 'test']
 ...
-box.info.vclock[5] == 0
+box.info.vclock[5] == nil
 ---
 - true
 ...
@@ -99,7 +99,7 @@ box.info.server.lsn == 0
 ---
 - true
 ...
-box.info.vclock[2] == 0
+box.info.vclock[2] == nil
 ---
 - true
 ...
@@ -219,7 +219,7 @@ box.info.vclock[2] == 1
 ---
 - true
 ...
-box.info.vclock[10] == 0
+box.info.vclock[10] == nil
 ---
 - true
 ...
@@ -247,7 +247,7 @@ box.info.vclock[2] == 1
 ---
 - true
 ...
-box.info.vclock[10] == 0
+box.info.vclock[10] == nil
 ---
 - true
 ...
@@ -270,7 +270,7 @@ box.info.server.lsn == -1
 ---
 - true
 ...
-box.info.vclock[10] == 0
+box.info.vclock[10] == nil
 ---
 - true
 ...
@@ -288,7 +288,7 @@ box.info.vclock[2] == 1
 ---
 - true
 ...
-box.info.vclock[10] == 0
+box.info.vclock[10] == nil
 ---
 - true
 ...
@@ -326,11 +326,11 @@ box.info.vclock[2] == 1
 ---
 - true
 ...
-box.info.vclock[10] == 0
+box.info.vclock[10] == nil
 ---
 - true
 ...
-box.info.vclock[10] == 0
+box.info.vclock[10] == nil
 ---
 - true
 ...
diff --git a/test/replication-py/cluster.test.py b/test/replication-py/cluster.test.py
index c94878cbe469c265409a457ca1a0b20b37c7dc4e..99efc75f83da3bd8d86ec97fc5acd9d44c1d122b 100644
--- a/test/replication-py/cluster.test.py
+++ b/test/replication-py/cluster.test.py
@@ -119,7 +119,7 @@ print '-------------------------------------------------------------'
 # Test that insert is OK
 new_uuid = '0d5bd431-7f3e-4695-a5c2-82de0a9cbc95'
 server.admin("box.space._cluster:insert{{5, '{0}'}}".format(new_uuid))
-server.admin("box.info.vclock[5] == 0")
+server.admin("box.info.vclock[5] == nil")
 
 # Replace with the same UUID is OK
 server.admin("box.space._cluster:replace{{5, '{0}'}}".format(new_uuid))
@@ -131,7 +131,7 @@ server.admin("box.space._cluster:update(5, {{'=', 3, 'test'}})")
 # Delete is OK
 server.admin("box.space._cluster:delete(5)")
 # gh-1219: LSN must not be removed from vclock on unregister
-server.admin("box.info.vclock[5] == 0")
+server.admin("box.info.vclock[5] == nil")
 
 # Cleanup
 server.stop()
@@ -158,7 +158,7 @@ sys.stdout.push_filter(replica_uuid, '<replica uuid>')
 replica.admin('box.info.server.id == %d' % replica_id)
 replica.admin('not box.info.server.ro')
 replica.admin('box.info.server.lsn == 0')
-replica.admin('box.info.vclock[%d] == 0' % replica_id)
+replica.admin('box.info.vclock[%d] == nil' % replica_id)
 
 print '-------------------------------------------------------------'
 print 'Modify data to change LSN and check box.info'
@@ -174,7 +174,6 @@ print '-------------------------------------------------------------'
 master.admin('box.space._cluster:delete{%d} ~= nil' % replica_id)
 replica.wait_lsn(master_id, master.get_lsn(master_id))
 replica.admin('box.info.server.id ~= %d' % replica_id)
-# Backward-compatibility: box.info.server.lsn is -1 instead of nil
 replica.admin('box.info.server.lsn == -1')
 # gh-1219: LSN must not be removed from vclock on unregister
 replica.admin('box.info.vclock[%d] == 1' % replica_id)
@@ -223,7 +222,7 @@ replica.admin('box.info.server.id == %d' % replica_id2)
 replica.admin('not box.info.server.ro')
 replica.admin('box.info.server.lsn == 0')
 replica.admin('box.info.vclock[%d] == 1' % replica_id)
-replica.admin('box.info.vclock[%d] == 0' % replica_id2)
+replica.admin('box.info.vclock[%d] == nil' % replica_id2)
 
 print '-------------------------------------------------------------'
 print 'Check that server_id can\'t be changed by UPDATE'
@@ -236,7 +235,7 @@ replica.admin('box.info.server.id == %d' % replica_id2)
 replica.admin('not box.info.server.ro')
 replica.admin('box.info.server.lsn == 0')
 replica.admin('box.info.vclock[%d] == 1' % replica_id)
-replica.admin('box.info.vclock[%d] == 0' % replica_id2)
+replica.admin('box.info.vclock[%d] == nil' % replica_id2)
 replica.admin('box.info.vclock[%d] == nil' % replica_id3)
 
 print '-------------------------------------------------------------'
@@ -248,7 +247,7 @@ replica.wait_lsn(master_id, master.get_lsn(master_id))
 replica.admin('box.info.server.id ~= %d' % replica_id)
 # Backward-compatibility: box.info.server.lsn is -1 instead of nil
 replica.admin('box.info.server.lsn == -1')
-replica.admin('box.info.vclock[%d] == 0' % replica_id2)
+replica.admin('box.info.vclock[%d] == nil' % replica_id2)
 
 print '-------------------------------------------------------------'
 print 'JOIN replica to read-only master'
@@ -278,7 +277,7 @@ master.admin("box.cfg{ replication_source = '%s' }" % replication_source)
 
 master.wait_lsn(replica_id, replica.get_lsn(replica_id))
 master.admin('box.info.vclock[%d] == 1' % replica_id)
-master.admin('box.info.vclock[%d] == 0' % replica_id2)
+master.admin('box.info.vclock[%d] == nil' % replica_id2)
 master.admin('box.info.vclock[%d] == nil' % replica_id3)
 
 master.admin("box.cfg{ replication_source = '' }")
@@ -310,8 +309,8 @@ replica.admin('not box.info.server.ro')
 # Replica should have the same vclock as master.
 master.admin('box.info.vclock[%d] == 1' % replica_id)
 replica.admin('box.info.vclock[%d] == 1' % replica_id)
-master.admin('box.info.vclock[%d] == 0' % replica_id2)
-replica.admin('box.info.vclock[%d] == 0' % replica_id2)
+master.admin('box.info.vclock[%d] == nil' % replica_id2)
+replica.admin('box.info.vclock[%d] == nil' % replica_id2)
 master.admin('box.info.vclock[%d] == nil' % replica_id3)
 replica.admin('box.info.vclock[%d] == nil' % replica_id3)
 
diff --git a/test/replication-py/multi.result b/test/replication-py/multi.result
index 9f685752cad3bc5e4d3f333b7e3991e6adaf620e..b4f16b6997ae9b6fb7ab7826923e55d551a9a546 100644
--- a/test/replication-py/multi.result
+++ b/test/replication-py/multi.result
@@ -19,21 +19,21 @@ server 1 connected
 server 1 connected
 box.info.vclock
 ---
-- {1: 4, 2: 0, 3: 0}
+- {1: 4}
 ...
 server 2 connected
 server 2 connected
 server 2 connected
 box.info.vclock
 ---
-- {1: 4, 2: 0, 3: 0}
+- {1: 4}
 ...
 server 3 connected
 server 3 connected
 server 3 connected
 box.info.vclock
 ---
-- {1: 4, 2: 0, 3: 0}
+- {1: 4}
 ...
 done
 ----------------------------------------------------------------------
diff --git a/test/replication/autobootstrap.result b/test/replication/autobootstrap.result
index 12294eeb470b48194a4c81865d26897543f75bab..79b6861bbe9bfb9d96538f0f5cdd3fcb26155b3f 100644
--- a/test/replication/autobootstrap.result
+++ b/test/replication/autobootstrap.result
@@ -27,21 +27,21 @@ _ = test_run:cmd("switch autobootstrap1")
 ...
 box.info.vclock
 ---
-- {1: 7, 2: 0, 3: 0}
+- {1: 7}
 ...
 _ = test_run:cmd("switch autobootstrap2")
 ---
 ...
 box.info.vclock
 ---
-- {1: 7, 2: 0, 3: 0}
+- {1: 7}
 ...
 _ = test_run:cmd("switch autobootstrap3")
 ---
 ...
 box.info.vclock
 ---
-- {1: 7, 2: 0, 3: 0}
+- {1: 7}
 ...
 _ = test_run:cmd("switch default")
 ---
diff --git a/test/replication/status.result b/test/replication/status.result
index 06e268d3e4419f82d93ac8894a8f1f5150e8745f..62342decac1312b818bbbbe804e6a68f42f76d76 100644
--- a/test/replication/status.result
+++ b/test/replication/status.result
@@ -45,7 +45,7 @@ r.vclock[1] > 0
 ---
 - true
 ...
-r.vclock[2] == 0
+r.vclock[2] == nil
 ---
 - true
 ...
diff --git a/test/replication/status.test.lua b/test/replication/status.test.lua
index 53617c33db9c3c7a1435d863b9b15bf161bdb65b..4f3ec9c79a7e7fde74d9d039a9d3b7a7da5db427 100644
--- a/test/replication/status.test.lua
+++ b/test/replication/status.test.lua
@@ -12,7 +12,7 @@ r.status == "follow"
 r.lag < 1
 r.idle < 1
 r.vclock[1] > 0
-r.vclock[2] == 0
+r.vclock[2] == nil
 r.uuid ~= nil
 
 box.space._schema:insert({'dup'})
diff --git a/test/unit/vclock.cc b/test/unit/vclock.cc
index 68d18cdda72f68021ffd4f93a07d51f34bb8c016..8498eba3b956abac56c9b0adde385df6e05f90b3 100644
--- a/test/unit/vclock.cc
+++ b/test/unit/vclock.cc
@@ -49,12 +49,10 @@ test_compare_one(uint32_t a_count, const int64_t *lsns_a,
 	vclock_create(&a);
 	vclock_create(&b);
 	for (uint32_t node_id = 0; node_id < a_count; node_id++) {
-		vclock_add_server(&a, node_id);
 		if (lsns_a[node_id] > 0)
 			vclock_follow(&a, node_id, lsns_a[node_id]);
 	}
 	for (uint32_t node_id = 0; node_id < b_count; node_id++) {
-		vclock_add_server(&b, node_id);
 		if (lsns_b[node_id] > 0)
 			vclock_follow(&b, node_id, lsns_b[node_id]);
 	}
@@ -227,7 +225,6 @@ test_isearch()
 			if (lsn <= 0)
 				continue;
 
-			vclock_add_server(&vclock, node_id);
 			vclock_follow(&vclock, node_id, lsn);
 		}
 
@@ -249,8 +246,6 @@ test_tostring_one(uint32_t count, const int64_t *lsns, const char *res)
 	struct vclock vclock;
 	vclock_create(&vclock);
 	for (uint32_t node_id = 0; node_id < count; node_id++) {
-		if (lsns[node_id] >= 0)
-			vclock_add_server(&vclock, node_id);
 		if (lsns[node_id] > 0)
 			vclock_follow(&vclock, node_id, lsns[node_id]);
 	}
@@ -279,7 +274,7 @@ test_tostring()
 	test(arg(10, 15, 20), "{0: 10, 1: 15, 2: 20}");
 	test(arg(10, -1, 15, -1, 20), "{0: 10, 2: 15, 4: 20}");
 	test(arg(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),
-	     "{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, "
+	     "{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, "
 	      "9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}");
 	test(arg(9223372036854775000, 9223372036854775001, 9223372036854775002,
 		 9223372036854775003, 9223372036854775004, 9223372036854775005,
diff --git a/test/unit/vclock.result b/test/unit/vclock.result
index ee2940d8f3efdd51f70f5819c21652f1c4342ae7..2ca741bbd9f5d00c51b3588e0ece9a7949076c1a 100644
--- a/test/unit/vclock.result
+++ b/test/unit/vclock.result
@@ -91,7 +91,7 @@ ok 2 - subtests
     ok 4 - tostring (1, 2) => {0: 1, 1: 2}
     ok 5 - tostring (10, 15, 20) => {0: 10, 1: 15, 2: 20}
     ok 6 - tostring (10, -1, 15, -1, 20) => {0: 10, 2: 15, 4: 20}
-    ok 7 - tostring (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) => {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}
+    ok 7 - tostring (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) => {1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14, 15: 15}
     ok 8 - tostring (9223372036854775000, 9223372036854775001, 9223372036854775002, 9223372036854775003, 9223372036854775004, 9223372036854775005, 9223372036854775006, 9223372036854775007, 9223372036854775008, 9223372036854775009, 9223372036854775010, 9223372036854775011, 9223372036854775012, 9223372036854775013, 9223372036854775014, 9223372036854775015) => {0: 9223372036854775000, 1: 9223372036854775001, 2: 9223372036854775002, 3: 9223372036854775003, 4: 9223372036854775004, 5: 9223372036854775005, 6: 9223372036854775006, 7: 9223372036854775007, 8: 9223372036854775008, 9: 9223372036854775009, 10: 9223372036854775010, 11: 9223372036854775011, 12: 9223372036854775012, 13: 9223372036854775013, 14: 9223372036854775014, 15: 9223372036854775015}
 	*** test_tostring: done ***
 ok 3 - subtests
diff --git a/test/xlog/panic_on_lsn_gap.result b/test/xlog/panic_on_lsn_gap.result
index e9ff7fa31f39f67298cdf17cb03da8fdb9a8da97..d1615de462a3ef3055423c640ac1617c69b0680a 100644
--- a/test/xlog/panic_on_lsn_gap.result
+++ b/test/xlog/panic_on_lsn_gap.result
@@ -26,7 +26,7 @@ test_run:cmd("switch panic")
 ...
 box.info.vclock
 ---
-- {1: 0}
+- {}
 ...
 s = box.space._schema
 ---
diff --git a/test/xlog/panic_on_wal_error.result b/test/xlog/panic_on_wal_error.result
index aa7e54ca20b77affbaa951a979f6d96a94485dcc..72d7d7d9d8cad29acb0fa2aac9079fe92cf6d82a 100644
--- a/test/xlog/panic_on_wal_error.result
+++ b/test/xlog/panic_on_wal_error.result
@@ -156,7 +156,7 @@ box.info.replication[1].status
 ...
 box.info.replication[1].message
 ---
-- 'Missing .xlog file between LSN 6 {1: 6, 2: 0} and 8 {1: 8}'
+- 'Missing .xlog file between LSN 6 {1: 6} and 8 {1: 8}'
 ...
 box.space.test:select{}
 ---