diff --git a/src/box/applier.cc b/src/box/applier.cc
index f48b1a4e3626e522a52488554904f20e2fa80aec..247dcb2569093572641b53b4b4e08f1a7faac858 100644
--- a/src/box/applier.cc
+++ b/src/box/applier.cc
@@ -164,7 +164,7 @@ applier_connect(struct applier *applier)
 	coio_connect(coio, uri, &applier->addr, &applier->addr_len);
 	assert(coio->fd >= 0);
 	coio_readn(coio, greetingbuf, IPROTO_GREETING_SIZE);
-	applier->last_row_time = ev_now(loop());
+	applier->last_row_time = ev_monotonic_now(loop());
 
 	/* Decode instance version and name from greeting */
 	struct greeting greeting;
@@ -221,7 +221,7 @@ applier_connect(struct applier *applier)
 			    uri->login_len, uri->password, uri->password_len);
 	coio_write_xrow(coio, &row);
 	coio_read_xrow(coio, &iobuf->in, &row);
-	applier->last_row_time = ev_now(loop());
+	applier->last_row_time = ev_monotonic_now(loop());
 	if (row.type != IPROTO_OK)
 		xrow_decode_error_xc(&row); /* auth failed */
 
@@ -287,7 +287,7 @@ applier_join(struct applier *applier)
 	assert(applier->join_stream != NULL);
 	while (true) {
 		coio_read_xrow(coio, &iobuf->in, &row);
-		applier->last_row_time = ev_now(loop());
+		applier->last_row_time = ev_monotonic_now(loop());
 		if (iproto_type_is_dml(row.type)) {
 			xstream_write_xc(applier->join_stream, &row);
 		} else if (row.type == IPROTO_OK) {
@@ -324,7 +324,7 @@ applier_join(struct applier *applier)
 	 */
 	while (true) {
 		coio_read_xrow(coio, &iobuf->in, &row);
-		applier->last_row_time = ev_now(loop());
+		applier->last_row_time = ev_monotonic_now(loop());
 		if (iproto_type_is_dml(row.type)) {
 			vclock_follow(&replicaset_vclock, row.replica_id,
 				      row.lsn);
@@ -403,7 +403,7 @@ applier_subscribe(struct applier *applier)
 	while (true) {
 		coio_read_xrow(coio, &iobuf->in, &row);
 		applier->lag = ev_now(loop()) - row.tm;
-		applier->last_row_time = ev_now(loop());
+		applier->last_row_time = ev_monotonic_now(loop());
 
 		if (iproto_type_is_error(row.type))
 			xrow_decode_error_xc(&row);  /* error */
@@ -584,7 +584,7 @@ applier_new(const char *uri, struct xstream *join_stream,
 
 	applier->join_stream = join_stream;
 	applier->subscribe_stream = subscribe_stream;
-	applier->last_row_time = ev_now(loop());
+	applier->last_row_time = ev_monotonic_now(loop());
 	rlist_create(&applier->on_state);
 	fiber_channel_create(&applier->pause, 0);
 	fiber_cond_create(&applier->writer_cond);
@@ -713,7 +713,7 @@ applier_connect_all(struct applier **appliers, int count,
 	/* Memory for on_state triggers registered in appliers */
 	struct applier_on_state triggers[VCLOCK_MAX];
 	/* Wait results until this time */
-	double deadline = fiber_time() + timeout;
+	double deadline = ev_monotonic_now(loop()) + timeout;
 
 	/* Add triggers and start simulations connection to remote peers */
 	for (int i = 0; i < count; i++) {
@@ -726,7 +726,7 @@ applier_connect_all(struct applier **appliers, int count,
 
 	/* Wait for all appliers */
 	for (int i = 0; i < count; i++) {
-		double wait = deadline - fiber_time();
+		double wait = deadline - ev_monotonic_now(loop());
 		if (wait < 0.0 ||
 		    applier_wait_for_state(&triggers[i], wait) != 0) {
 			goto error;
diff --git a/src/box/lua/info.c b/src/box/lua/info.c
index 9ce80c022a19ed63ffbda9b0bac1711658bfdf5e..f3343752a6daf4353ada84e7257286ee8116ccfd 100644
--- a/src/box/lua/info.c
+++ b/src/box/lua/info.c
@@ -88,7 +88,8 @@ lbox_pushapplier(lua_State *L, struct applier *applier)
 		lua_settable(L, -3);
 
 		lua_pushstring(L, "idle");
-		lua_pushnumber(L, ev_now(loop()) - applier->last_row_time);
+		lua_pushnumber(L, ev_monotonic_now(loop()) -
+			       applier->last_row_time);
 		lua_settable(L, -3);
 
 		struct error *e = diag_last_error(&applier->reader->diag);
diff --git a/src/box/lua/net_box.c b/src/box/lua/net_box.c
index c112e8ab47b81144c09ed1fc8a677683619f4455..db2d2dbb49fe0604ca49d313beaa67d99e599111 100644
--- a/src/box/lua/net_box.c
+++ b/src/box/lua/net_box.c
@@ -536,11 +536,11 @@ netbox_communicate(lua_State *L)
 				goto handle_error;
 		}
 
-		ev_tstamp deadline = fiber_time() + timeout;
+		ev_tstamp deadline = ev_monotonic_now(loop()) + timeout;
 		revents = coio_wait(fd, EV_READ | (ibuf_used(send_buf) != 0 ?
 				EV_WRITE : 0), timeout);
 		luaL_testcancel(L);
-		timeout = deadline - fiber_time();
+		timeout = deadline - ev_monotonic_now(loop());
 		timeout = MAX(0.0, timeout);
 		if (revents == 0 && timeout == 0.0) {
 			lua_pushinteger(L, ER_TIMEOUT);
diff --git a/src/box/txn.cc b/src/box/txn.cc
index 1f5529d5722c9808f4a0ef63b55bfe569bae2904..5188ea39eb58caecad898390e7e92cb7d246a93f 100644
--- a/src/box/txn.cc
+++ b/src/box/txn.cc
@@ -202,10 +202,10 @@ txn_write_to_wal(struct txn *txn)
 	}
 	assert(row == req->rows + req->n_rows);
 
-	ev_tstamp start = ev_now(loop()), stop;
+	ev_tstamp start = ev_monotonic_now(loop());
 	int64_t res = journal_write(req);
 
-	stop = ev_now(loop());
+	ev_tstamp stop = ev_monotonic_now(loop());
 	if (stop - start > too_long_threshold)
 		say_warn("too long WAL write: %.3f sec", stop - start);
 	if (res < 0) {
diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index e7de0b704059735865bda7f7a9ddb16899ce0f57..c6ed11505b15e6f5cfb009aca3ed7ccd3a6c167a 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1277,10 +1277,10 @@ static ev_tstamp
 vy_scheduler_quota_throttled_cb(struct vy_quota *quota, ev_tstamp timeout)
 {
 	struct vy_env *env = container_of(quota, struct vy_env, quota);
-	ev_tstamp wait_start = ev_now(loop());
+	ev_tstamp wait_start = ev_monotonic_now(loop());
 	if (fiber_cond_wait_timeout(&env->scheduler->quota_cond, timeout) != 0)
 		return 0; /* timed out */
-	ev_tstamp wait_end = ev_now(loop());
+	ev_tstamp wait_end = ev_monotonic_now(loop());
 	return timeout - (wait_end - wait_start);
 }
 
@@ -1845,7 +1845,7 @@ vy_scheduler_trigger_dump(struct vy_scheduler *scheduler)
 		 * dump bandwidth when the dump round is complete
 		 * (see vy_scheduler_complete_dump()).
 		 */
-		scheduler->dump_start = ev_now(loop());
+		scheduler->dump_start = ev_monotonic_now(loop());
 	}
 	scheduler->generation++;
 }
@@ -1901,7 +1901,7 @@ vy_scheduler_complete_dump(struct vy_scheduler *scheduler)
 
 	/* Account dump bandwidth. */
 	struct vy_stat *stat = scheduler->env->stat;
-	ev_tstamp now = ev_now(loop());
+	ev_tstamp now = ev_monotonic_now(loop());
 	ev_tstamp dump_duration = now - scheduler->dump_start;
 	if (dump_duration > 0)
 		histogram_collect(stat->dump_bw, mem_dumped / dump_duration);
diff --git a/src/box/vy_read_iterator.c b/src/box/vy_read_iterator.c
index 745e2b383d182d183f76f09a43a1cd9519ab0eb3..4be826b052b8ed214ef1fdf622971cc0e4f162c1 100644
--- a/src/box/vy_read_iterator.c
+++ b/src/box/vy_read_iterator.c
@@ -808,7 +808,7 @@ vy_read_iterator_next_range(struct vy_read_iterator *itr, struct tuple **ret)
 NODISCARD int
 vy_read_iterator_next(struct vy_read_iterator *itr, struct tuple **result)
 {
-	ev_tstamp start_time = ev_now(loop());
+	ev_tstamp start_time = ev_monotonic_now(loop());
 
 	/* The key might be set to NULL during previous call, that means
 	 * that there's no more data */
@@ -964,7 +964,8 @@ vy_read_iterator_next(struct vy_read_iterator *itr, struct tuple **result)
 	if (prev_key != NULL)
 		tuple_unref(prev_key);
 
-	latency_collect(&index->stat.latency, ev_now(loop()) - start_time);
+	latency_collect(&index->stat.latency,
+			ev_monotonic_now(loop()) - start_time);
 	return rc;
 }
 
diff --git a/src/box/xlog.c b/src/box/xlog.c
index 14764f7ccdf7495c58365f2123d413d436dba045..11bce2d6035e570ca0d0e03513e9fae891e571b1 100644
--- a/src/box/xlog.c
+++ b/src/box/xlog.c
@@ -658,7 +658,7 @@ xlog_init(struct xlog *xlog)
 {
 	memset(xlog, 0, sizeof(*xlog));
 	xlog->sync_interval = SNAP_SYNC_INTERVAL;
-	xlog->sync_time = ev_time();
+	xlog->sync_time = ev_monotonic_time();
 	xlog->is_autocommit = true;
 	obuf_create(&xlog->obuf, &cord()->slabc, XLOG_TX_AUTOCOMMIT_THRESHOLD);
 	obuf_create(&xlog->zbuf, &cord()->slabc, XLOG_TX_AUTOCOMMIT_THRESHOLD);
@@ -1090,7 +1090,7 @@ xlog_tx_write(struct xlog *log)
 		if (log->rate_limit > 0) {
 			double throttle_time;
 			throttle_time = (double)sync_len / log->rate_limit -
-					(ev_time() - log->sync_time);
+					(ev_monotonic_time() - log->sync_time);
 			if (throttle_time > 0)
 				fiber_sleep(throttle_time);
 		}
@@ -1103,7 +1103,7 @@ xlog_tx_write(struct xlog *log)
 #else
 		fdatasync(log->fd);
 #endif /* HAVE_SYNC_FILE_RANGE */
-		log->sync_time = ev_time();
+		log->sync_time = ev_monotonic_time();
 		if (log->free_cache) {
 #ifdef HAVE_POSIX_FADVISE
 			/** free page cache */
diff --git a/src/evio.h b/src/evio.h
index 4ddf8c3987f81b99ffe942b0d6882b433d4e7647..e91ba11fc3a6e687cb1e3b8093dbdc4715d964e4 100644
--- a/src/evio.h
+++ b/src/evio.h
@@ -138,14 +138,14 @@ static inline void
 evio_timeout_init(ev_loop *loop, ev_tstamp *start, ev_tstamp *delay,
 		  ev_tstamp timeout)
 {
-	*start = ev_now(loop);
+	*start = ev_monotonic_now(loop);
 	*delay = timeout;
 }
 
 static inline void
 evio_timeout_update(ev_loop *loop, ev_tstamp start, ev_tstamp *delay)
 {
-	ev_tstamp elapsed = ev_now(loop) - start;
+	ev_tstamp elapsed = ev_monotonic_now(loop) - start;
 	*delay = (elapsed >= *delay) ? 0 : *delay - elapsed;
 }
 
diff --git a/src/fiber_channel.c b/src/fiber_channel.c
index 6f1afda653eb564ace353c7357eb2a44ddc9fe0c..99e51a47e7e0bdb0e72ed00bb8564b27a39355ba 100644
--- a/src/fiber_channel.c
+++ b/src/fiber_channel.c
@@ -185,7 +185,7 @@ fiber_channel_check_wait(struct fiber_channel *ch, ev_tstamp start_time,
 		diag_set(FiberIsCancelled);
 		return -1;
 	}
-	if (timeout == 0 || ev_now(loop()) > start_time + timeout) {
+	if (timeout == 0 || ev_monotonic_now(loop()) > start_time + timeout) {
 		diag_set(TimedOut);
 		return -1;
 	}
@@ -291,7 +291,7 @@ fiber_channel_put_msg_timeout(struct fiber_channel *ch,
 {
 	/** Ensure delivery fairness in case of prolonged wait. */
 	bool first_try = true;
-	ev_tstamp start_time = ev_now(loop());
+	ev_tstamp start_time = ev_monotonic_now(loop());
 
 	while (true) {
 		/*
@@ -383,7 +383,7 @@ fiber_channel_put_msg_timeout(struct fiber_channel *ch,
 		}
 		if (pad.status == FIBER_CHANNEL_WAIT_DONE)
 			return 0;  /* OK, someone took the message. */
-		timeout -= ev_now(loop()) - start_time;
+		timeout -= ev_monotonic_now(loop()) - start_time;
 	}
 }
 
@@ -394,7 +394,7 @@ fiber_channel_get_msg_timeout(struct fiber_channel *ch,
 {
 	/** Ensure delivery fairness in case of prolonged wait. */
 	bool first_try = true;
-	ev_tstamp start_time = ev_now(loop());
+	ev_tstamp start_time = ev_monotonic_now(loop());
 
 	while (true) {
 		struct fiber *f;
@@ -484,6 +484,6 @@ fiber_channel_get_msg_timeout(struct fiber_channel *ch,
 			*msg = pad.msg;
 			return 0;
 		}
-		timeout -= ev_now(loop()) - start_time;
+		timeout -= ev_monotonic_now(loop()) - start_time;
 	}
 }
diff --git a/src/fiber_pool.c b/src/fiber_pool.c
index 4e34e625afaff109524b393c7cb2a68db636f39d..0a81c006983a1f2062170d58ea2ef8fb12b9c027 100644
--- a/src/fiber_pool.c
+++ b/src/fiber_pool.c
@@ -42,7 +42,7 @@ fiber_pool_f(va_list ap)
 	struct ev_loop *loop = pool->consumer;
 	struct stailq *output = &pool->output;
 	struct cmsg *msg;
-	ev_tstamp last_active_at = ev_now(loop);
+	ev_tstamp last_active_at = ev_monotonic_now(loop);
 	pool->size++;
 restart:
 	msg = NULL;
@@ -64,9 +64,10 @@ fiber_pool_f(va_list ap)
 		cmsg_deliver(msg);
 	}
 	/** Put the current fiber into a fiber cache. */
-	if (msg != NULL || ev_now(loop) - last_active_at < pool->idle_timeout) {
+	if (msg != NULL ||
+	    ev_monotonic_now(loop) - last_active_at < pool->idle_timeout) {
 		if (msg != NULL)
-			last_active_at = ev_now(loop);
+			last_active_at = ev_monotonic_now(loop);
 		/*
 		 * Add the fiber to the front of the list, so that
 		 * it is most likely to get scheduled again.
diff --git a/src/latch.h b/src/latch.h
index 5a4d1ecb1eb683d1fda3fbd0c919623c9516b797..cbdff7182d8ec32ef3f589529a297a07e589f14f 100644
--- a/src/latch.h
+++ b/src/latch.h
@@ -126,7 +126,7 @@ latch_lock_timeout(struct latch *l, ev_tstamp timeout)
 			l->owner = fiber();
 			break;
 		}
-		timeout -= ev_now(loop()) - start;
+		timeout -= ev_monotonic_now(loop()) - start;
 		if (timeout <= 0) {
 			result = 1;
 			break;
diff --git a/src/main.cc b/src/main.cc
index fec960e9611babb6a3dbaffaebb6f0941afa8715..9912b0e92a177660061e98ac4c8eedae90fca297 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -92,7 +92,7 @@ static double start_time;
 double
 tarantool_uptime(void)
 {
-	return ev_now(loop()) - start_time;
+	return ev_monotonic_now(loop()) - start_time;
 }
 
 /**
@@ -543,7 +543,6 @@ print_help(const char *program)
 int
 main(int argc, char **argv)
 {
-	start_time = ev_time();
 	/* set locale to make iswXXXX function work */
 	if (setlocale(LC_CTYPE, "C.UTF-8") == NULL &&
 	    setlocale(LC_CTYPE, "en_US.UTF-8") == NULL &&
@@ -660,6 +659,8 @@ main(int argc, char **argv)
 	cbus_init();
 	tarantool_lua_init(tarantool_bin, main_argc, main_argv);
 
+	start_time = ev_monotonic_time();
+
 	try {
 		box_init();
 		box_lua_init(tarantool_L);
diff --git a/src/rmean.c b/src/rmean.c
index 2752a37960fcd0d33d04ddc672233a4941de5be1..222441f754e50e7b6941cd366b8eec36d7e68dda 100644
--- a/src/rmean.c
+++ b/src/rmean.c
@@ -90,7 +90,7 @@ rmean_age(ev_loop *loop,
 	struct rmean *rmean = (struct rmean *) timer->data;
 
 	double dt = rmean->prev_ts;
-	rmean->prev_ts = ev_now(loop);
+	rmean->prev_ts = ev_monotonic_now(loop);
 	dt = rmean->prev_ts - dt;
 	for (size_t i = 0; i < rmean->stats_n; i++) {
 		if (rmean->stats[i].name == NULL)
@@ -114,7 +114,7 @@ rmean_new(const char **name, size_t n)
 	for (size_t i = 0; i < n; i++, name++) {
 		rmean->stats[i].name = *name;
 	}
-	rmean->prev_ts = ev_now(loop());
+	rmean->prev_ts = ev_monotonic_now(loop());
 	ev_timer_init(&rmean->timer, rmean_age, 0, 1.);
 	ev_timer_again(loop(), &rmean->timer);
 	return rmean;