diff --git a/.gitignore b/.gitignore
index 62e3fa457137617f8250d433053bf6bb75b21f52..7f5982e9987ec714206f5c5e456a1131c69e9d78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,10 +1,6 @@
 .gitignore
 .gdb_history
 TAGS
-_debug_box
-_release_box
-_debug_feeder
-_release_feeder
 config.mk
 lcov
 *.o
@@ -19,7 +15,6 @@ CMakeFiles
 CMakeCache.txt
 cmake_install.cmake
 mod/box/tarantool_box
-mod/feeder/tarantool_feeder
 include/config.h
 CPackConfig.cmake
 CPackSourceConfig.cmake
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac2bda1b96703298804bcb91acf6e51fe1144517..c647bb3b3c3ff1caa7ce5ad509bf89c88faa1ad9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,7 +21,7 @@ include(cmake/check_objective_c_compiler.cmake)
 # and what modules to produce.
 #
 set (TARANTOOL_PRODUCT "box")
-set (TARANTOOL_MODULES "box" "feeder")
+set (TARANTOOL_MODULES "box")
 
 #
 # Set default build type to Debug. This is to ease a developer's
diff --git a/cfg/core_cfg.cfg_tmpl b/cfg/core_cfg.cfg_tmpl
index ca18e226b7c0e6e370c349ddf4eaa0dce410bb34..b73e138195445e12eb73330fa66791a963b62f39 100644
--- a/cfg/core_cfg.cfg_tmpl
+++ b/cfg/core_cfg.cfg_tmpl
@@ -1,6 +1,10 @@
 # username to switch to
 username=NULL, ro
 
+# tarantool bind ip address, applies to master
+# and replication ports. INADDR_ANY is the default value.
+bind_ipaddr="INADDR_ANY", ro
+
 # save core on abort/assert
 # deprecated; use ulimit instead
 coredump=0, ro
@@ -9,6 +13,9 @@ coredump=0, ro
 # used for admin's connections
 admin_port=0, ro
 
+# Replication clients should use this port (bind_ipaddr:replication_port).
+replication_port=0, ro
+
 # Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5
 log_level=4
 
diff --git a/cfg/tarantool_box_cfg.c b/cfg/tarantool_box_cfg.c
index 57bd9fc6c32a7d40a9a2f62b27428504e3374b43..4e4d564a1fc3d354d3ae765b18a5faddbaebc442 100644
--- a/cfg/tarantool_box_cfg.c
+++ b/cfg/tarantool_box_cfg.c
@@ -29,8 +29,10 @@ init_tarantool_cfg(tarantool_cfg *c) {
 	c->__confetti_flags = 0;
 
 	c->username = NULL;
+	c->bind_ipaddr = NULL;
 	c->coredump = 0;
 	c->admin_port = 0;
+	c->replication_port = 0;
 	c->log_level = 0;
 	c->slab_alloc_arena = 0;
 	c->slab_alloc_minimal = 0;
@@ -61,9 +63,7 @@ init_tarantool_cfg(tarantool_cfg *c) {
 	c->wal_dir_rescan_delay = 0;
 	c->panic_on_snap_error = 0;
 	c->panic_on_wal_error = 0;
-	c->remote_hot_standby = 0;
-	c->wal_feeder_ipaddr = NULL;
-	c->wal_feeder_port = 0;
+	c->replication_source = NULL;
 	c->namespace = NULL;
 }
 
@@ -72,8 +72,11 @@ fill_default_tarantool_cfg(tarantool_cfg *c) {
 	c->__confetti_flags = 0;
 
 	c->username = NULL;
+	c->bind_ipaddr = strdup("INADDR_ANY");
+	if (c->bind_ipaddr == NULL) return CNF_NOMEMORY;
 	c->coredump = 0;
 	c->admin_port = 0;
+	c->replication_port = 0;
 	c->log_level = 4;
 	c->slab_alloc_arena = 1;
 	c->slab_alloc_minimal = 64;
@@ -107,9 +110,7 @@ fill_default_tarantool_cfg(tarantool_cfg *c) {
 	c->wal_dir_rescan_delay = 0.1;
 	c->panic_on_snap_error = 1;
 	c->panic_on_wal_error = 0;
-	c->remote_hot_standby = 0;
-	c->wal_feeder_ipaddr = NULL;
-	c->wal_feeder_port = 0;
+	c->replication_source = NULL;
 	c->namespace = NULL;
 	return 0;
 }
@@ -150,12 +151,18 @@ acceptDefault_name__namespace__index__key_field(tarantool_cfg_namespace_index_ke
 static NameAtom _name__username[] = {
 	{ "username", -1, NULL }
 };
+static NameAtom _name__bind_ipaddr[] = {
+	{ "bind_ipaddr", -1, NULL }
+};
 static NameAtom _name__coredump[] = {
 	{ "coredump", -1, NULL }
 };
 static NameAtom _name__admin_port[] = {
 	{ "admin_port", -1, NULL }
 };
+static NameAtom _name__replication_port[] = {
+	{ "replication_port", -1, NULL }
+};
 static NameAtom _name__log_level[] = {
 	{ "log_level", -1, NULL }
 };
@@ -246,14 +253,8 @@ static NameAtom _name__panic_on_snap_error[] = {
 static NameAtom _name__panic_on_wal_error[] = {
 	{ "panic_on_wal_error", -1, NULL }
 };
-static NameAtom _name__remote_hot_standby[] = {
-	{ "remote_hot_standby", -1, NULL }
-};
-static NameAtom _name__wal_feeder_ipaddr[] = {
-	{ "wal_feeder_ipaddr", -1, NULL }
-};
-static NameAtom _name__wal_feeder_port[] = {
-	{ "wal_feeder_port", -1, NULL }
+static NameAtom _name__replication_source[] = {
+	{ "replication_source", -1, NULL }
 };
 static NameAtom _name__namespace[] = {
 	{ "namespace", -1, NULL }
@@ -344,6 +345,17 @@ acceptValue(tarantool_cfg* c, OptDef* opt, int check_rdonly) {
 		if (opt->paramValue.stringval && c->username == NULL)
 			return CNF_NOMEMORY;
 	}
+	else if ( cmpNameAtoms( opt->name, _name__bind_ipaddr) ) {
+		if (opt->paramType != stringType )
+			return CNF_WRONGTYPE;
+		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
+		errno = 0;
+		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->bind_ipaddr == NULL) || strcmp(opt->paramValue.stringval, c->bind_ipaddr) != 0))
+			return CNF_RDONLY;
+		c->bind_ipaddr = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
+		if (opt->paramValue.stringval && c->bind_ipaddr == NULL)
+			return CNF_NOMEMORY;
+	}
 	else if ( cmpNameAtoms( opt->name, _name__coredump) ) {
 		if (opt->paramType != numberType )
 			return CNF_WRONGTYPE;
@@ -372,6 +384,20 @@ acceptValue(tarantool_cfg* c, OptDef* opt, int check_rdonly) {
 			return CNF_RDONLY;
 		c->admin_port = i32;
 	}
+	else if ( cmpNameAtoms( opt->name, _name__replication_port) ) {
+		if (opt->paramType != numberType )
+			return CNF_WRONGTYPE;
+		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
+		errno = 0;
+		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
+		if (i32 == 0 && errno == EINVAL)
+			return CNF_WRONGINT;
+		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
+			return CNF_WRONGRANGE;
+		if (check_rdonly && c->replication_port != i32)
+			return CNF_RDONLY;
+		c->replication_port = i32;
+	}
 	else if ( cmpNameAtoms( opt->name, _name__log_level) ) {
 		if (opt->paramType != numberType )
 			return CNF_WRONGTYPE;
@@ -752,39 +778,15 @@ acceptValue(tarantool_cfg* c, OptDef* opt, int check_rdonly) {
 			return CNF_RDONLY;
 		c->panic_on_wal_error = i32;
 	}
-	else if ( cmpNameAtoms( opt->name, _name__remote_hot_standby) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		c->remote_hot_standby = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__wal_feeder_ipaddr) ) {
+	else if ( cmpNameAtoms( opt->name, _name__replication_source) ) {
 		if (opt->paramType != stringType )
 			return CNF_WRONGTYPE;
 		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
 		errno = 0;
-		c->wal_feeder_ipaddr = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->wal_feeder_ipaddr == NULL)
+		c->replication_source = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
+		if (opt->paramValue.stringval && c->replication_source == NULL)
 			return CNF_NOMEMORY;
 	}
-	else if ( cmpNameAtoms( opt->name, _name__wal_feeder_port) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		c->wal_feeder_port = i32;
-	}
 	else if ( cmpNameAtoms( opt->name, _name__namespace) ) {
 		if (opt->paramType != arrayType )
 			return CNF_WRONGTYPE;
@@ -1062,8 +1064,10 @@ parse_cfg_buffer_tarantool_cfg(tarantool_cfg *c, char *buffer, int check_rdonly,
 typedef enum IteratorState {
 	_S_Initial = 0,
 	S_name__username,
+	S_name__bind_ipaddr,
 	S_name__coredump,
 	S_name__admin_port,
+	S_name__replication_port,
 	S_name__log_level,
 	S_name__slab_alloc_arena,
 	S_name__slab_alloc_minimal,
@@ -1094,9 +1098,7 @@ typedef enum IteratorState {
 	S_name__wal_dir_rescan_delay,
 	S_name__panic_on_snap_error,
 	S_name__panic_on_wal_error,
-	S_name__remote_hot_standby,
-	S_name__wal_feeder_ipaddr,
-	S_name__wal_feeder_port,
+	S_name__replication_source,
 	S_name__namespace,
 	S_name__namespace__enabled,
 	S_name__namespace__cardinality,
@@ -1142,6 +1144,16 @@ tarantool_cfg_iterator_next(tarantool_cfg_iterator_t* i, tarantool_cfg *c, char
 				return NULL;
 			}
 			snprintf(buf, PRINTBUFLEN-1, "username");
+			i->state = S_name__bind_ipaddr;
+			return buf;
+		case S_name__bind_ipaddr:
+			*v = (c->bind_ipaddr) ? strdup(c->bind_ipaddr) : NULL;
+			if (*v == NULL && c->bind_ipaddr) {
+				free(i);
+				out_warning(CNF_NOMEMORY, "No memory to output value");
+				return NULL;
+			}
+			snprintf(buf, PRINTBUFLEN-1, "bind_ipaddr");
 			i->state = S_name__coredump;
 			return buf;
 		case S_name__coredump:
@@ -1164,6 +1176,17 @@ tarantool_cfg_iterator_next(tarantool_cfg_iterator_t* i, tarantool_cfg *c, char
 			}
 			sprintf(*v, "%"PRId32, c->admin_port);
 			snprintf(buf, PRINTBUFLEN-1, "admin_port");
+			i->state = S_name__replication_port;
+			return buf;
+		case S_name__replication_port:
+			*v = malloc(32);
+			if (*v == NULL) {
+				free(i);
+				out_warning(CNF_NOMEMORY, "No memory to output value");
+				return NULL;
+			}
+			sprintf(*v, "%"PRId32, c->replication_port);
+			snprintf(buf, PRINTBUFLEN-1, "replication_port");
 			i->state = S_name__log_level;
 			return buf;
 		case S_name__log_level:
@@ -1488,38 +1511,16 @@ tarantool_cfg_iterator_next(tarantool_cfg_iterator_t* i, tarantool_cfg *c, char
 			}
 			sprintf(*v, "%"PRId32, c->panic_on_wal_error);
 			snprintf(buf, PRINTBUFLEN-1, "panic_on_wal_error");
-			i->state = S_name__remote_hot_standby;
-			return buf;
-		case S_name__remote_hot_standby:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->remote_hot_standby);
-			snprintf(buf, PRINTBUFLEN-1, "remote_hot_standby");
-			i->state = S_name__wal_feeder_ipaddr;
-			return buf;
-		case S_name__wal_feeder_ipaddr:
-			*v = (c->wal_feeder_ipaddr) ? strdup(c->wal_feeder_ipaddr) : NULL;
-			if (*v == NULL && c->wal_feeder_ipaddr) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "wal_feeder_ipaddr");
-			i->state = S_name__wal_feeder_port;
+			i->state = S_name__replication_source;
 			return buf;
-		case S_name__wal_feeder_port:
-			*v = malloc(32);
-			if (*v == NULL) {
+		case S_name__replication_source:
+			*v = (c->replication_source) ? strdup(c->replication_source) : NULL;
+			if (*v == NULL && c->replication_source) {
 				free(i);
 				out_warning(CNF_NOMEMORY, "No memory to output value");
 				return NULL;
 			}
-			sprintf(*v, "%"PRId32, c->wal_feeder_port);
-			snprintf(buf, PRINTBUFLEN-1, "wal_feeder_port");
+			snprintf(buf, PRINTBUFLEN-1, "replication_source");
 			i->state = S_name__namespace;
 			return buf;
 		case S_name__namespace:
@@ -1805,8 +1806,12 @@ dup_tarantool_cfg(tarantool_cfg* dst, tarantool_cfg* src) {
 	dst->username = src->username == NULL ? NULL : strdup(src->username);
 	if (src->username != NULL && dst->username == NULL)
 		return CNF_NOMEMORY;
+	dst->bind_ipaddr = src->bind_ipaddr == NULL ? NULL : strdup(src->bind_ipaddr);
+	if (src->bind_ipaddr != NULL && dst->bind_ipaddr == NULL)
+		return CNF_NOMEMORY;
 	dst->coredump = src->coredump;
 	dst->admin_port = src->admin_port;
+	dst->replication_port = src->replication_port;
 	dst->log_level = src->log_level;
 	dst->slab_alloc_arena = src->slab_alloc_arena;
 	dst->slab_alloc_minimal = src->slab_alloc_minimal;
@@ -1849,11 +1854,9 @@ dup_tarantool_cfg(tarantool_cfg* dst, tarantool_cfg* src) {
 	dst->wal_dir_rescan_delay = src->wal_dir_rescan_delay;
 	dst->panic_on_snap_error = src->panic_on_snap_error;
 	dst->panic_on_wal_error = src->panic_on_wal_error;
-	dst->remote_hot_standby = src->remote_hot_standby;
-	dst->wal_feeder_ipaddr = src->wal_feeder_ipaddr == NULL ? NULL : strdup(src->wal_feeder_ipaddr);
-	if (src->wal_feeder_ipaddr != NULL && dst->wal_feeder_ipaddr == NULL)
+	dst->replication_source = src->replication_source == NULL ? NULL : strdup(src->replication_source);
+	if (src->replication_source != NULL && dst->replication_source == NULL)
 		return CNF_NOMEMORY;
-	dst->wal_feeder_port = src->wal_feeder_port;
 
 	dst->namespace = NULL;
 	if (src->namespace != NULL) {
@@ -1916,6 +1919,8 @@ destroy_tarantool_cfg(tarantool_cfg* c) {
 
 	if (c->username != NULL)
 		free(c->username);
+	if (c->bind_ipaddr != NULL)
+		free(c->bind_ipaddr);
 	if (c->work_dir != NULL)
 		free(c->work_dir);
 	if (c->pid_file != NULL)
@@ -1928,8 +1933,8 @@ destroy_tarantool_cfg(tarantool_cfg* c) {
 		free(c->wal_dir);
 	if (c->custom_proc_title != NULL)
 		free(c->custom_proc_title);
-	if (c->wal_feeder_ipaddr != NULL)
-		free(c->wal_feeder_ipaddr);
+	if (c->replication_source != NULL)
+		free(c->replication_source);
 
 	if (c->namespace != NULL) {
 		i->idx_name__namespace = 0;
@@ -1996,6 +2001,11 @@ cmp_tarantool_cfg(tarantool_cfg* c1, tarantool_cfg* c2, int only_check_rdonly) {
 
 		return diff;
 }
+	if (confetti_strcmp(c1->bind_ipaddr, c2->bind_ipaddr) != 0) {
+		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->bind_ipaddr");
+
+		return diff;
+}
 	if (c1->coredump != c2->coredump) {
 		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->coredump");
 
@@ -2006,6 +2016,11 @@ cmp_tarantool_cfg(tarantool_cfg* c1, tarantool_cfg* c2, int only_check_rdonly) {
 
 		return diff;
 	}
+	if (c1->replication_port != c2->replication_port) {
+		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->replication_port");
+
+		return diff;
+	}
 	if (!only_check_rdonly) {
 		if (c1->log_level != c2->log_level) {
 			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->log_level");
@@ -2167,26 +2182,12 @@ cmp_tarantool_cfg(tarantool_cfg* c1, tarantool_cfg* c2, int only_check_rdonly) {
 		return diff;
 	}
 	if (!only_check_rdonly) {
-		if (c1->remote_hot_standby != c2->remote_hot_standby) {
-			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->remote_hot_standby");
-
-			return diff;
-		}
-	}
-	if (!only_check_rdonly) {
-		if (confetti_strcmp(c1->wal_feeder_ipaddr, c2->wal_feeder_ipaddr) != 0) {
-			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->wal_feeder_ipaddr");
+		if (confetti_strcmp(c1->replication_source, c2->replication_source) != 0) {
+			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->replication_source");
 
 			return diff;
 }
 	}
-	if (!only_check_rdonly) {
-		if (c1->wal_feeder_port != c2->wal_feeder_port) {
-			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->wal_feeder_port");
-
-			return diff;
-		}
-	}
 
 	i1->idx_name__namespace = 0;
 	i2->idx_name__namespace = 0;
diff --git a/cfg/tarantool_box_cfg.cfg b/cfg/tarantool_box_cfg.cfg
index b5ade814456d550e5152f803864a2c136a907917..3b2e6f843551889a9154ec3c4689613c94220008 100644
--- a/cfg/tarantool_box_cfg.cfg
+++ b/cfg/tarantool_box_cfg.cfg
@@ -2,6 +2,10 @@
 # username to switch to
 username = NULL
 
+# tarantool bind ip address, applies to master
+# and replication ports. INADDR_ANY is the default value.
+bind_ipaddr = "INADDR_ANY"
+
 # save core on abort/assert
 # deprecated; use ulimit instead
 coredump = 0
@@ -10,6 +14,9 @@ coredump = 0
 # used for admin's connections
 admin_port = 0
 
+# Replication clients should use this port (bind_ipaddr:replication_port).
+replication_port = 0
+
 # Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5
 log_level = 4
 
@@ -95,8 +102,10 @@ wal_fsync_delay = 0
 # size of WAL writer request buffer
 wal_writer_inbox_size = 128
 
-# Local hot standby (if enabled, the server will run in local hot standby
-# mode, continuously fetching WAL records from shared local directory).
+# Local hot standby (if enabled, the server will run in hot
+# standby mode, continuously fetching WAL records from wal_dir,
+# until it is able to bind to the primary port.
+# In local hot standby mode the server only accepts reads.
 local_hot_standby = 0
 
 # Delay, in seconds, between successive re-readings of wal_dir.
@@ -109,11 +118,12 @@ wal_dir_rescan_delay = 0.1
 panic_on_snap_error = 1
 panic_on_wal_error = 0
 
-# Remote hot standby (if enabled, the server will run in hot standby mode
-# continuously fetching WAL records from wal_feeder_ipaddr:wal_feeder_port
-remote_hot_standby = 0
-wal_feeder_ipaddr = NULL
-wal_feeder_port = 0
+# Replication mode (if enabled, the server, once
+# bound to the primary port, will connect to
+# replication_source (ipaddr:port) and run continously
+# fetching records from it.. In replication mode the server
+# only accepts reads.
+replication_source = NULL
 namespace = [    {
         enabled = -1
         cardinality = -1
diff --git a/cfg/tarantool_box_cfg.h b/cfg/tarantool_box_cfg.h
index e81d06c4c4f958c85d877e7f4a0425e8c7b19d1c..eda7d13bfca328b02ccadb7c9996d698b00456fe 100644
--- a/cfg/tarantool_box_cfg.h
+++ b/cfg/tarantool_box_cfg.h
@@ -39,6 +39,12 @@ typedef struct tarantool_cfg {
 	/* username to switch to */
 	char*	username;
 
+	/*
+	 * tarantool bind ip address, applies to master
+	 * and replication ports. INADDR_ANY is the default value.
+	 */
+	char*	bind_ipaddr;
+
 	/*
 	 * save core on abort/assert
 	 * deprecated; use ulimit instead
@@ -51,6 +57,9 @@ typedef struct tarantool_cfg {
 	 */
 	int32_t	admin_port;
 
+	/* Replication clients should use this port (bind_ipaddr:replication_port). */
+	int32_t	replication_port;
+
 	/* Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5 */
 	int32_t	log_level;
 
@@ -145,8 +154,10 @@ typedef struct tarantool_cfg {
 	int32_t	wal_writer_inbox_size;
 
 	/*
-	 * Local hot standby (if enabled, the server will run in local hot standby
-	 * mode, continuously fetching WAL records from shared local directory).
+	 * Local hot standby (if enabled, the server will run in hot
+	 * standby mode, continuously fetching WAL records from wal_dir,
+	 * until it is able to bind to the primary port.
+	 * In local hot standby mode the server only accepts reads.
 	 */
 	int32_t	local_hot_standby;
 
@@ -165,12 +176,13 @@ typedef struct tarantool_cfg {
 	int32_t	panic_on_wal_error;
 
 	/*
-	 * Remote hot standby (if enabled, the server will run in hot standby mode
-	 * continuously fetching WAL records from wal_feeder_ipaddr:wal_feeder_port
+	 * Replication mode (if enabled, the server, once
+	 * bound to the primary port, will connect to
+	 * replication_source (ipaddr:port) and run continously
+	 * fetching records from it.. In replication mode the server
+	 * only accepts reads.
 	 */
-	int32_t	remote_hot_standby;
-	char*	wal_feeder_ipaddr;
-	int32_t	wal_feeder_port;
+	char*	replication_source;
 	tarantool_cfg_namespace**	namespace;
 } tarantool_cfg;
 
diff --git a/cfg/tarantool_feeder_cfg.c b/cfg/tarantool_feeder_cfg.c
deleted file mode 100644
index 3f5fb82f1f76f89b82bb06505d7c8671b3a8e58f..0000000000000000000000000000000000000000
--- a/cfg/tarantool_feeder_cfg.c
+++ /dev/null
@@ -1,946 +0,0 @@
-#include <errno.h>
-#include <limits.h>
-#include <inttypes.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-
-/*
- * Autogenerated file, do not edit it!
- */
-
-
-#include "cfg/warning.h"
-#include "cfg/tarantool_feeder_cfg.h"
-static int
-cmpNameAtoms(NameAtom *a, NameAtom *b) {
-	while(a && b) {
-		if (strcasecmp(a->name, b->name) != 0)
-			return 0;
-		a = a->next;
-		b = b->next;
-	}
-	return (a == NULL && b == NULL) ? 1 : 0;
-}
-
-void
-init_tarantool_cfg(tarantool_cfg *c) {
-	c->__confetti_flags = 0;
-
-	c->username = NULL;
-	c->coredump = 0;
-	c->admin_port = 0;
-	c->log_level = 0;
-	c->slab_alloc_arena = 0;
-	c->slab_alloc_minimal = 0;
-	c->slab_alloc_factor = 0;
-	c->work_dir = NULL;
-	c->pid_file = NULL;
-	c->logger = NULL;
-	c->logger_nonblock = 0;
-	c->io_collect_interval = 0;
-	c->backlog = 0;
-	c->readahead = 0;
-	c->wal_feeder_bind_ipaddr = NULL;
-	c->wal_feeder_bind_port = 0;
-	c->wal_feeder_dir = NULL;
-	c->custom_proc_title = NULL;
-}
-
-int
-fill_default_tarantool_cfg(tarantool_cfg *c) {
-	c->__confetti_flags = 0;
-
-	c->username = NULL;
-	c->coredump = 0;
-	c->admin_port = 0;
-	c->log_level = 4;
-	c->slab_alloc_arena = 1;
-	c->slab_alloc_minimal = 64;
-	c->slab_alloc_factor = 2;
-	c->work_dir = NULL;
-	c->pid_file = strdup("tarantool.pid");
-	if (c->pid_file == NULL) return CNF_NOMEMORY;
-	c->logger = NULL;
-	c->logger_nonblock = 1;
-	c->io_collect_interval = 0;
-	c->backlog = 1024;
-	c->readahead = 16320;
-	c->wal_feeder_bind_ipaddr = NULL;
-	c->wal_feeder_bind_port = 0;
-	c->wal_feeder_dir = NULL;
-	c->custom_proc_title = NULL;
-	return 0;
-}
-
-void
-swap_tarantool_cfg(struct tarantool_cfg *c1, struct tarantool_cfg *c2) {
-	struct tarantool_cfg tmpcfg = *c1;
-	*c1 = *c2;
-	*c2 = tmpcfg;
-}
-
-static NameAtom _name__username[] = {
-	{ "username", -1, NULL }
-};
-static NameAtom _name__coredump[] = {
-	{ "coredump", -1, NULL }
-};
-static NameAtom _name__admin_port[] = {
-	{ "admin_port", -1, NULL }
-};
-static NameAtom _name__log_level[] = {
-	{ "log_level", -1, NULL }
-};
-static NameAtom _name__slab_alloc_arena[] = {
-	{ "slab_alloc_arena", -1, NULL }
-};
-static NameAtom _name__slab_alloc_minimal[] = {
-	{ "slab_alloc_minimal", -1, NULL }
-};
-static NameAtom _name__slab_alloc_factor[] = {
-	{ "slab_alloc_factor", -1, NULL }
-};
-static NameAtom _name__work_dir[] = {
-	{ "work_dir", -1, NULL }
-};
-static NameAtom _name__pid_file[] = {
-	{ "pid_file", -1, NULL }
-};
-static NameAtom _name__logger[] = {
-	{ "logger", -1, NULL }
-};
-static NameAtom _name__logger_nonblock[] = {
-	{ "logger_nonblock", -1, NULL }
-};
-static NameAtom _name__io_collect_interval[] = {
-	{ "io_collect_interval", -1, NULL }
-};
-static NameAtom _name__backlog[] = {
-	{ "backlog", -1, NULL }
-};
-static NameAtom _name__readahead[] = {
-	{ "readahead", -1, NULL }
-};
-static NameAtom _name__wal_feeder_bind_ipaddr[] = {
-	{ "wal_feeder_bind_ipaddr", -1, NULL }
-};
-static NameAtom _name__wal_feeder_bind_port[] = {
-	{ "wal_feeder_bind_port", -1, NULL }
-};
-static NameAtom _name__wal_feeder_dir[] = {
-	{ "wal_feeder_dir", -1, NULL }
-};
-static NameAtom _name__custom_proc_title[] = {
-	{ "custom_proc_title", -1, NULL }
-};
-
-#define ARRAYALLOC(x,n,t,_chk_ro, __flags)  do {                    \
-   int l = 0, ar;                                                   \
-   __typeof__(x) y = (x), t;                                        \
-   if ( (n) <= 0 ) return CNF_WRONGINDEX; /* wrong index */         \
-   while(y && *y) {                                                 \
-       l++; y++;                                                    \
-   }                                                                \
-   if ( (n) >= (l + 1) ) {                                          \
-      if (_chk_ro)  return CNF_RDONLY;                              \
-      if ( (x) == NULL )                                            \
-          t = y = malloc( ((n)+1) * sizeof( __typeof__(*(x))) );    \
-      else {                                                        \
-          t = realloc((x), ((n)+1) * sizeof( __typeof__(*(x))) );   \
-          y = t + l;                                                \
-      }                                                             \
-      if (t == NULL)  return CNF_NOMEMORY;                          \
-      (x) = t;                                                      \
-      memset(y, 0, (((n)+1) - l) * sizeof( __typeof__(*(x))) );     \
-      while ( y - (x) < (n) ) {                                     \
-          *y = malloc( sizeof( __typeof__(**(x))) );                \
-          if (*y == NULL)  return CNF_NOMEMORY;                     \
-          if ( (ar = acceptDefault##t(*y)) != 0 ) return ar;        \
-          (*y)->__confetti_flags = __flags;                         \
-          y++;                                                      \
-      }                                                             \
-   }                                                                \
-} while(0)
-
-static ConfettyError
-acceptValue(tarantool_cfg* c, OptDef* opt, int check_rdonly) {
-
-	if ( cmpNameAtoms( opt->name, _name__username) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->username == NULL) || strcmp(opt->paramValue.stringval, c->username) != 0))
-			return CNF_RDONLY;
-		c->username = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->username == NULL)
-			return CNF_NOMEMORY;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__coredump) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->coredump != i32)
-			return CNF_RDONLY;
-		c->coredump = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__admin_port) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->admin_port != i32)
-			return CNF_RDONLY;
-		c->admin_port = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__log_level) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		c->log_level = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__slab_alloc_arena) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		double dbl = strtod(opt->paramValue.numberval, NULL);
-		if ( (dbl == 0 || dbl == -HUGE_VAL || dbl == HUGE_VAL) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->slab_alloc_arena != dbl)
-			return CNF_RDONLY;
-		c->slab_alloc_arena = dbl;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__slab_alloc_minimal) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->slab_alloc_minimal != i32)
-			return CNF_RDONLY;
-		c->slab_alloc_minimal = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__slab_alloc_factor) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		double dbl = strtod(opt->paramValue.numberval, NULL);
-		if ( (dbl == 0 || dbl == -HUGE_VAL || dbl == HUGE_VAL) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->slab_alloc_factor != dbl)
-			return CNF_RDONLY;
-		c->slab_alloc_factor = dbl;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__work_dir) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->work_dir == NULL) || strcmp(opt->paramValue.stringval, c->work_dir) != 0))
-			return CNF_RDONLY;
-		c->work_dir = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->work_dir == NULL)
-			return CNF_NOMEMORY;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__pid_file) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->pid_file == NULL) || strcmp(opt->paramValue.stringval, c->pid_file) != 0))
-			return CNF_RDONLY;
-		c->pid_file = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->pid_file == NULL)
-			return CNF_NOMEMORY;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__logger) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->logger == NULL) || strcmp(opt->paramValue.stringval, c->logger) != 0))
-			return CNF_RDONLY;
-		c->logger = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->logger == NULL)
-			return CNF_NOMEMORY;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__logger_nonblock) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->logger_nonblock != i32)
-			return CNF_RDONLY;
-		c->logger_nonblock = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__io_collect_interval) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		double dbl = strtod(opt->paramValue.numberval, NULL);
-		if ( (dbl == 0 || dbl == -HUGE_VAL || dbl == HUGE_VAL) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->io_collect_interval != dbl)
-			return CNF_RDONLY;
-		c->io_collect_interval = dbl;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__backlog) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->backlog != i32)
-			return CNF_RDONLY;
-		c->backlog = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__readahead) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		c->readahead = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__wal_feeder_bind_ipaddr) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->wal_feeder_bind_ipaddr == NULL) || strcmp(opt->paramValue.stringval, c->wal_feeder_bind_ipaddr) != 0))
-			return CNF_RDONLY;
-		c->wal_feeder_bind_ipaddr = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->wal_feeder_bind_ipaddr == NULL)
-			return CNF_NOMEMORY;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__wal_feeder_bind_port) ) {
-		if (opt->paramType != numberType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		long int i32 = strtol(opt->paramValue.numberval, NULL, 10);
-		if (i32 == 0 && errno == EINVAL)
-			return CNF_WRONGINT;
-		if ( (i32 == LONG_MIN || i32 == LONG_MAX) && errno == ERANGE)
-			return CNF_WRONGRANGE;
-		if (check_rdonly && c->wal_feeder_bind_port != i32)
-			return CNF_RDONLY;
-		c->wal_feeder_bind_port = i32;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__wal_feeder_dir) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->wal_feeder_dir == NULL) || strcmp(opt->paramValue.stringval, c->wal_feeder_dir) != 0))
-			return CNF_RDONLY;
-		c->wal_feeder_dir = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->wal_feeder_dir == NULL)
-			return CNF_NOMEMORY;
-	}
-	else if ( cmpNameAtoms( opt->name, _name__custom_proc_title) ) {
-		if (opt->paramType != stringType )
-			return CNF_WRONGTYPE;
-		c->__confetti_flags &= ~CNF_FLAG_STRUCT_NOTSET;
-		errno = 0;
-		if (check_rdonly && ( (opt->paramValue.stringval == NULL && c->custom_proc_title == NULL) || strcmp(opt->paramValue.stringval, c->custom_proc_title) != 0))
-			return CNF_RDONLY;
-		c->custom_proc_title = (opt->paramValue.stringval) ? strdup(opt->paramValue.stringval) : NULL;
-		if (opt->paramValue.stringval && c->custom_proc_title == NULL)
-			return CNF_NOMEMORY;
-	}
-	else {
-		return CNF_MISSED;
-	}
-	return CNF_OK;
-}
-
-static void cleanFlags(tarantool_cfg* c, OptDef* opt);
-
-#define PRINTBUFLEN	8192
-static char*
-dumpOptDef(NameAtom *atom) {
-	static char	buf[PRINTBUFLEN], *ptr;
-	int  i = 0;
-
-	ptr = buf;
-	while(atom) {
-		if (i) ptr += snprintf(ptr, PRINTBUFLEN - 1 - (ptr - buf), ".");
-		ptr += snprintf(ptr, PRINTBUFLEN - 1 - (ptr - buf), "%s", atom->name);
-		if (atom->index >= 0)
-			ptr += snprintf(ptr, PRINTBUFLEN - 1 - (ptr - buf), "[%d]", atom->index);
-		i = 1;
-		atom = atom->next;
-	}
-	return buf;
-}
-
-static void
-acceptCfgDef(tarantool_cfg *c, OptDef *opt, int check_rdonly, int *n_accepted, int *n_skipped) {
-	ConfettyError	r;
-	OptDef		*orig_opt = opt;
-
-	if (n_accepted) *n_accepted=0;
-	if (n_skipped) *n_skipped=0;
-
-	while(opt) {
-		r = acceptValue(c, opt, check_rdonly);
-		switch(r) {
-			case CNF_OK:
-				if (n_accepted) (*n_accepted)++;
-				break;
-			case CNF_MISSED:
-				out_warning(r, "Could not find '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_WRONGTYPE:
-				out_warning(r, "Wrong value type for '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_WRONGINDEX:
-				out_warning(r, "Wrong array index in '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_RDONLY:
-				out_warning(r, "Could not accept read only '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_WRONGINT:
-				out_warning(r, "Could not parse integer value for '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_WRONGRANGE:
-				out_warning(r, "Wrong range for '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_NOMEMORY:
-				out_warning(r, "Not enough memory to accept '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			case CNF_NOTSET:
-				out_warning(r, "Option '%s' is not set (or has a default value)", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-			default:
-				out_warning(r, "Unknown error for '%s' option", dumpOptDef(opt->name));
-				if (n_skipped) (*n_skipped)++;
-				break;
-		}
-
-		opt = opt->next;
-	}
-
-	cleanFlags(c, orig_opt);
-}
-
-void
-parse_cfg_file_tarantool_cfg(tarantool_cfg *c, FILE *fh, int check_rdonly, int *n_accepted, int *n_skipped) {
-	OptDef *option;
-
-	option = parseCfgDef(fh);
-	acceptCfgDef(c, option, check_rdonly, n_accepted, n_skipped);
-	freeCfgDef(option);
-}
-
-void
-parse_cfg_buffer_tarantool_cfg(tarantool_cfg *c, char *buffer, int check_rdonly, int *n_accepted, int *n_skipped) {
-	OptDef *option;
-
-	option = parseCfgDefBuffer(buffer);
-	acceptCfgDef(c, option, check_rdonly, n_accepted, n_skipped);
-	freeCfgDef(option);
-}
-
-/************** Iterator **************/
-typedef enum IteratorState {
-	_S_Initial = 0,
-	S_name__username,
-	S_name__coredump,
-	S_name__admin_port,
-	S_name__log_level,
-	S_name__slab_alloc_arena,
-	S_name__slab_alloc_minimal,
-	S_name__slab_alloc_factor,
-	S_name__work_dir,
-	S_name__pid_file,
-	S_name__logger,
-	S_name__logger_nonblock,
-	S_name__io_collect_interval,
-	S_name__backlog,
-	S_name__readahead,
-	S_name__wal_feeder_bind_ipaddr,
-	S_name__wal_feeder_bind_port,
-	S_name__wal_feeder_dir,
-	S_name__custom_proc_title,
-	_S_Finished
-} IteratorState;
-
-struct tarantool_cfg_iterator_t {
-	IteratorState	state;
-};
-
-tarantool_cfg_iterator_t*
-tarantool_cfg_iterator_init() {
-	tarantool_cfg_iterator_t *i = malloc(sizeof(*i));
-	if (i == NULL) return NULL;
-	memset(i, 0, sizeof(*i));
-	return i;
-}
-
-char*
-tarantool_cfg_iterator_next(tarantool_cfg_iterator_t* i, tarantool_cfg *c, char **v) {
-	static char	buf[PRINTBUFLEN];
-
-	*v = NULL;
-	goto again; /* keep compiler quiet */
-again:
-	switch(i->state) {
-		case _S_Initial:
-		case S_name__username:
-			*v = (c->username) ? strdup(c->username) : NULL;
-			if (*v == NULL && c->username) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "username");
-			i->state = S_name__coredump;
-			return buf;
-		case S_name__coredump:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->coredump);
-			snprintf(buf, PRINTBUFLEN-1, "coredump");
-			i->state = S_name__admin_port;
-			return buf;
-		case S_name__admin_port:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->admin_port);
-			snprintf(buf, PRINTBUFLEN-1, "admin_port");
-			i->state = S_name__log_level;
-			return buf;
-		case S_name__log_level:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->log_level);
-			snprintf(buf, PRINTBUFLEN-1, "log_level");
-			i->state = S_name__slab_alloc_arena;
-			return buf;
-		case S_name__slab_alloc_arena:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%g", c->slab_alloc_arena);
-			snprintf(buf, PRINTBUFLEN-1, "slab_alloc_arena");
-			i->state = S_name__slab_alloc_minimal;
-			return buf;
-		case S_name__slab_alloc_minimal:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->slab_alloc_minimal);
-			snprintf(buf, PRINTBUFLEN-1, "slab_alloc_minimal");
-			i->state = S_name__slab_alloc_factor;
-			return buf;
-		case S_name__slab_alloc_factor:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%g", c->slab_alloc_factor);
-			snprintf(buf, PRINTBUFLEN-1, "slab_alloc_factor");
-			i->state = S_name__work_dir;
-			return buf;
-		case S_name__work_dir:
-			*v = (c->work_dir) ? strdup(c->work_dir) : NULL;
-			if (*v == NULL && c->work_dir) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "work_dir");
-			i->state = S_name__pid_file;
-			return buf;
-		case S_name__pid_file:
-			*v = (c->pid_file) ? strdup(c->pid_file) : NULL;
-			if (*v == NULL && c->pid_file) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "pid_file");
-			i->state = S_name__logger;
-			return buf;
-		case S_name__logger:
-			*v = (c->logger) ? strdup(c->logger) : NULL;
-			if (*v == NULL && c->logger) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "logger");
-			i->state = S_name__logger_nonblock;
-			return buf;
-		case S_name__logger_nonblock:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->logger_nonblock);
-			snprintf(buf, PRINTBUFLEN-1, "logger_nonblock");
-			i->state = S_name__io_collect_interval;
-			return buf;
-		case S_name__io_collect_interval:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%g", c->io_collect_interval);
-			snprintf(buf, PRINTBUFLEN-1, "io_collect_interval");
-			i->state = S_name__backlog;
-			return buf;
-		case S_name__backlog:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->backlog);
-			snprintf(buf, PRINTBUFLEN-1, "backlog");
-			i->state = S_name__readahead;
-			return buf;
-		case S_name__readahead:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->readahead);
-			snprintf(buf, PRINTBUFLEN-1, "readahead");
-			i->state = S_name__wal_feeder_bind_ipaddr;
-			return buf;
-		case S_name__wal_feeder_bind_ipaddr:
-			*v = (c->wal_feeder_bind_ipaddr) ? strdup(c->wal_feeder_bind_ipaddr) : NULL;
-			if (*v == NULL && c->wal_feeder_bind_ipaddr) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "wal_feeder_bind_ipaddr");
-			i->state = S_name__wal_feeder_bind_port;
-			return buf;
-		case S_name__wal_feeder_bind_port:
-			*v = malloc(32);
-			if (*v == NULL) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			sprintf(*v, "%"PRId32, c->wal_feeder_bind_port);
-			snprintf(buf, PRINTBUFLEN-1, "wal_feeder_bind_port");
-			i->state = S_name__wal_feeder_dir;
-			return buf;
-		case S_name__wal_feeder_dir:
-			*v = (c->wal_feeder_dir) ? strdup(c->wal_feeder_dir) : NULL;
-			if (*v == NULL && c->wal_feeder_dir) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "wal_feeder_dir");
-			i->state = S_name__custom_proc_title;
-			return buf;
-		case S_name__custom_proc_title:
-			*v = (c->custom_proc_title) ? strdup(c->custom_proc_title) : NULL;
-			if (*v == NULL && c->custom_proc_title) {
-				free(i);
-				out_warning(CNF_NOMEMORY, "No memory to output value");
-				return NULL;
-			}
-			snprintf(buf, PRINTBUFLEN-1, "custom_proc_title");
-			i->state = _S_Finished;
-			return buf;
-		case _S_Finished:
-			free(i);
-			break;
-		default:
-			out_warning(CNF_INTERNALERROR, "Unknown state for tarantool_cfg_iterator_t: %d", i->state);
-			free(i);
-	}
-	return NULL;
-}
-
-/************** Checking of required fields  **************/
-int
-check_cfg_tarantool_cfg(tarantool_cfg *c) {
-	tarantool_cfg_iterator_t iterator, *i = &iterator;
-	int	res = 0;
-
-	if (c->wal_feeder_bind_ipaddr == NULL) {
-		res++;
-		out_warning(CNF_NOTSET, "Option '%s' is not set (or has a default value)", dumpOptDef(_name__wal_feeder_bind_ipaddr));
-	}
-	if (c->wal_feeder_bind_port == 0) {
-		res++;
-		out_warning(CNF_NOTSET, "Option '%s' is not set (or has a default value)", dumpOptDef(_name__wal_feeder_bind_port));
-	}
-	if (c->wal_feeder_dir == NULL) {
-		res++;
-		out_warning(CNF_NOTSET, "Option '%s' is not set (or has a default value)", dumpOptDef(_name__wal_feeder_dir));
-	}
-	return res;
-}
-
-static void
-cleanFlags(tarantool_cfg* c, OptDef* opt) {
-	tarantool_cfg_iterator_t iterator, *i = &iterator;
-
-}
-
-/************** Duplicate config  **************/
-
-int
-dup_tarantool_cfg(tarantool_cfg* dst, tarantool_cfg* src) {
-	tarantool_cfg_iterator_t iterator, *i = &iterator;
-
-	dst->username = src->username == NULL ? NULL : strdup(src->username);
-	if (src->username != NULL && dst->username == NULL)
-		return CNF_NOMEMORY;
-	dst->coredump = src->coredump;
-	dst->admin_port = src->admin_port;
-	dst->log_level = src->log_level;
-	dst->slab_alloc_arena = src->slab_alloc_arena;
-	dst->slab_alloc_minimal = src->slab_alloc_minimal;
-	dst->slab_alloc_factor = src->slab_alloc_factor;
-	dst->work_dir = src->work_dir == NULL ? NULL : strdup(src->work_dir);
-	if (src->work_dir != NULL && dst->work_dir == NULL)
-		return CNF_NOMEMORY;
-	dst->pid_file = src->pid_file == NULL ? NULL : strdup(src->pid_file);
-	if (src->pid_file != NULL && dst->pid_file == NULL)
-		return CNF_NOMEMORY;
-	dst->logger = src->logger == NULL ? NULL : strdup(src->logger);
-	if (src->logger != NULL && dst->logger == NULL)
-		return CNF_NOMEMORY;
-	dst->logger_nonblock = src->logger_nonblock;
-	dst->io_collect_interval = src->io_collect_interval;
-	dst->backlog = src->backlog;
-	dst->readahead = src->readahead;
-	dst->wal_feeder_bind_ipaddr = src->wal_feeder_bind_ipaddr == NULL ? NULL : strdup(src->wal_feeder_bind_ipaddr);
-	if (src->wal_feeder_bind_ipaddr != NULL && dst->wal_feeder_bind_ipaddr == NULL)
-		return CNF_NOMEMORY;
-	dst->wal_feeder_bind_port = src->wal_feeder_bind_port;
-	dst->wal_feeder_dir = src->wal_feeder_dir == NULL ? NULL : strdup(src->wal_feeder_dir);
-	if (src->wal_feeder_dir != NULL && dst->wal_feeder_dir == NULL)
-		return CNF_NOMEMORY;
-	dst->custom_proc_title = src->custom_proc_title == NULL ? NULL : strdup(src->custom_proc_title);
-	if (src->custom_proc_title != NULL && dst->custom_proc_title == NULL)
-		return CNF_NOMEMORY;
-
-	return CNF_OK;
-}
-
-/************** Destroy config  **************/
-
-void
-destroy_tarantool_cfg(tarantool_cfg* c) {
-	tarantool_cfg_iterator_t iterator, *i = &iterator;
-
-	if (c->username != NULL)
-		free(c->username);
-	if (c->work_dir != NULL)
-		free(c->work_dir);
-	if (c->pid_file != NULL)
-		free(c->pid_file);
-	if (c->logger != NULL)
-		free(c->logger);
-	if (c->wal_feeder_bind_ipaddr != NULL)
-		free(c->wal_feeder_bind_ipaddr);
-	if (c->wal_feeder_dir != NULL)
-		free(c->wal_feeder_dir);
-	if (c->custom_proc_title != NULL)
-		free(c->custom_proc_title);
-}
-
-/************** Compare config  **************/
-
-int
-confetti_strcmp(char *s1, char *s2) {
-	if (s1 == NULL || s2 == NULL) {
-		if (s1 != s2)
-			return s1 == NULL ? -1 : 1;
-		else
-			return 0;
-	}
-
-	return strcmp(s1, s2);
-}
-
-char *
-cmp_tarantool_cfg(tarantool_cfg* c1, tarantool_cfg* c2, int only_check_rdonly) {
-	tarantool_cfg_iterator_t iterator1, iterator2, *i1 = &iterator1, *i2 = &iterator2;
-	static char diff[PRINTBUFLEN];
-
-	if (confetti_strcmp(c1->username, c2->username) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->username");
-
-		return diff;
-}
-	if (c1->coredump != c2->coredump) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->coredump");
-
-		return diff;
-	}
-	if (c1->admin_port != c2->admin_port) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->admin_port");
-
-		return diff;
-	}
-	if (!only_check_rdonly) {
-		if (c1->log_level != c2->log_level) {
-			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->log_level");
-
-			return diff;
-		}
-	}
-	if (c1->slab_alloc_arena != c2->slab_alloc_arena) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->slab_alloc_arena");
-
-		return diff;
-	}
-	if (c1->slab_alloc_minimal != c2->slab_alloc_minimal) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->slab_alloc_minimal");
-
-		return diff;
-	}
-	if (c1->slab_alloc_factor != c2->slab_alloc_factor) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->slab_alloc_factor");
-
-		return diff;
-	}
-	if (confetti_strcmp(c1->work_dir, c2->work_dir) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->work_dir");
-
-		return diff;
-}
-	if (confetti_strcmp(c1->pid_file, c2->pid_file) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->pid_file");
-
-		return diff;
-}
-	if (confetti_strcmp(c1->logger, c2->logger) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->logger");
-
-		return diff;
-}
-	if (c1->logger_nonblock != c2->logger_nonblock) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->logger_nonblock");
-
-		return diff;
-	}
-	if (c1->io_collect_interval != c2->io_collect_interval) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->io_collect_interval");
-
-		return diff;
-	}
-	if (c1->backlog != c2->backlog) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->backlog");
-
-		return diff;
-	}
-	if (!only_check_rdonly) {
-		if (c1->readahead != c2->readahead) {
-			snprintf(diff, PRINTBUFLEN - 1, "%s", "c->readahead");
-
-			return diff;
-		}
-	}
-	if (confetti_strcmp(c1->wal_feeder_bind_ipaddr, c2->wal_feeder_bind_ipaddr) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->wal_feeder_bind_ipaddr");
-
-		return diff;
-}
-	if (c1->wal_feeder_bind_port != c2->wal_feeder_bind_port) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->wal_feeder_bind_port");
-
-		return diff;
-	}
-	if (confetti_strcmp(c1->wal_feeder_dir, c2->wal_feeder_dir) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->wal_feeder_dir");
-
-		return diff;
-}
-	if (confetti_strcmp(c1->custom_proc_title, c2->custom_proc_title) != 0) {
-		snprintf(diff, PRINTBUFLEN - 1, "%s", "c->custom_proc_title");
-
-		return diff;
-}
-
-	return 0;
-}
-
diff --git a/cfg/tarantool_feeder_cfg.cfg b/cfg/tarantool_feeder_cfg.cfg
deleted file mode 100644
index c8407c3fb5afddedd81128534fce9ed90cd47525..0000000000000000000000000000000000000000
--- a/cfg/tarantool_feeder_cfg.cfg
+++ /dev/null
@@ -1,58 +0,0 @@
-
-# username to switch to
-username = NULL
-
-# save core on abort/assert
-# deprecated; use ulimit instead
-coredump = 0
-
-# admin port
-# used for admin's connections
-admin_port = 0
-
-# Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5
-log_level = 4
-
-# Size of slab arena in GB
-slab_alloc_arena = 1
-
-# Size of minimal allocation unit
-slab_alloc_minimal = 64
-
-# Growth factor, each subsequent unit size is factor * prev unit size
-slab_alloc_factor = 2
-
-# working directory (daemon will chdir(2) to it)
-work_dir = NULL
-
-# name of pid file
-pid_file = "tarantool.pid"
-
-# logger command will be executed via /bin/sh -c {}
-# example: 'exec cronolog /var/log/tarantool/%Y-%m/%Y-%m-%d/tarantool.log'
-# example: 'exec extra/logger.pl /var/log/tarantool/tarantool.log'
-# when logger is not configured all logging going to STDERR
-logger = NULL
-
-# make logging nonblocking, this potentially can lose some logging data
-logger_nonblock = 1
-
-# delay between loop iterations
-io_collect_interval = 0
-
-# size of listen backlog
-backlog = 1024
-
-# network io readahead
-readahead = 16320
-
-# feed WAL to remote replicas
-# feeder accepts it's clients on wal_feeder_bind_ipaddr:wal_feeder_bind_port
-wal_feeder_bind_ipaddr = NULL
-wal_feeder_bind_port = 0
-
-# Directory with WAL files to serve
-wal_feeder_dir = NULL
-
-# custom proc title is appended after normal
-custom_proc_title = NULL
diff --git a/cfg/tarantool_feeder_cfg.h b/cfg/tarantool_feeder_cfg.h
deleted file mode 100644
index 5ac2d0a5f34e51daf5b7d37bd4b2877a6044444d..0000000000000000000000000000000000000000
--- a/cfg/tarantool_feeder_cfg.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef tarantool_cfg_CFG_H
-#define tarantool_cfg_CFG_H
-
-#include <stdio.h>
-#include <sys/types.h>
-
-/*
- * Autogenerated file, do not edit it!
- */
-
-typedef struct tarantool_cfg {
-	unsigned char __confetti_flags;
-
-
-	/* username to switch to */
-	char*	username;
-
-	/*
-	 * save core on abort/assert
-	 * deprecated; use ulimit instead
-	 */
-	int32_t	coredump;
-
-	/*
-	 * admin port
-	 * used for admin's connections
-	 */
-	int32_t	admin_port;
-
-	/* Log verbosity, possible values: ERROR=1, CRIT=2, WARN=3, INFO=4(default), DEBUG=5 */
-	int32_t	log_level;
-
-	/* Size of slab arena in GB */
-	double	slab_alloc_arena;
-
-	/* Size of minimal allocation unit */
-	int32_t	slab_alloc_minimal;
-
-	/* Growth factor, each subsequent unit size is factor * prev unit size */
-	double	slab_alloc_factor;
-
-	/* working directory (daemon will chdir(2) to it) */
-	char*	work_dir;
-
-	/* name of pid file */
-	char*	pid_file;
-
-	/*
-	 * logger command will be executed via /bin/sh -c {}
-	 * example: 'exec cronolog /var/log/tarantool/%Y-%m/%Y-%m-%d/tarantool.log'
-	 * example: 'exec extra/logger.pl /var/log/tarantool/tarantool.log'
-	 * when logger is not configured all logging going to STDERR
-	 */
-	char*	logger;
-
-	/* make logging nonblocking, this potentially can lose some logging data */
-	int32_t	logger_nonblock;
-
-	/* delay between loop iterations */
-	double	io_collect_interval;
-
-	/* size of listen backlog */
-	int32_t	backlog;
-
-	/* network io readahead */
-	int32_t	readahead;
-
-	/*
-	 * feed WAL to remote replicas
-	 * feeder accepts it's clients on wal_feeder_bind_ipaddr:wal_feeder_bind_port
-	 */
-	char*	wal_feeder_bind_ipaddr;
-	int32_t	wal_feeder_bind_port;
-
-	/* Directory with WAL files to serve */
-	char*	wal_feeder_dir;
-
-	/* custom proc title is appended after normal */
-	char*	custom_proc_title;
-} tarantool_cfg;
-
-#ifndef CNF_FLAG_STRUCT_NEW
-#define CNF_FLAG_STRUCT_NEW	0x01
-#endif
-#ifndef CNF_FLAG_STRUCT_NOTSET
-#define CNF_FLAG_STRUCT_NOTSET	0x02
-#endif
-#ifndef CNF_STRUCT_DEFINED
-#define CNF_STRUCT_DEFINED(s) ((s) != NULL && ((s)->__confetti_flags & CNF_FLAG_STRUCT_NOTSET) == 0)
-#endif
-
-void init_tarantool_cfg(tarantool_cfg *c);
-
-int fill_default_tarantool_cfg(tarantool_cfg *c);
-
-void swap_tarantool_cfg(struct tarantool_cfg *c1, struct tarantool_cfg *c2);
-
-void parse_cfg_file_tarantool_cfg(tarantool_cfg *c, FILE *fh, int check_rdonly, int *n_accepted, int *n_skipped);
-
-void parse_cfg_buffer_tarantool_cfg(tarantool_cfg *c, char *buffer, int check_rdonly, int *n_accepted, int *n_skipped);
-
-int check_cfg_tarantool_cfg(tarantool_cfg *c);
-
-int dup_tarantool_cfg(tarantool_cfg *dst, tarantool_cfg *src);
-
-void destroy_tarantool_cfg(tarantool_cfg *c);
-
-char *cmp_tarantool_cfg(tarantool_cfg* c1, tarantool_cfg* c2, int only_check_rdonly);
-
-typedef struct tarantool_cfg_iterator_t tarantool_cfg_iterator_t;
-tarantool_cfg_iterator_t* tarantool_cfg_iterator_init();
-char* tarantool_cfg_iterator_next(tarantool_cfg_iterator_t* i, tarantool_cfg *c, char **v);
-
-#endif
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index cd698f0e5bb10c6b7533bc9196265c0442710ba1..f154b95e6cad04e6ff0de8fd585ac2d3cf833b2c 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -52,6 +52,7 @@ set (recompiled_core_sources
      ${CMAKE_SOURCE_DIR}/core/tarantool.m
      ${CMAKE_SOURCE_DIR}/core/say.m
      ${CMAKE_SOURCE_DIR}/core/admin.m
+     ${CMAKE_SOURCE_DIR}/core/replication.m
      ${CMAKE_SOURCE_DIR}/core/fiber.m PARENT_SCOPE)
 
 set (common_sources tbuf.m palloc.m util.m
diff --git a/core/admin.m b/core/admin.m
index 412dc7b8868b918a84f51db2f8f62170c8c162a5..62d74731f0cbf62a96967c4f81c5a7e0a77dfabb 100644
--- a/core/admin.m
+++ b/core/admin.m
@@ -1477,7 +1477,7 @@ admin_handler(void *_data __attribute__((unused)))
 int
 admin_init(void)
 {
-	if (fiber_server(cfg.admin_port, admin_handler, NULL, NULL) == NULL) {
+	if (fiber_server("admin", cfg.admin_port, admin_handler, NULL, NULL) == NULL) {
 		say_syserror("can't bind to %d", cfg.admin_port);
 		return -1;
 	}
diff --git a/core/admin.rl b/core/admin.rl
index 81265ecf7a57c87b87a9ca15ec80eb1d978d7141..992b179715146eaf160b32df0dc84ee08d663c14 100644
--- a/core/admin.rl
+++ b/core/admin.rl
@@ -223,7 +223,7 @@ admin_handler(void *_data __attribute__((unused)))
 int
 admin_init(void)
 {
-	if (fiber_server(cfg.admin_port, admin_handler, NULL, NULL) == NULL) {
+	if (fiber_server("admin", cfg.admin_port, admin_handler, NULL, NULL) == NULL) {
 		say_syserror("can't bind to %d", cfg.admin_port);
 		return -1;
 	}
diff --git a/core/fiber.m b/core/fiber.m
index c0b83055f0f27b7a1e98b7523ff45540203f0dcb..0ccd53a5038d69a561bf13d3349f52aa8c5d7c8e 100644
--- a/core/fiber.m
+++ b/core/fiber.m
@@ -256,21 +256,21 @@ wait_for_child(pid_t pid)
 }
 
 
-static void
-fiber_io_start(int events)
+void
+fiber_io_start(int fd, int events)
 {
 	ev_io *io = &fiber->io;
 
 	assert (!ev_is_active(io));
 
-	ev_io_set(io, fiber->fd, events);
+	ev_io_set(io, fd, events);
 	ev_io_start(io);
 }
 
 /** @note: this is a cancellation point.
  */
 
-static void
+void
 fiber_io_yield()
 {
 	assert(ev_is_active(&fiber->io));
@@ -285,12 +285,12 @@ fiber_io_yield()
 	}
 }
 
-static void
-fiber_io_stop(int events __attribute__((unused)))
+void
+fiber_io_stop(int fd __attribute__((unused)), int events __attribute__((unused)))
 {
 	ev_io *io = &fiber->io;
 
-	assert(ev_is_active(io) && io->fd == fiber->fd && (io->events & events));
+	assert(ev_is_active(io) && io->fd == fd && (io->events & events));
 
 	ev_io_stop(io);
 }
@@ -490,7 +490,7 @@ fiber_create(const char *name, int fd, int inbox_size, void (*f) (void *), void
 		if (tarantool_coro_create(&fiber->coro, fiber_loop, NULL) == NULL)
 			return NULL;
 
-		fiber->pool = palloc_create_pool(name);
+		fiber->pool = palloc_create_pool("");
 		fiber->inbox = palloc(eter_pool, (sizeof(*fiber->inbox) +
 						  inbox_size * sizeof(struct tbuf *)));
 		fiber->inbox->size = inbox_size;
@@ -581,7 +581,7 @@ fiber_close(void)
 
 	/* We don't know if IO is active if there was an error. */
 	if (ev_is_active(&fiber->io))
-		fiber_io_stop(-1);
+		fiber_io_stop(fiber->fd, -1);
 
 	int r = close(fiber->fd);
 
@@ -675,7 +675,7 @@ fiber_bread(struct tbuf *buf, size_t at_least)
 	ssize_t r;
 	tbuf_ensure(buf, MAX(cfg.readahead, at_least));
 
-	fiber_io_start(EV_READ);
+	fiber_io_start(fiber->fd, EV_READ);
 	for (;;) {
 		fiber_io_yield();
 		r = read(fiber->fd, buf->data + buf->len, buf->size - buf->len);
@@ -689,7 +689,7 @@ fiber_bread(struct tbuf *buf, size_t at_least)
 			break;
 		}
 	}
-	fiber_io_stop(EV_READ);
+	fiber_io_stop(fiber->fd, EV_READ);
 
 	return r;
 }
@@ -713,7 +713,7 @@ fiber_flush_output(void)
 	struct iovec *iov = iovec(fiber->iov);
 	size_t iov_cnt = fiber->iov_cnt;
 
-	fiber_io_start(EV_WRITE);
+	fiber_io_start(fiber->fd, EV_WRITE);
 	while (iov_cnt > 0) {
 		fiber_io_yield();
 		bytes += r = writev(fiber->fd, iov, MIN(iov_cnt, IOV_MAX));
@@ -736,7 +736,7 @@ fiber_flush_output(void)
 			}
 		}
 	}
-	fiber_io_stop(EV_WRITE);
+	fiber_io_stop(fiber->fd, EV_WRITE);
 
 	if (r < 0) {
 		size_t rem = 0;
@@ -762,7 +762,7 @@ fiber_read(void *buf, size_t count)
 {
 	ssize_t r, done = 0;
 
-	fiber_io_start(EV_READ);
+	fiber_io_start(fiber->fd, EV_READ);
 	while (count != done) {
 
 		fiber_io_yield();
@@ -775,7 +775,7 @@ fiber_read(void *buf, size_t count)
 		}
 		done += r;
 	}
-	fiber_io_stop(EV_READ);
+	fiber_io_stop(fiber->fd, EV_READ);
 
 	return done;
 }
@@ -790,7 +790,7 @@ fiber_write(const void *buf, size_t count)
 	int r;
 	unsigned int done = 0;
 
-	fiber_io_start(EV_WRITE);
+	fiber_io_start(fiber->fd, EV_WRITE);
 
 	while (count != done) {
 		fiber_io_yield();
@@ -802,7 +802,7 @@ fiber_write(const void *buf, size_t count)
 		}
 		done += r;
 	}
-	fiber_io_stop(EV_WRITE);
+	fiber_io_stop(fiber->fd, EV_WRITE);
 
 	return done;
 }
@@ -826,9 +826,9 @@ fiber_connect(struct sockaddr_in *addr)
 		if (errno != EINPROGRESS)
 			goto error;
 
-		fiber_io_start(EV_WRITE);
+		fiber_io_start(fiber->fd, EV_WRITE);
 		fiber_io_yield();
-		fiber_io_stop(EV_WRITE);
+		fiber_io_stop(fiber->fd, EV_WRITE);
 
 		int error;
 		socklen_t error_size = sizeof(error);
@@ -1029,7 +1029,7 @@ struct child *
 spawn_child(const char *name, int inbox_size, struct tbuf *(*handler) (void *, struct tbuf *),
 	    void *state)
 {
-	char *proxy_name;
+	char proxy_name[FIBER_NAME_MAXLEN];
 	int socks[2];
 	int pid;
 
@@ -1051,12 +1051,10 @@ spawn_child(const char *name, int inbox_size, struct tbuf *(*handler) (void *, s
 		struct child *c = palloc(eter_pool, sizeof(*c));
 		c->pid = pid;
 
-		proxy_name = palloc(eter_pool, 64);
-		snprintf(proxy_name, 64, "%s/sock2inbox", name);
+		snprintf(proxy_name, sizeof(proxy_name), "%s/sock2inbox", name);
 		c->in = fiber_create(proxy_name, socks[1], inbox_size, sock2inbox, NULL);
 		fiber_call(c->in);
-		proxy_name = palloc(eter_pool, 64);
-		snprintf(proxy_name, 64, "%s/inbox2sock", name);
+		snprintf(proxy_name, sizeof(proxy_name), "%s/inbox2sock", name);
 		c->out = fiber_create(proxy_name, socks[1], inbox_size, inbox2sock, NULL);
 		c->out->flags |= FIBER_READING_INBOX;
 		return c;
@@ -1071,7 +1069,7 @@ spawn_child(const char *name, int inbox_size, struct tbuf *(*handler) (void *, s
 		close_all_xcpt(2, socks[0], sayfd);
 		snprintf(child_name, sizeof(child_name), "%s/child", name);
 		fiber_set_name(&sched, child_name);
-		set_proc_title(name);
+		set_proc_title("%s%s", name, custom_proc_title);
 		say_crit("%s initialized", name);
 		blocking_loop(socks[0], handler, state);
 	}
@@ -1082,64 +1080,20 @@ tcp_server_handler(void *data)
 {
 	struct fiber_server *server = fiber->data;
 	struct fiber *h;
-	char name[64];
+	char name[FIBER_NAME_MAXLEN];
 	int fd;
-	bool warning_said = false;
 	int one = 1;
-	struct sockaddr_in sin;
-	struct linger ling = { 0, 0 };
 
-	if ((fiber->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
-		say_syserror("socket");
+	if (fiber_serv_socket(fiber, server->port, true, 0.1) != 0) {
+		say_error("init server socket on port %i fail", server->port);
 		exit(EX_OSERR);
 	}
 
-	if (setsockopt(fiber->fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1 ||
-	    setsockopt(fiber->fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)) == -1 ||
-	    setsockopt(fiber->fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) == -1 ||
-	    setsockopt(fiber->fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) == -1) {
-		say_syserror("setsockopt");
-		exit(EX_OSERR);
-	}
-
-	if (set_nonblock(fiber->fd) == -1)
-		exit(EX_OSERR);
-
-	memset(&sin, 0, sizeof(struct sockaddr_in));
-	sin.sin_family = AF_INET;
-	sin.sin_port = htons(server->port);
-	sin.sin_addr.s_addr = INADDR_ANY;
-
-	for (;;) {
-		if (bind(fiber->fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
-			if (errno == EADDRINUSE)
-				goto sleep_and_retry;
-			say_syserror("bind");
-			exit(EX_OSERR);
-		}
-		if (listen(fiber->fd, cfg.backlog) == -1) {
-			if (errno == EADDRINUSE)
-				goto sleep_and_retry;
-			say_syserror("listen");
-			exit(EX_OSERR);
-		}
-
-		say_info("bound to TCP port %i", server->port);
-		break;
-
-	      sleep_and_retry:
-		if (!warning_said) {
-			say_warn("port %i is already in use, "
-				 "will retry binding after 0.1 seconds.", server->port);
-			warning_said = true;
-		}
-		fiber_sleep(0.1);
-	}
-
-	if (server->on_bind != NULL)
+	if (server->on_bind != NULL) {
 		server->on_bind(server->data);
+	}
 
-	fiber_io_start(EV_READ);
+	fiber_io_start(fiber->fd, EV_READ);
 	for (;;) {
 		fiber_io_yield();
 
@@ -1171,19 +1125,18 @@ tcp_server_handler(void *data)
 			continue;
 		}
 	}
-	fiber_io_stop(EV_READ);
+	fiber_io_stop(fiber->fd, EV_READ);
 }
 
 struct fiber *
-fiber_server(int port, void (*handler) (void *data), void *data,
+fiber_server(const char *name, int port, void (*handler) (void *data), void *data,
 	     void (*on_bind) (void *data))
 {
-	char *server_name;
+	char server_name[FIBER_NAME_MAXLEN];
 	struct fiber_server *server;
 	struct fiber *s;
 
-	server_name = palloc(eter_pool, 64);
-	snprintf(server_name, 64, "%i/acceptor", port);
+	snprintf(server_name, sizeof(server_name), "%i/%s", port, name);
 	s = fiber_create(server_name, -1, -1, tcp_server_handler, data);
 	s->data = server = palloc(eter_pool, sizeof(struct fiber_server));
 	assert(server != NULL);
@@ -1195,6 +1148,112 @@ fiber_server(int port, void (*handler) (void *data), void *data,
 	return s;
 }
 
+/** create new fiber's socket and set standat options. */
+static int
+create_socket(struct fiber *fiber)
+{
+	if (fiber->fd != -1) {
+		say_error("fiber is already has socket");
+		goto create_socket_fail;
+	}
+
+	fiber->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (fiber->fd == -1) {
+		say_syserror("socket");
+		goto create_socket_fail;
+	}
+
+	int one = 1;
+	if (setsockopt(fiber->fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) != 0) {
+		say_syserror("setsockopt");
+		goto create_socket_fail;
+	}
+
+	struct linger ling = { 0, 0 };
+	if (setsockopt(fiber->fd, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one)) != 0 ||
+	    setsockopt(fiber->fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) != 0 ||
+	    setsockopt(fiber->fd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)) != 0) {
+		say_syserror("setsockopt");
+		goto create_socket_fail;
+	}
+
+	if (set_nonblock(fiber->fd) == -1) {
+		goto create_socket_fail;
+	}
+
+	return 0;
+
+create_socket_fail:
+
+	if (fiber->fd != -1) {
+		close(fiber->fd);
+	}
+	return -1;
+}
+
+/** Create server socket and bind his on port. */
+int
+fiber_serv_socket(struct fiber *fiber, unsigned short port, bool retry, ev_tstamp delay)
+{
+	const ev_tstamp min_delay = 0.001; /* minimal delay is 1 msec */
+	struct sockaddr_in sin;
+	bool warning_said = false;
+
+	if (delay < min_delay) {
+		delay = min_delay;
+	}
+
+	if (create_socket(fiber) != 0) {
+		return -1;
+	}
+
+	/* clean sockaddr_in struct */
+	memset(&sin, 0, sizeof(struct sockaddr_in));
+
+	/* fill sockaddr_in struct */
+	sin.sin_family = AF_INET;
+	sin.sin_port = htons(port);
+	if (strcmp(cfg.bind_ipaddr, "INADDR_ANY") == 0) {
+		sin.sin_addr.s_addr = INADDR_ANY;
+	} else {
+		if (!inet_aton(cfg.bind_ipaddr, &sin.sin_addr)) {
+			say_syserror("inet_aton");
+			return -1;
+		}
+	}
+
+	while (true) {
+		if (bind(fiber->fd, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
+			if (retry && (errno == EADDRINUSE)) {
+				/* retry mode, try, to bind after delay */
+				goto sleep_and_retry;
+			}
+			say_syserror("bind");
+			return -1;
+		}
+		if (listen(fiber->fd, cfg.backlog) != 0) {
+			if (retry && (errno == EADDRINUSE)) {
+				/* retry mode, try, to bind after delay */
+				goto sleep_and_retry;
+			}
+			say_syserror("listen");
+			return -1;
+		}
+
+		say_info("bound to port %i", port);
+		break;
+
+	sleep_and_retry:
+		if (!warning_said) {
+			say_warn("port %i is already in use, "
+				 "will retry binding after %lf seconds.", port, delay);
+			warning_said = true;
+		}
+		fiber_sleep(delay);
+	}
+
+	return 0;
+}
 
 void
 fiber_info(struct tbuf *out)
diff --git a/core/log_io.m b/core/log_io.m
index 566b4cdbbac5cb5b4cc30e48740e24f839fc3528..58dde06dbaa84a785ab32093b9c20205b2f97652 100644
--- a/core/log_io.m
+++ b/core/log_io.m
@@ -1239,7 +1239,7 @@ write_to_disk(void *_state, struct tbuf *t)
 		goto fail;
 	}
 
-	/* flush stdio buffer to keep feeder in sync */
+	/* flush stdio buffer to keep replication in sync */
 	if (fflush(wal->f) < 0) {
 		say_syserror("can't flush wal");
 		goto fail;
diff --git a/core/log_io_remote.m b/core/log_io_remote.m
index 1d54f9603f6fb5df4a918d87d0c58df588e3994f..f8d11e4b4acf1138ac8a54ab07e1e540dad22b3f 100644
--- a/core/log_io_remote.m
+++ b/core/log_io_remote.m
@@ -39,6 +39,9 @@
 #include <say.h>
 #include <pickle.h>
 
+static int
+default_remote_row_handler(struct recovery_state *r, struct tbuf *row);
+
 static u32
 row_v11_len(struct tbuf *r)
 {
@@ -83,7 +86,7 @@ remote_read_row(i64 initial_lsn)
 	for (;;) {
 		if (fiber->fd < 0) {
 			if (fiber_connect(fiber->data) < 0) {
-				err = "can't connect to feeder";
+				err = "can't connect to master";
 				goto err;
 			}
 
@@ -102,8 +105,9 @@ remote_read_row(i64 initial_lsn)
 				goto err;
 			}
 
-			say_crit("successfully connected to feeder");
+			say_crit("successfully connected to master");
 			say_crit("starting replication from lsn:%" PRIi64, initial_lsn);
+
 			warning_said = false;
 			err = NULL;
 		}
@@ -130,18 +134,18 @@ remote_read_row(i64 initial_lsn)
 static void
 pull_from_remote(void *state)
 {
-	struct remote_state *h = state;
+	struct recovery_state *r = state;
 	struct tbuf *row;
 
 	for (;;) {
 		fiber_setcancelstate(true);
-		row = remote_read_row(h->r->confirmed_lsn + 1);
+		row = remote_read_row(r->confirmed_lsn + 1);
 		fiber_setcancelstate(false);
 
-		h->r->recovery_lag = ev_now() - row_v11(row)->tm;
-		h->r->recovery_last_update_tstamp = ev_now();
+		r->recovery_lag = ev_now() - row_v11(row)->tm;
+		r->recovery_last_update_tstamp = ev_now();
 
-		if (h->handler(h->r, row) < 0) {
+		if (default_remote_row_handler(r, row) < 0) {
 			fiber_close();
 			continue;
 		}
@@ -150,7 +154,7 @@ pull_from_remote(void *state)
 	}
 }
 
-int
+static int
 default_remote_row_handler(struct recovery_state *r, struct tbuf *row)
 {
 	struct tbuf *data;
@@ -177,29 +181,28 @@ default_remote_row_handler(struct recovery_state *r, struct tbuf *row)
 }
 
 void
-recovery_follow_remote(struct recovery_state *r,
-		       const char *ip_addr, int port)
+recovery_follow_remote(struct recovery_state *r, const char *remote)
 {
-	char *name;
+	char name[FIBER_NAME_MAXLEN];
+	char ip_addr[32];
+	int port;
+	int rc;
 	struct fiber *f;
 	struct in_addr server;
 	struct sockaddr_in *addr;
-	struct remote_state *h;
 
 	assert(r->remote_recovery == NULL);
 
-	say_crit("initializing the replica, WAL feeder %s:%i", ip_addr, port);
-	name = palloc(eter_pool, 64);
-	snprintf(name, 64, "replica/%s:%i", ip_addr, port);
+	say_crit("initializing the replica, WAL master %s", remote);
+	snprintf(name, sizeof(name), "replica/%s", remote);
 
-	h = palloc(eter_pool, sizeof(*h));
-	h->r = r;
-	h->handler = default_remote_row_handler;
-
-	f = fiber_create(name, -1, -1, pull_from_remote, h);
+	f = fiber_create(name, -1, -1, pull_from_remote, r);
 	if (f == NULL)
 		return;
 
+	rc = sscanf(remote, "%31[^:]:%i", ip_addr, &port);
+	assert(rc == 2);
+
 	if (inet_aton(ip_addr, &server) < 0) {
 		say_syserror("inet_aton: %s", ip_addr);
 		return;
diff --git a/core/replication.m b/core/replication.m
new file mode 100644
index 0000000000000000000000000000000000000000..12b3872f40086e96ce503fb398f21fbfc02774b3
--- /dev/null
+++ b/core/replication.m
@@ -0,0 +1,653 @@
+/*
+ * Copyright (C) 2011 Mail.RU
+ * Copyright (C) 2011 Yuriy Vostrikov
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <replication.h>
+#include <say.h>
+#include <fiber.h>
+#include TARANTOOL_CONFIG
+#include <palloc.h>
+#include <stddef.h>
+
+#include <stddef.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "fiber.h"
+
+/** Replication topology
+ * ----------------------
+ *
+ * Tarantool replication consists of 3 interacting processes:
+ * master, spawner and replication relay.
+ *
+ * The spawner is created at server start, and master communicates
+ * with the spawner using a socketpair(2). Replication relays are
+ * created by the spawner and handle one client connection each.
+ *
+ * The master process binds to replication_port and accepts
+ * incoming connections. This is done in the master to be able to
+ * correctly handle RELOAD CONFIGURATION, which happens in the
+ * master, and, in future, perform authentication of replication
+ * clients. Since the master uses fibers to serve all clients,
+ * replication acceptor fiber is just one of many fibers in use.
+ * Once a client socket is accepted, it is sent to the spawner
+ * process, through the master's end of the socket pair.
+ *
+ * The spawner listens on the receiving end of the socket pair and
+ * for every received socket creates a replication relay, which is
+ * then responsible for sending write ahead logs to the replica.
+ *
+ * Upon shutdown, the master closes its end of the socket pair.
+ * The spawner then reads EOF from its end, terminates all
+ * children and exits.
+ */
+static int master_to_spawner_sock;
+
+/** replication_port acceptor fiber */
+static void
+acceptor_handler(void *data __attribute__((unused)));
+
+/** Send a file descriptor to replication relay spawner.
+ *
+ * @param client_sock the file descriptor to be sent.
+ */
+static void
+acceptor_send_sock(int client_sock);
+
+/** Replication spawner process */
+static struct spawner {
+	/** reading end of the socket pair with the master */
+	int sock;
+	/** non-zero if got a terminating signal */
+	sig_atomic_t killed;
+	/** child process count */
+	sig_atomic_t child_count;
+} spawner;
+
+/** Initialize spawner process.
+ *
+ * @param sock the socket between the main process and the spawner.
+ */
+static void
+spawner_init(int sock);
+
+/** Spawner main loop. */
+static void
+spawner_main_loop();
+
+/** Shutdown spawner and all its children. */
+static void
+spawner_shutdown();
+
+/** Handle SIGINT, SIGTERM, SIGPIPE, SIGHUP. */
+static void
+spawner_signal_handler(int signal);
+
+/** Handle SIGCHLD: collect status of a terminated child.  */
+static void
+spawner_sigchld_handler(int signal __attribute__((unused)));
+
+/** Create a replication relay.
+ *
+ * @return 0 on success, -1 on error
+ */
+static int
+spawner_create_replication_relay(int client_sock);
+
+/** Shut down all relays when shutting down the spawner. */
+static void
+spawner_shutdown_children();
+
+/** Initialize replication relay process. */
+static void
+replication_relay_loop(int client_sock);
+
+/** A libev callback invoked when a relay client socket is ready
+ * for read. This currently only happens when the client closes
+ * its socket, and we get an EOF.
+ */
+static void
+replication_relay_recv(struct ev_io *w, int revents);
+
+/** Send a single row to the client. */
+static int
+replication_relay_send_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t);
+
+
+/*-----------------------------------------------------------------------------*/
+/* replication module                                                          */
+/*-----------------------------------------------------------------------------*/
+
+/** Check replication module configuration. */
+int
+replication_check_config(struct tarantool_cfg *config)
+{
+	if (config->replication_port < 0 ||
+	    config->replication_port >= USHRT_MAX) {
+		say_error("invalid replication port value: %"PRId32,
+			  config->replication_port);
+		return -1;
+	}
+
+	return 0;
+}
+
+/** Pre-fork replication spawner process. */
+void
+replication_prefork()
+{
+	if (cfg.replication_port == 0) {
+		/* replication is not needed, do nothing */
+		return;
+	}
+	int sockpair[2];
+	/*
+	 * Create UNIX sockets to communicate between the main and
+	 * spawner processes.
+         */
+	if (socketpair(PF_LOCAL, SOCK_STREAM, 0, sockpair) != 0)
+		panic_syserror("socketpair");
+
+	/* create spawner */
+	pid_t pid = fork();
+	if (pid == -1)
+		panic_syserror("fork");
+
+	if (pid != 0) {
+		/* parent process: tarantool */
+		close(sockpair[1]);
+		master_to_spawner_sock = sockpair[0];
+		if (set_nonblock(master_to_spawner_sock) == -1)
+			panic("set_nonblock");
+	} else {
+		/* child process: spawner */
+		close(sockpair[0]);
+		/*
+		 * Move to an own process group, to not receive
+		 * signals from the controlling tty.
+		 */
+		setpgid(0, 0);
+		spawner_init(sockpair[1]);
+	}
+}
+
+/**
+ * Create a fiber which accepts client connections and pushes them
+ * to replication spawner.
+ */
+
+void
+replication_init()
+{
+	if (cfg.replication_port == 0)
+		return;                        /* replication is not in use */
+
+	char fiber_name[FIBER_NAME_MAXLEN];
+
+	/* create acceptor fiber */
+	snprintf(fiber_name, FIBER_NAME_MAXLEN, "%i/replication", cfg.replication_port);
+
+	struct fiber *acceptor = fiber_create(fiber_name, -1, -1, acceptor_handler, NULL);
+
+	if (acceptor == NULL) {
+		panic("create fiber fail");
+	}
+
+	fiber_call(acceptor);
+}
+
+
+/*-----------------------------------------------------------------------------*/
+/* replication accept/sender fibers                                            */
+/*-----------------------------------------------------------------------------*/
+
+/** Replication acceptor fiber handler. */
+static void
+acceptor_handler(void *data __attribute__((unused)))
+{
+	if (fiber_serv_socket(fiber, cfg.replication_port, true, 0.1) != 0) {
+		panic("can not bind to replication port");
+	}
+
+	for (;;) {
+		struct sockaddr_in addr;
+		socklen_t addrlen = sizeof(addr);
+		int client_sock = -1;
+
+		/* wait new connection request */
+		fiber_io_start(fiber->fd, EV_READ);
+		fiber_io_yield();
+		/* accept connection */
+		client_sock = accept(fiber->fd, &addr, &addrlen);
+		if (client_sock == -1) {
+			if (errno == EAGAIN && errno == EWOULDBLOCK) {
+				continue;
+			}
+			panic_syserror("accept");
+		}
+		fiber_io_stop(fiber->fd, EV_READ);
+		say_info("connection from %s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
+		acceptor_send_sock(client_sock);
+	}
+}
+
+
+/** Send a file descriptor to the spawner. */
+static void
+acceptor_send_sock(int client_sock)
+{
+	struct msghdr msg;
+	struct iovec iov[1];
+	char control_buf[CMSG_SPACE(sizeof(int))];
+	struct cmsghdr *control_message = NULL;
+	int cmd_code = 0;
+
+	iov[0].iov_base = &cmd_code;
+	iov[0].iov_len = sizeof(cmd_code);
+
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = control_buf;
+	msg.msg_controllen = sizeof(control_buf);
+
+	control_message = CMSG_FIRSTHDR(&msg);
+	control_message->cmsg_len = CMSG_LEN(sizeof(int));
+	control_message->cmsg_level = SOL_SOCKET;
+	control_message->cmsg_type = SCM_RIGHTS;
+	*((int *) CMSG_DATA(control_message)) = client_sock;
+
+	/* wait, when interprocess comm. socket is ready for write */
+	fiber_io_start(master_to_spawner_sock, EV_WRITE);
+	fiber_io_yield();
+	/* send client socket to the spawner */
+	if (sendmsg(master_to_spawner_sock, &msg, 0) < 0)
+		say_syserror("sendmsg");
+
+	fiber_io_stop(master_to_spawner_sock, EV_WRITE);
+	/* close client socket in the main process */
+	close(client_sock);
+}
+
+
+/*-----------------------------------------------------------------------------*/
+/* spawner process                                                             */
+/*-----------------------------------------------------------------------------*/
+
+/** Initialize the spawner. */
+
+static void
+spawner_init(int sock)
+{
+	char name[sizeof(fiber->name)];
+	struct sigaction sa;
+
+	snprintf(name, sizeof(name), "spawner%s", custom_proc_title);
+	fiber_set_name(fiber, name);
+	set_proc_title(name);
+
+	/* init replicator process context */
+	spawner.sock = sock;
+
+	/* init signals */
+	memset(&sa, 0, sizeof(sa));
+	sigemptyset(&sa.sa_mask);
+
+	/*
+	 * The spawner normally does not receive any signals,
+	 * except when sent by a system administrator.
+	 * When the master process terminates, it closes its end
+	 * of the socket pair and this signals to the spawner that
+	 * it's time to die as well. But before exiting, the
+	 * spawner must kill and collect all active replication
+	 * relays. This is why we need to change the default
+	 * signal action here.
+	 */
+	sa.sa_handler = spawner_signal_handler;
+
+	if (sigaction(SIGHUP, &sa, NULL) == -1 ||
+	    sigaction(SIGINT, &sa, NULL) == -1 ||
+	    sigaction(SIGTERM, &sa, NULL) == -1 ||
+	    sigaction(SIGPIPE, &sa, NULL) == -1)
+		say_syserror("sigaction");
+
+	sa.sa_handler = spawner_sigchld_handler;
+
+	if (sigaction(SIGCHLD, &sa, NULL) == -1)
+		say_syserror("sigaction");
+
+	say_crit("initialized");
+	spawner_main_loop();
+}
+
+
+
+static int
+spawner_unpack_cmsg(struct msghdr *msg)
+{
+	struct cmsghdr *control_message;
+	for (control_message = CMSG_FIRSTHDR(msg);
+	     control_message != NULL;
+	     control_message = CMSG_NXTHDR(msg, control_message))
+		if ((control_message->cmsg_level == SOL_SOCKET) &&
+		    (control_message->cmsg_type == SCM_RIGHTS))
+			return *((int *) CMSG_DATA(control_message));
+	assert(false);
+	return -1;
+}
+
+/** Replication spawner process main loop. */
+static void
+spawner_main_loop()
+{
+	struct msghdr msg;
+	struct iovec iov[1];
+	char control_buf[CMSG_SPACE(sizeof(int))];
+	int cmd_code = 0;
+	int client_sock;
+
+	iov[0].iov_base = &cmd_code;
+	iov[0].iov_len = sizeof(cmd_code);
+
+	msg.msg_name = NULL;
+	msg.msg_namelen = 0;
+	msg.msg_iov = iov;
+	msg.msg_iovlen = 1;
+	msg.msg_control = control_buf;
+	msg.msg_controllen = sizeof(control_buf);
+
+	while (!spawner.killed) {
+		int msglen = recvmsg(spawner.sock, &msg, 0);
+		if (msglen > 0) {
+			client_sock = spawner_unpack_cmsg(&msg);
+			spawner_create_replication_relay(client_sock);
+		} else if (msglen == 0) { /* orderly master shutdown */
+			say_info("Exiting: master shutdown");
+			break;
+		} else { /* msglen == -1 */
+			if (errno != EINTR)
+				say_syserror("recvmsg");
+			/* continue, the error may be temporary */
+		}
+	}
+	spawner_shutdown();
+}
+
+/** Replication spawner shutdown. */
+static void
+spawner_shutdown()
+{
+	/* close socket */
+	close(spawner.sock);
+
+	/* kill all children */
+	spawner_shutdown_children();
+
+	exit(EXIT_SUCCESS);
+}
+
+/** Replication spawner signal handler for terminating signals. */
+static void spawner_signal_handler(int signal)
+{
+	say_info("Exiting: %s", strsignal(signal));
+	spawner.killed = signal;
+}
+
+/** Wait for a terminated child. */
+static void
+spawner_sigchld_handler(int signo __attribute__((unused)))
+{
+	do {
+		int exit_status;
+		pid_t pid = waitpid(-1, &exit_status, WNOHANG);
+		switch (pid) {
+		case -1:
+			if (errno != ECHILD)
+				say_syserror("waitpid");
+		case 0: /* no more changes in children status */
+			return;
+		default:
+			spawner.child_count--;
+			say_info("child finished: pid = %d, exit status = %d",
+				 (int) pid, WEXITSTATUS(exit_status));
+		}
+	} while (spawner.child_count > 0);
+}
+
+/** Create replication client handler process. */
+static int
+spawner_create_replication_relay(int client_sock)
+{
+	pid_t pid = fork();
+
+	if (pid < 0) {
+		say_syserror("fork");
+		return -1;
+	}
+
+	if (pid == 0) {
+		close(spawner.sock);
+		replication_relay_loop(client_sock);
+	} else {
+		spawner.child_count++;
+		close(client_sock);
+		say_info("created a replication relay: pid = %d", (int) pid);
+	}
+
+	return 0;
+}
+
+/** Replicator spawner shutdown: kill and wait for children. */
+static void
+spawner_shutdown_children()
+{
+	int kill_signo = SIGTERM, signo;
+	sigset_t mask, orig_mask, alarm_mask;
+
+retry:
+	sigemptyset(&mask);
+	sigaddset(&mask, SIGCHLD);
+	sigaddset(&mask, SIGALRM);
+	/*
+	 * We're going to kill the entire process group, which
+	 * we're part of. Handle the signal sent to ourselves.
+	 */
+	sigaddset(&mask, kill_signo);
+
+	if (spawner.child_count == 0)
+		return;
+
+	/* Block SIGCHLD and SIGALRM to avoid races. */
+	if (sigprocmask(SIG_BLOCK, &mask, &orig_mask)) {
+		say_syserror("sigprocmask");
+		return;
+	}
+
+	/* We'll wait for children no longer than 5 sec.  */
+	alarm(5);
+
+	say_info("sending signal %d to %"PRIu32" children", kill_signo,
+		 (u32) spawner.child_count);
+
+	kill(0, kill_signo);
+
+	say_info("waiting for children for up to 5 seconds");
+
+	while (spawner.child_count > 0) {
+		sigwait(&mask, &signo);
+		if (signo == SIGALRM) {         /* timed out */
+			break;
+		}
+		else if (signo != kill_signo) {
+			assert(signo == SIGCHLD);
+			spawner_sigchld_handler(signo);
+		}
+	}
+
+	/* Reset the alarm. */
+	alarm(0);
+
+	/* Clear possibly pending SIGALRM. */
+	sigpending(&alarm_mask);
+	if (sigismember(&alarm_mask, SIGALRM)) {
+		sigemptyset(&alarm_mask);
+		sigaddset(&alarm_mask, SIGALRM);
+		sigwait(&alarm_mask, &signo);
+	}
+
+	/* Restore the old mask. */
+	if (sigprocmask(SIG_SETMASK, &orig_mask, NULL)) {
+		say_syserror("sigprocmask");
+		return;
+	}
+
+	if (kill_signo == SIGTERM) {
+		kill_signo = SIGKILL;
+		goto retry;
+	}
+}
+
+/** The main loop of replication client service process. */
+static void
+replication_relay_loop(int client_sock)
+{
+	char name[FIBER_NAME_MAXLEN];
+	struct sigaction sa;
+	struct recovery_state *log_io;
+	struct tbuf *ver;
+	i64 lsn;
+	ssize_t r;
+
+	fiber->has_peer = true;
+	fiber->fd = client_sock;
+
+	/* set process title and fiber name */
+	memset(name, 0, sizeof(name));
+	snprintf(name, sizeof(name), "relay/%s", fiber_peer_name(fiber));
+	fiber_set_name(fiber, name);
+	set_proc_title("%s%s", name, custom_proc_title);
+
+	/* init signals */
+	memset(&sa, 0, sizeof(sa));
+	sigemptyset(&sa.sa_mask);
+
+	/* Reset all signals to their defaults. */
+	sa.sa_handler = SIG_DFL;
+	if (sigaction(SIGCHLD, &sa, NULL) == -1 ||
+	    sigaction(SIGHUP, &sa, NULL) == -1 ||
+	    sigaction(SIGINT, &sa, NULL) == -1 ||
+	    sigaction(SIGTERM, &sa, NULL) == -1)
+		say_syserror("sigaction");
+
+	/* Block SIGPIPE, we already handle EPIPE. */
+	sa.sa_handler = SIG_IGN;
+	if (sigaction(SIGPIPE, &sa, NULL) == -1)
+		say_syserror("sigaction");
+
+	r = read(fiber->fd, &lsn, sizeof(lsn));
+	if (r != sizeof(lsn)) {
+		if (r < 0) {
+			panic_syserror("read");
+		}
+		panic("invalid LSN request size: %zu", r);
+	}
+	say_info("starting recovery from lsn:%"PRIi64, lsn);
+
+	ver = tbuf_alloc(fiber->pool);
+	tbuf_append(ver, &default_version, sizeof(default_version));
+	replication_relay_send_row(NULL, ver);
+
+	/* init libev events handlers */
+	ev_default_loop(0);
+
+	/* init read events */
+	struct ev_io sock_read_ev;
+	int sock_read_fd = fiber->fd;
+	sock_read_ev.data = (void *)&sock_read_fd;
+	ev_io_init(&sock_read_ev, replication_relay_recv, sock_read_fd, EV_READ);
+	ev_io_start(&sock_read_ev);
+
+	/* init reovery porcess */
+	log_io = recover_init(NULL, cfg.wal_dir,
+			      replication_relay_send_row, INT32_MAX, 0, 64, RECOVER_READONLY, false);
+
+	recover(log_io, lsn);
+	recover_follow(log_io, 0.1);
+
+	ev_loop(0);
+
+	say_crit("exiting the relay loop");
+	exit(EXIT_SUCCESS);
+}
+
+/** Receive data event to replication socket handler */
+static void
+replication_relay_recv(struct ev_io *w, int __attribute__((unused)) revents)
+{
+	int fd = *((int *)w->data);
+	u8 data;
+
+	int result = recv(fd, &data, sizeof(data), 0);
+
+	if (result == 0 || (result < 0 && errno == ECONNRESET)) {
+		say_info("the client has closed its replication socket, exiting");
+		exit(EXIT_SUCCESS);
+	}
+	if (result < 0)
+		say_syserror("recv");
+
+	exit(EXIT_FAILURE);
+}
+
+/** Send to row to client. */
+static int
+replication_relay_send_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t)
+{
+	u8 *data = t->data;
+	ssize_t bytes, len = t->len;
+	while (len > 0) {
+		bytes = write(fiber->fd, data, len);
+		if (bytes < 0) {
+			if (errno == EPIPE) {
+				/* socket closed on opposite site */
+				goto shutdown_handler;
+			}
+			panic_syserror("write");
+		}
+		len -= bytes;
+		data += bytes;
+	}
+
+	say_debug("send row: %" PRIu32 " bytes %s", t->len, tbuf_to_hex(t));
+	return 0;
+shutdown_handler:
+	say_info("the client has closed its replication socket, exiting");
+	exit(EXIT_SUCCESS);
+}
+
diff --git a/core/tarantool.m b/core/tarantool.m
index ab05b24c98ea2b8758671dfc6d17324c69144625..414bc9120036bc7afb6d1bf8389f0f5d2abefa19 100644
--- a/core/tarantool.m
+++ b/core/tarantool.m
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2010 Mail.RU
- * Copyright (C) 2010 Yuriy Vostrikov
+ * Copyright (C) 2010-2011 Mail.RU
+ * Copyright (C) 2010-2011 Yuriy Vostrikov
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -43,6 +43,7 @@
 # include <sys/prctl.h>
 #endif
 #include <admin.h>
+#include <replication.h>
 #include <fiber.h>
 #include <iproto.h>
 #include <latch.h>
@@ -62,6 +63,8 @@ static pid_t master_pid;
 const char *cfg_filename = DEFAULT_CFG_FILENAME;
 char *cfg_filename_fullpath = NULL;
 char *binary_filename;
+char *custom_proc_title;
+
 struct tarantool_cfg cfg;
 struct recovery_state *recovery_state;
 
@@ -97,6 +100,9 @@ load_cfg(struct tarantool_cfg *conf, i32 check_rdonly)
 	if (n_accepted == 0 || n_skipped != 0)
 		return -1;
 
+	if (replication_check_config(conf) != 0)
+		return -1;
+
 	return mod_check_config(conf);
 }
 
@@ -184,7 +190,6 @@ tarantool_uptime(void)
 	return ev_now() - start_time;
 }
 
-#ifdef STORAGE
 int
 snapshot(void *ev, int events __attribute__((unused)))
 {
@@ -227,7 +232,6 @@ snapshot(void *ev, int events __attribute__((unused)))
 
 	return 0;
 }
-#endif
 
 static void
 sig_int(int signal)
@@ -341,9 +345,7 @@ initialize_minimal()
 int
 main(int argc, char **argv)
 {
-#ifdef STORAGE
 	const char *cat_filename = NULL;
-#endif
 	const char *cfg_paramname = NULL;
 
 #ifndef HAVE_LIBC_STACK_END
@@ -376,13 +378,11 @@ main(int argc, char **argv)
 			   gopt_option('c', GOPT_ARG, gopt_shorts('c'),
 				       gopt_longs("config"),
 				       "=FILE", "path to configuration file (default: " DEFAULT_CFG_FILENAME ")"),
-#ifdef STORAGE
 			   gopt_option('C', GOPT_ARG, gopt_shorts(0), gopt_longs("cat"),
 				       "=FILE", "cat snapshot file to stdout in readable format and exit"),
 			   gopt_option('I', 0, gopt_shorts(0),
 				       gopt_longs("init-storage", "init_storage"),
 				       NULL, "initialize storage (an empty snapshot file) and exit"),
-#endif
 			   gopt_option('v', 0, gopt_shorts('v'), gopt_longs("verbose"),
 				       NULL, "increase verbosity level in log messages"),
 			   gopt_option('B', 0, gopt_shorts('B'), gopt_longs("background"),
@@ -483,7 +483,7 @@ main(int argc, char **argv)
 				exit(EX_OSERR);
 			}
 		} else {
-			say_error("can't swith to %s: i'm not root", cfg.username);
+			say_error("can't switch to %s: i'm not root", cfg.username);
 		}
 	}
 
@@ -506,7 +506,6 @@ main(int argc, char **argv)
 #endif
 	}
 
-#ifdef STORAGE
 	if (gopt_arg(opt, 'C', &cat_filename)) {
 		initialize_minimal();
 		if (access(cat_filename, R_OK) == -1) {
@@ -525,7 +524,6 @@ main(int argc, char **argv)
 		snapshot_save(recovery_state, mod_snapshot);
 		exit(EXIT_SUCCESS);
 	}
-#endif
 
 	if (gopt(opt, 'B'))
 		daemonize(1, 1);
@@ -535,14 +533,21 @@ main(int argc, char **argv)
 		atexit(remove_pid);
 	}
 
+	/* init process title */
+	if (cfg.custom_proc_title == NULL) {
+		custom_proc_title = "";
+	} else {
+		custom_proc_title = palloc(eter_pool, strlen(cfg.custom_proc_title) + 2);
+		strcat(custom_proc_title, "@");
+		strcat(custom_proc_title, cfg.custom_proc_title);
+	}
+
 	say_logger_init(cfg.logger_nonblock);
 	booting = false;
 
-#if defined(UTILITY)
-	initialize_minimal();
-	signal_init();
-	mod_init();
-#elif defined(STORAGE)
+	initialize(cfg.slab_alloc_arena, cfg.slab_alloc_minimal, cfg.slab_alloc_factor);
+	replication_prefork();
+
 	ev_default_loop(EVFLAG_AUTO);
 
 	ev_signal *ev_sig;
@@ -550,11 +555,12 @@ main(int argc, char **argv)
 	ev_signal_init(ev_sig, (void *)snapshot, SIGUSR1);
 	ev_signal_start(ev_sig);
 
-	initialize(cfg.slab_alloc_arena, cfg.slab_alloc_minimal, cfg.slab_alloc_factor);
 	signal_init();
 
 	mod_init();
 	admin_init();
+	replication_init();
+
 	prelease(fiber->pool);
 	say_crit("log level %i", cfg.log_level);
 	say_crit("entering event loop");
@@ -564,8 +570,6 @@ main(int argc, char **argv)
 	start_time = ev_now();
 	ev_loop(0);
 	say_crit("exiting loop");
-#else
-#error UTILITY or STORAGE must be defined
-#endif
+
 	return 0;
 }
diff --git a/include/fiber.h b/include/fiber.h
index ab8cd7e679dc7e6265c270bae709fd22a8e827e1..0a85b7e0d64b438e25edc7f70c1990759c7d5b76 100644
--- a/include/fiber.h
+++ b/include/fiber.h
@@ -42,7 +42,7 @@
 
 #include "exception.h"
 
-#define FIBER_NAME_MAXLEN 16
+#define FIBER_NAME_MAXLEN 32
 
 #define FIBER_READING_INBOX 0x1
 /** Can this fiber be cancelled? */
@@ -129,6 +129,16 @@ void fiber_init(void);
 struct fiber *fiber_create(const char *name, int fd, int inbox_size, void (*f) (void *), void *);
 void fiber_set_name(struct fiber *fiber, const char *name);
 void wait_for_child(pid_t pid);
+
+void
+fiber_io_start(int fd, int events);
+
+void
+fiber_io_yield();
+
+void
+fiber_io_stop(int fd, int events);
+
 void yield(void);
 void fiber_destroy_all();
 
@@ -193,10 +203,24 @@ int set_nonblock(int sock);
 
 typedef void (*fiber_server_callback)(void *);
 
-struct fiber *fiber_server(int port,
+struct fiber *fiber_server(const char *name, int port,
 			   fiber_server_callback callback, void *,
 			   void (*on_bind) (void *));
 
+/**
+ * Create server socket and bind his on port. cfd.bind_ipaddr param using as IP address.
+ *
+ * @param type the fiber server type (TCP or UDP)
+ * @param port the bind ip port.
+ * @param retry the retry flag, if flag up the function will be try again to bind
+ *              socket after delay.
+ * @param delay the bind socket retry delay in sec.
+ *
+ * @return on success, zero is returned. on error, -1 is returned.
+ */
+int
+fiber_serv_socket(struct fiber *fiber, unsigned short port, bool retry, ev_tstamp delay);
+
 struct child *spawn_child(const char *name,
 			  int inbox_size,
 			  struct tbuf *(*handler) (void *, struct tbuf *), void *state);
diff --git a/include/log_io.h b/include/log_io.h
index 1b3214ac91373499d7408f069120bde5f8637be5..a1ce9bd6e3b4bf7beb4cf0c16a8e490336a4343b 100644
--- a/include/log_io.h
+++ b/include/log_io.h
@@ -124,11 +124,6 @@ struct recovery_state {
 	void *data;
 };
 
-struct remote_state {
-	struct recovery_state *r;
-	int (*handler) (struct recovery_state * r, struct tbuf *row);
-};
-
 struct wal_write_request {
 	i64 lsn;
 	u32 len;
@@ -169,8 +164,7 @@ void recovery_wait_lsn(struct recovery_state *r, i64 lsn);
 int read_log(const char *filename,
 	     row_handler xlog_handler, row_handler snap_handler, void *state);
 
-void recovery_follow_remote(struct recovery_state *r,
-			    const char *ip_addr, int port);
+void recovery_follow_remote(struct recovery_state *r, const char *remote);
 void recovery_stop_remote(struct recovery_state *r);
 
 struct log_io_iter;
diff --git a/include/replication.h b/include/replication.h
new file mode 100644
index 0000000000000000000000000000000000000000..252062c50c728e9cd6dcb3ae2881bb1f7d531314
--- /dev/null
+++ b/include/replication.h
@@ -0,0 +1,58 @@
+#ifndef TARANTOOL_REPLICATION_H_INCLUDED
+#define TARANTOOL_REPLICATION_H_INCLUDED
+/*
+ * Copyright (C) 2011 Mail.RU
+ * Copyright (C) 2011 Yuriy Vostrikov
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <tarantool.h>
+#include <util.h>
+
+/**
+ * Check replication configuration.
+ *
+ * @param config  config file to check.
+ *
+ * @return 0 on success, -1 on error
+ */
+int
+replication_check_config(struct tarantool_cfg *config);
+
+/**
+ * Pre-fork replication spawner process.
+ *
+ * @return None. Panics and exits on error.
+ */
+void
+replication_prefork();
+
+/**
+ * Initialize replication module.
+ *
+ * @return None. Panics and exits on error.
+ */
+void
+replication_init();
+
+#endif // TARANTOOL_REPLICATION_H_INCLUDED
+
diff --git a/include/tarantool.h b/include/tarantool.h
index 29301ecdb9c8f8ce602ef8086ca4f56a8246a0e5..e446641ea23954a4ec3221c368869fbce024077c 100644
--- a/include/tarantool.h
+++ b/include/tarantool.h
@@ -46,6 +46,7 @@ extern struct tarantool_cfg cfg;
 extern const char *cfg_filename;
 extern bool init_storage, booting;
 extern char *binary_filename;
+extern char *custom_proc_title;
 i32 reload_cfg(struct tbuf *out);
 int snapshot(void * /* ev */, int /* events */);
 const char *tarantool_version(void);
diff --git a/mod/CMakeLists.txt b/mod/CMakeLists.txt
index b7cc1e1487cdc0f9d5c3596268016da0268c1fbd..c5d680fbeb82b9ae32588d9e6ab5a14eccbc93fc 100644
--- a/mod/CMakeLists.txt
+++ b/mod/CMakeLists.txt
@@ -9,15 +9,9 @@ function(tarantool_module mod)
       ${module_sources}
       ${CMAKE_SOURCE_DIR}/cfg/tarantool_${mod}_cfg.c)
 
-  if (mod STREQUAL "feeder")
-    set (STORAGE_OR_UTILITY "UTILITY")
-  else()
-    set (STORAGE_OR_UTILITY "STORAGE")
-  endif()
-
   add_library(lt${mod} STATIC ${recompiled_core_sources})
   set_target_properties(lt${mod} PROPERTIES COMPILE_FLAGS
-    "${core_cflags} -D${STORAGE_OR_UTILITY} -DTARANTOOL_CONFIG='<cfg/tarantool_${mod}_cfg.h>'")
+    "${core_cflags} -DTARANTOOL_CONFIG='<cfg/tarantool_${mod}_cfg.h>'")
   add_dependencies(lt${mod} generate_headers generate_admin_c)
 
   target_link_libraries(tarantool_${mod} lt${mod} ${common_libraries})
diff --git a/mod/box/box.m b/mod/box/box.m
index ae4e2af7bfde4059e5d8cd311a1339d34bea5e89..dcd1532fbe8c9fbb77fdc6da7521e270e4ddac5c 100644
--- a/mod/box/box.m
+++ b/mod/box/box.m
@@ -58,8 +58,6 @@ static char status[64] = "unknown";
 static int stat_base;
 STRS(messages, MESSAGES);
 
-static char *custom_proc_title;
-
 /* hooks */
 typedef int (*box_hook_t) (struct box_txn * txn);
 
@@ -1172,9 +1170,10 @@ title(const char *fmt, ...)
 	va_end(ap);
 
 	int ports[] = { cfg.primary_port, cfg.secondary_port,
-			cfg.memcached_port, cfg.admin_port };
+			cfg.memcached_port, cfg.admin_port,
+			cfg.replication_port };
 	int *pptr = ports;
-	char *names[] = { "pri", "sec", "memc", "adm", NULL };
+	char *names[] = { "pri", "sec", "memc", "adm", "rpl", NULL };
 	char **nptr = names;
 
 	for (; *nptr; nptr++, pptr++)
@@ -1189,33 +1188,29 @@ title(const char *fmt, ...)
 static void
 box_enter_master_or_replica_mode(struct tarantool_cfg *conf)
 {
-	if (conf->remote_hot_standby) {
+	if (conf->replication_source != NULL) {
 		rw_callback = box_process_ro;
 
 		recovery_wait_lsn(recovery_state, recovery_state->lsn);
-		recovery_follow_remote(recovery_state,
-				      conf->wal_feeder_ipaddr,
-				      conf->wal_feeder_port);
-
-		snprintf(status, sizeof(status), "replica/%s:%i%s",
-			 conf->wal_feeder_ipaddr, conf->wal_feeder_port,
-			 custom_proc_title);
-		title("replica/%s:%i%s", conf->wal_feeder_ipaddr,
-		      conf->wal_feeder_port, custom_proc_title);
+		recovery_follow_remote(recovery_state, conf->replication_source);
+
+		snprintf(status, sizeof(status), "replica/%s%s",
+			 conf->replication_source, custom_proc_title);
+		title("replica/%s%s", conf->replication_source, custom_proc_title);
 	} else {
 		rw_callback = box_process_rw;
 
 		memcached_start_expire();
 
-		snprintf(status, sizeof(status), "primary");
-		title("primary");
+		snprintf(status, sizeof(status), "primary%s", custom_proc_title);
+		title("primary%s", custom_proc_title);
 
 		say_info("I am primary");
 	}
 }
 
 static void
-box_leave_local_hot_standby_mode(void *data __attribute__((unused)))
+box_leave_local_standby_mode(void *data __attribute__((unused)))
 {
 	recover_finalize(recovery_state);
 
@@ -1225,22 +1220,31 @@ box_leave_local_hot_standby_mode(void *data __attribute__((unused)))
 i32
 mod_check_config(struct tarantool_cfg *conf)
 {
-	/* local & remote standby can not work together */
-	if (conf->remote_hot_standby > 0 && conf->local_hot_standby > 0) {
-		out_warning(0, "Remote and local hot standby modes "
+	/* replication & hot standby modes can not work together */
+	if (conf->replication_source != NULL && conf->local_hot_standby > 0) {
+		out_warning(0, "replication and local hot standby modes "
 			       "can't be enabled simultaneously");
 		return -1;
 	}
 
-	/* in the remote_hot_standby mode wal_feeder_ipaddr and wal_feeder_port must be defiend */
-	if (conf->remote_hot_standby &&
-	    (conf->wal_feeder_ipaddr == NULL || conf->wal_feeder_port == 0)) {
-		out_warning(0, "wal_feeder_ipaddr & wal_feeder_port "
-				"must be provided in remote_hot_standby mode");
-		return -1;
+	/* check replication mode */
+	if (conf->replication_source != NULL) {
+		/* check replication port */
+		char ip_addr[32];
+		int port;
+
+		if (sscanf(conf->replication_source, "%31[^:]:%i",
+			   ip_addr, &port) != 2) {
+			out_warning(0, "replication source IP address is not recognized");
+			return -1;
+		}
+		if (port <= 0 || port >= USHRT_MAX) {
+			out_warning(0, "invalid replication source port value: %i", port);
+			return -1;
+		}
 	}
 
-	/* check primary ports */
+	/* check primary port */
 	if (conf->primary_port != 0 &&
 	    (conf->primary_port <= 0 || conf->primary_port >= USHRT_MAX)) {
 		out_warning(0, "invalid primary port value: %i", conf->primary_port);
@@ -1393,22 +1397,22 @@ mod_check_config(struct tarantool_cfg *conf)
 i32
 mod_reload_config(struct tarantool_cfg *old_conf, struct tarantool_cfg *new_conf)
 {
-	if (old_conf->remote_hot_standby != new_conf->remote_hot_standby ||
-	    (old_conf->remote_hot_standby != 0 &&
-	     (strcmp(old_conf->wal_feeder_ipaddr,
-		     new_conf->wal_feeder_ipaddr) != 0 ||
-	      old_conf->wal_feeder_port != new_conf->wal_feeder_port))) {
+	bool old_is_replica = old_conf->replication_source != NULL;
+	bool new_is_replica = new_conf->replication_source != NULL;
+
+	if (old_is_replica != new_is_replica ||
+	    (old_is_replica &&
+	     (strcmp(old_conf->replication_source, new_conf->replication_source) != 0))) {
 
 		if (recovery_state->finalize != true) {
 			out_warning(0, "Could not propagate %s before local recovery finished",
-				    old_conf->remote_hot_standby == true ? "slave to master" :
+				    old_is_replica == true ? "slave to master" :
 				    "master to slave");
 
 			return -1;
 		}
 
-		if (old_conf->remote_hot_standby == 0 &&
-		    new_conf->remote_hot_standby != 0)
+		if (!old_is_replica && new_is_replica)
 			memcached_stop_expire();
 
 		if (recovery_state->remote_recovery)
@@ -1425,15 +1429,6 @@ mod_init(void)
 {
 	static iproto_callback ro_callback = box_process_ro;
 
-	/* init process title */
-	if (cfg.custom_proc_title == NULL)
-		custom_proc_title = "";
-	else {
-		custom_proc_title = palloc(eter_pool, strlen(cfg.custom_proc_title) + 2);
-		strcat(custom_proc_title, "@");
-		strcat(custom_proc_title, cfg.custom_proc_title);
-	}
-
 	title("loading");
 
 	/* initialization namespaces */
@@ -1473,21 +1468,22 @@ mod_init(void)
 		title("hot_standby");
 	}
 
-	/* run memcached server */
-	if (cfg.memcached_port != 0)
-		fiber_server(cfg.memcached_port, memcached_handler, NULL, NULL);
+	/* run primary server */
+	if (cfg.primary_port != 0)
+		fiber_server("primary", cfg.primary_port,
+			     (fiber_server_callback) iproto_interact,
+			     &rw_callback, box_leave_local_standby_mode);
 
 	/* run secondary server */
 	if (cfg.secondary_port != 0)
-		fiber_server(cfg.secondary_port,
+		fiber_server("secondary", cfg.secondary_port,
 			     (fiber_server_callback) iproto_interact,
 			     &ro_callback, NULL);
 
-	/* run primary server */
-	if (cfg.primary_port != 0)
-		fiber_server(cfg.primary_port,
-			     (fiber_server_callback) iproto_interact,
-			     &rw_callback, box_leave_local_hot_standby_mode);
+	/* run memcached server */
+	if (cfg.memcached_port != 0)
+		fiber_server("memcached", cfg.memcached_port,
+			     memcached_handler, NULL, NULL);
 }
 
 int
diff --git a/mod/box/box_cfg.cfg_tmpl b/mod/box/box_cfg.cfg_tmpl
index 3ab9b3fbfbed6962a26934f6a1e1275becb28da9..b2592128c8d4d5afd98473931b5742462bbed29a 100644
--- a/mod/box/box_cfg.cfg_tmpl
+++ b/mod/box/box_cfg.cfg_tmpl
@@ -45,8 +45,10 @@ wal_fsync_delay=0, ro
 # size of WAL writer request buffer
 wal_writer_inbox_size=128, ro
 
-# Local hot standby (if enabled, the server will run in local hot standby
-# mode, continuously fetching WAL records from shared local directory).
+# Local hot standby (if enabled, the server will run in hot
+# standby mode, continuously fetching WAL records from wal_dir,
+# until it is able to bind to the primary port.
+# In local hot standby mode the server only accepts reads.
 local_hot_standby=0, ro
 # Delay, in seconds, between successive re-readings of wal_dir.
 # The re-scan is necessary to discover new WAL files or snapshots.
@@ -59,12 +61,12 @@ wal_dir_rescan_delay=0.1, ro
 panic_on_snap_error=1, ro
 panic_on_wal_error=0, ro
 
-# Remote hot standby (if enabled, the server will run in hot standby mode
-# continuously fetching WAL records from wal_feeder_ipaddr:wal_feeder_port
-remote_hot_standby=0
-wal_feeder_ipaddr=NULL
-wal_feeder_port=0
-
+# Replication mode (if enabled, the server, once
+# bound to the primary port, will connect to
+# replication_source (ipaddr:port) and run continously
+# fetching records from it.. In replication mode the server
+# only accepts reads.
+replication_source=NULL
 
 namespace = [
   {
diff --git a/mod/feeder/CMakeLists.txt b/mod/feeder/CMakeLists.txt
deleted file mode 100644
index 4852343fe75f602983ae07dca3c1f6329c7346c9..0000000000000000000000000000000000000000
--- a/mod/feeder/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-tarantool_module("feeder" feeder.m)
diff --git a/mod/feeder/feeder.m b/mod/feeder/feeder.m
deleted file mode 100644
index 0aa184da2ec91f8dfc44df4e26d09b938309b4f4..0000000000000000000000000000000000000000
--- a/mod/feeder/feeder.m
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2010 Mail.RU
- * Copyright (C) 2010 Yuriy Vostrikov
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-
-#include <fiber.h>
-#include <util.h>
-#include "cfg/tarantool_feeder_cfg.h"
-#include "palloc.h"
-#include "log_io.h"
-#include "say.h"
-#include "tarantool.h"
-
-const char *mod_name = "Feeder";
-static char *custom_proc_title;
-
-static int
-send_row(struct recovery_state *r __attribute__((unused)), struct tbuf *t)
-{
-	u8 *data = t->data;
-	ssize_t bytes, len = t->len;
-	while (len > 0) {
-		bytes = write(fiber->fd, data, len);
-		if (bytes < 0) {
-			say_syserror("write");
-			exit(EXIT_SUCCESS);
-		}
-		len -= bytes;
-		data += bytes;
-	}
-
-	say_debug("send row: %" PRIu32 " bytes %s", t->len, tbuf_to_hex(t));
-
-	return 0;
-}
-
-static void
-recover_feed_slave(int sock)
-{
-	struct recovery_state *log_io;
-	struct tbuf *ver;
-	i64 lsn;
-	ssize_t r;
-
-	fiber->has_peer = true;
-	fiber->fd = sock;
-	fiber_set_name(fiber, "feeder");
-	set_proc_title("replication_relay%s %s", custom_proc_title, fiber_peer_name(fiber));
-
-	ev_default_loop(0);
-
-	r = read(fiber->fd, &lsn, sizeof(lsn));
-	if (r != sizeof(lsn)) {
-		if (r < 0)
-			say_syserror("read");
-		exit(EXIT_SUCCESS);
-	}
-
-	ver = tbuf_alloc(fiber->pool);
-	tbuf_append(ver, &default_version, sizeof(default_version));
-	send_row(NULL, ver);
-
-	log_io = recover_init(NULL, cfg.wal_feeder_dir,
-			      send_row, INT32_MAX, 0, 64, RECOVER_READONLY, false);
-
-	recover(log_io, lsn);
-	recover_follow(log_io, 0.1);
-	ev_loop(0);
-}
-
-i32
-mod_check_config(struct tarantool_cfg *conf __attribute__((unused)))
-{
-	return 0;
-}
-
-i32
-mod_reload_config(struct tarantool_cfg *old_conf __attribute__((unused)),
-		  struct tarantool_cfg *new_conf __attribute__((unused)))
-{
-	return 0;
-}
-
-void
-mod_init(void)
-{
-	int server, client;
-	struct sockaddr_in server_addr;
-	int one = 1;
-
-	if (cfg.wal_feeder_bind_port == 0)
-		panic("can't start feeder without wal_feeder_bind_port");
-
-	if (cfg.wal_feeder_dir == NULL)
-		panic("can't start feeder without wal_feeder_dir");
-
-	if (cfg.custom_proc_title == NULL)
-		custom_proc_title = "";
-	else {
-		custom_proc_title = palloc(eter_pool, strlen(cfg.custom_proc_title) + 2);
-		strcat(custom_proc_title, "@");
-		strcat(custom_proc_title, cfg.custom_proc_title);
-	}
-
-	set_proc_title("replication_server%s %s:%i",
-		       custom_proc_title,
-		       cfg.wal_feeder_bind_ipaddr == NULL ? "ANY" : cfg.wal_feeder_bind_ipaddr,
-		       cfg.wal_feeder_bind_port);
-
-	server = socket(AF_INET, SOCK_STREAM, 0);
-	if (server < 0) {
-		say_syserror("socket");
-		goto exit;
-	}
-
-	memset(&server_addr, 0, sizeof(server_addr));
-
-	server_addr.sin_family = AF_INET;
-	if (cfg.wal_feeder_bind_ipaddr == NULL) {
-		server_addr.sin_addr.s_addr = INADDR_ANY;
-	} else {
-		server_addr.sin_addr.s_addr = inet_addr(cfg.wal_feeder_bind_ipaddr);
-		if (server_addr.sin_addr.s_addr == INADDR_NONE)
-			panic("inet_addr: %s'", cfg.wal_feeder_bind_ipaddr);
-	}
-	server_addr.sin_port = htons(cfg.wal_feeder_bind_port);
-
-	if (setsockopt(server, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
-		say_syserror("setsockopt");
-		goto exit;
-	}
-
-	if (bind(server, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
-		say_syserror("bind");
-		goto exit;
-	}
-
-	listen(server, 5);
-
-	for (;;) {
-		pid_t child;
-		client = accept(server, NULL, NULL);
-		if (client < 0) {
-			say_syserror("accept");
-			continue;
-		}
-		child = fork();
-		if (child < 0) {
-			say_syserror("fork");
-			continue;
-		}
-		if (child == 0)
-			recover_feed_slave(client);
-		else
-			close(client);
-	}
-      exit:
-	exit(EXIT_FAILURE);
-}
-
-void
-mod_exec(char *str __attribute__((unused)), int len __attribute__((unused)),
-	 struct tbuf *out)
-{
-	tbuf_printf(out, "Unimplemented");
-}
diff --git a/mod/feeder/feeder_cfg.cfg_tmpl b/mod/feeder/feeder_cfg.cfg_tmpl
deleted file mode 100644
index ae0dfb4da7e96e9c51ab15f3c1ed4b94866e7d4e..0000000000000000000000000000000000000000
--- a/mod/feeder/feeder_cfg.cfg_tmpl
+++ /dev/null
@@ -1,11 +0,0 @@
-
-# feed WAL to remote replicas
-# feeder accepts it's clients on wal_feeder_bind_ipaddr:wal_feeder_bind_port
-wal_feeder_bind_ipaddr=NULL, ro, required
-wal_feeder_bind_port=0, ro, required
-
-# Directory with WAL files to serve
-wal_feeder_dir=NULL, ro, required
-
-# custom proc title is appended after normal
-custom_proc_title=NULL, ro
diff --git a/test/box/show.result b/test/box/show.result
index ed96c04e25574cfe1304e5b26427a1409812a767..074eaae954252c8760b09cfdd1095a1da77e909b 100644
--- a/test/box/show.result
+++ b/test/box/show.result
@@ -28,8 +28,10 @@ show configuration
 ---
 configuration:
   username: (null)
+  bind_ipaddr: "INADDR_ANY"
   coredump: "0"
   admin_port: "33015"
+  replication_port: "0"
   log_level: "4"
   slab_alloc_arena: "0.1"
   slab_alloc_minimal: "64"
@@ -60,9 +62,7 @@ configuration:
   wal_dir_rescan_delay: "0.1"
   panic_on_snap_error: "1"
   panic_on_wal_error: "0"
-  remote_hot_standby: "0"
-  wal_feeder_ipaddr: (null)
-  wal_feeder_port: "0"
+  replication_source: (null)
   namespace[0].enabled: "1"
   namespace[0].cardinality: "-1"
   namespace[0].estimated_rows: "0"
diff --git a/test/box_replication/tarantool_beholder_to_slave.cfg b/test/box_replication/cfg/hot_standby.cfg
similarity index 66%
rename from test/box_replication/tarantool_beholder_to_slave.cfg
rename to test/box_replication/cfg/hot_standby.cfg
index 9b97eba8a467cbdecdfe2286c2f1f3bb4ae18e00..9d559d6443e34c9df4c26d4f21cda39f75a3837d 100644
--- a/test/box_replication/tarantool_beholder_to_slave.cfg
+++ b/test/box_replication/cfg/hot_standby.cfg
@@ -1,17 +1,20 @@
-slab_alloc_arena=0.05
 pid_file = "tarantool.pid"
+logger="cat - >> tarantool.log"
+
+bind_ipaddr="INADDR_ANY"
+
+wal_dir="../"
+snap_dir="../"
 
 primary_port = 33013
 secondary_port = 33024
 admin_port = 33025
 
-logger="tee -a tarantool.log"
+replication_port=33016
+custom_proc_title="hot_standby"
+
 namespace[0].enabled = 1
 namespace[0].index[0].type = "HASH"
 namespace[0].index[0].unique = 1
 namespace[0].index[0].key_field[0].fieldno = 0
 namespace[0].index[0].key_field[0].type = "NUM"
-
-remote_hot_standby = 1
-wal_feeder_ipaddr = "127.0.0.1"
-wal_feeder_port = 33116
diff --git a/test/box_replication/tarantool.cfg b/test/box_replication/cfg/master.cfg
similarity index 71%
rename from test/box_replication/tarantool.cfg
rename to test/box_replication/cfg/master.cfg
index 9f75124040313b3cb13d4cdbdc1771d286e746dd..603e36ed80a57012b17e64d895c4d4f90d3463a4 100644
--- a/test/box_replication/tarantool.cfg
+++ b/test/box_replication/cfg/master.cfg
@@ -1,13 +1,18 @@
-slab_alloc_arena=0.05
 pid_file = "tarantool.pid"
+logger="cat - >> tarantool.log"
+
+bind_ipaddr="INADDR_ANY"
 
 primary_port = 33013
 secondary_port = 33014
 admin_port = 33015
 
-logger="tee -a tarantool.log"
+replication_port=33016
+custom_proc_title="master"
+
 namespace[0].enabled = 1
 namespace[0].index[0].type = "HASH"
 namespace[0].index[0].unique = 1
 namespace[0].index[0].key_field[0].fieldno = 0
 namespace[0].index[0].key_field[0].type = "NUM"
+
diff --git a/test/box_replication/tarantool_to_slave.cfg b/test/box_replication/cfg/master_to_replica.cfg
similarity index 65%
rename from test/box_replication/tarantool_to_slave.cfg
rename to test/box_replication/cfg/master_to_replica.cfg
index fe58a84e4108d2fc959a332d1a6a74f5e08857f8..172daaca513f4a57482f5d64e24cf87a3d2a1bd1 100644
--- a/test/box_replication/tarantool_to_slave.cfg
+++ b/test/box_replication/cfg/master_to_replica.cfg
@@ -1,17 +1,19 @@
-slab_alloc_arena=0.05
 pid_file = "tarantool.pid"
+logger="cat - >> tarantool.log"
+
+bind_ipaddr="INADDR_ANY"
 
 primary_port = 33013
 secondary_port = 33014
 admin_port = 33015
 
-logger="tee -a tarantool.log"
+replication_port=33016
+custom_proc_title="master"
+
 namespace[0].enabled = 1
 namespace[0].index[0].type = "HASH"
 namespace[0].index[0].unique = 1
 namespace[0].index[0].key_field[0].fieldno = 0
 namespace[0].index[0].key_field[0].type = "NUM"
 
-remote_hot_standby = 1
-wal_feeder_ipaddr = "127.0.0.1"
-wal_feeder_port = 33116
+replication_source = "127.0.0.1:33116"
diff --git a/test/box_replication/tarantool_slave.cfg b/test/box_replication/cfg/replica.cfg
similarity index 65%
rename from test/box_replication/tarantool_slave.cfg
rename to test/box_replication/cfg/replica.cfg
index 0630c863552a63ff3d788347eb7b884020251f6f..a3d5898b04f6e5c5e3980289cc92705d79615706 100644
--- a/test/box_replication/tarantool_slave.cfg
+++ b/test/box_replication/cfg/replica.cfg
@@ -1,17 +1,19 @@
-slab_alloc_arena=0.05
 pid_file = "tarantool.pid"
+logger="cat - >> tarantool.log"
+
+bind_ipaddr="INADDR_ANY"
 
 primary_port = 33113
 secondary_port = 33114
 admin_port = 33115
 
-logger="tee -a tarantool.log"
+replication_port=33116
+custom_proc_title="replica"
+
 namespace[0].enabled = 1
 namespace[0].index[0].type = "HASH"
 namespace[0].index[0].unique = 1
 namespace[0].index[0].key_field[0].fieldno = 0
 namespace[0].index[0].key_field[0].type = "NUM"
 
-remote_hot_standby = 1
-wal_feeder_ipaddr = "127.0.0.1"
-wal_feeder_port = 33016
+replication_source = "127.0.0.1:33016"
diff --git a/test/box_replication/tarantool_slave_to_master.cfg b/test/box_replication/cfg/replica_to_master.cfg
similarity index 71%
rename from test/box_replication/tarantool_slave_to_master.cfg
rename to test/box_replication/cfg/replica_to_master.cfg
index 33eaa9799bb24ba56ed5df8a76eaaa153e6dd366..68bde6cc5cfb362b32fcaa2acd4ebd91f21f1f89 100644
--- a/test/box_replication/tarantool_slave_to_master.cfg
+++ b/test/box_replication/cfg/replica_to_master.cfg
@@ -1,11 +1,15 @@
-slab_alloc_arena=0.05
 pid_file = "tarantool.pid"
+logger="cat - >> tarantool.log"
+
+bind_ipaddr="INADDR_ANY"
 
 primary_port = 33113
 secondary_port = 33114
 admin_port = 33115
 
-logger="tee -a tarantool.log"
+replication_port=33116
+custom_proc_title="replica"
+
 namespace[0].enabled = 1
 namespace[0].index[0].type = "HASH"
 namespace[0].index[0].unique = 1
diff --git a/test/box_replication/common.result b/test/box_replication/common.result
deleted file mode 100644
index 36aeaa44d0cc95857c0d5bc5b9cebea34cae3fcc..0000000000000000000000000000000000000000
--- a/test/box_replication/common.result
+++ /dev/null
@@ -1,149 +0,0 @@
-
-#
-# Insert several tuples.
-#
-
-insert into t0 values (1, 'the tuple #1')
-Insert OK, 1 row affected
-insert into t0 values (2, 'the tuple #2')
-Insert OK, 1 row affected
-insert into t0 values (3, 'the tuple #3')
-Insert OK, 1 row affected
-insert into t0 values (4, 'the tuple #4')
-Insert OK, 1 row affected
-
-#
-# Reconfigure slave to replicate from secondary feeder.
-#
-
-reload configuration
----
-ok
-...
-
-#
-# Insert more tuples.
-#
-
-insert into t0 values (5, 'the tuple #5')
-Insert OK, 1 row affected
-insert into t0 values (6, 'the tuple #6')
-Insert OK, 1 row affected
-insert into t0 values (7, 'the tuple #7')
-Insert OK, 1 row affected
-insert into t0 values (8, 'the tuple #8')
-Insert OK, 1 row affected
-insert into t0 values (9, 'the tuple #9')
-Insert OK, 1 row affected
-
-#
-# Select from master.
-#
-
-select * from t0 where k0 = 1
-Found 1 tuple:
-[1, 'the tuple #1']
-select * from t0 where k0 = 2
-Found 1 tuple:
-[2, 'the tuple #2']
-select * from t0 where k0 = 3
-Found 1 tuple:
-[3, 'the tuple #3']
-select * from t0 where k0 = 4
-Found 1 tuple:
-[4, 'the tuple #4']
-select * from t0 where k0 = 5
-Found 1 tuple:
-[5, 'the tuple #5']
-select * from t0 where k0 = 6
-Found 1 tuple:
-[6, 'the tuple #6']
-select * from t0 where k0 = 7
-Found 1 tuple:
-[7, 'the tuple #7']
-select * from t0 where k0 = 8
-Found 1 tuple:
-[8, 'the tuple #8']
-select * from t0 where k0 = 9
-Found 1 tuple:
-[9, 'the tuple #9']
-
-#
-# Select from slave.
-#
-
-select * from t0 where k0 = 1
-Found 1 tuple:
-[1, 'the tuple #1']
-select * from t0 where k0 = 2
-Found 1 tuple:
-[2, 'the tuple #2']
-select * from t0 where k0 = 3
-Found 1 tuple:
-[3, 'the tuple #3']
-select * from t0 where k0 = 4
-Found 1 tuple:
-[4, 'the tuple #4']
-select * from t0 where k0 = 5
-Found 1 tuple:
-[5, 'the tuple #5']
-select * from t0 where k0 = 6
-Found 1 tuple:
-[6, 'the tuple #6']
-select * from t0 where k0 = 7
-Found 1 tuple:
-[7, 'the tuple #7']
-select * from t0 where k0 = 8
-Found 1 tuple:
-[8, 'the tuple #8']
-select * from t0 where k0 = 9
-Found 1 tuple:
-[9, 'the tuple #9']
-
-#
-# Try to insert into slave.
-#
-
-insert into t0 values (100, 'the tuple #100')
-An error occurred: ER_NONMASTER, 'Non master connection, but it should be�'
-
-#
-# Propagate slave to master.
-#
-
-reload configuration
----
-ok
-...
-
-#
-# Try to insert into slave after it was propagated to master.
-#
-
-insert into t0 values (100, 'the tuple #100')
-Insert OK, 1 row affected
-select * from t0 where k0 = 100
-Found 1 tuple:
-[100, 'the tuple #100']
-
-#
-# Try to propagate beholder to slave.
-#
-
-reload configuration
----
-fail:
- - Could not propagate master to slave before local recovery finished
-...
-
-#
-# Propagate master to slave.
-#
-
-reload configuration
----
-ok
-...
-select * from t0 where k0 = 100
-Found 1 tuple:
-[100, 'the tuple #100']
diff --git a/test/box_replication/common.test b/test/box_replication/common.test
deleted file mode 100644
index 461d04edcd533a13d16b1f1c49d7abb46b4df3ba..0000000000000000000000000000000000000000
--- a/test/box_replication/common.test
+++ /dev/null
@@ -1,139 +0,0 @@
-import os
-from lib.tarantool_box_server import TarantoolBoxServer
-from lib.tarantool_feeder_server import TarantoolFeederServer
-
-master = server
-
-# Startup master beholder.
-beholder = TarantoolBoxServer()
-beholder.deploy("box_replication/tarantool_beholder.cfg",
-		beholder.find_exe(self.args.builddir),
-		os.path.join(self.args.vardir, "beholder"))
-
-# Startup master feeder.
-feeder = TarantoolFeederServer()
-feeder.deploy("box_replication/feeder.cfg",
-	      feeder.find_exe(self.args.builddir),
-	      os.path.join(self.args.vardir, "feeder"))
-
-# Startup secondary master feeder.
-secondary_feeder = TarantoolFeederServer()
-secondary_feeder.deploy("box_replication/feeder_secondary.cfg",
-			secondary_feeder.find_exe(self.args.builddir),
-			os.path.join(self.args.vardir, "feeder_secondary"))
-
-# Startup replication server.
-slave = TarantoolBoxServer()
-slave.deploy("box_replication/tarantool_slave.cfg",
-	     slave.find_exe(self.args.builddir),
-	     os.path.join(self.args.vardir, "slave"))
-# Startup replication feeder.
-slave_feeder = TarantoolFeederServer()
-slave_feeder.deploy("box_replication/feeder_slave.cfg",
-		    slave_feeder.find_exe(self.args.builddir),
-		    os.path.join(self.args.vardir, "slave/feeder"))
-
-print """
-#
-# Insert several tuples.
-#
-"""
-for i in range(1, 5):
-	master.sql.execute("insert into t0 values ({0}, 'the tuple #{0}')".format(i),
-			   silent=False)
-
-slave.wait_lsn(5)
-
-print """
-#
-# Reconfigure slave to replicate from secondary feeder.
-#
-"""
-slave.reconfigure("box_replication/tarantool_slave_secondary_feeder_replication.cfg")
-feeder.stop()
-feeder.cleanup(True)
-
-print """
-#
-# Insert more tuples.
-#
-"""
-for i in range(5, 10):
-	master.sql.execute("insert into t0 values ({0}, 'the tuple #{0}')".format(i),
-			   silent=False)
-
-print """
-#
-# Select from master.
-#
-"""
-for i in range(1, 10):
-	master.sql.execute("select * from t0 where k0 = {0}".format(i),
-			   silent=False)
-
-slave.wait_lsn(10)
-
-print """
-#
-# Select from slave.
-#
-"""
-for i in range(1,10):
-	slave.sql.execute("select * from t0 where k0 = {0}".format(i),
-			  silent=False)
-
-print """
-#
-# Try to insert into slave.
-#
-"""
-slave.sql.execute("insert into t0 values (100, 'the tuple #100')",
-		  silent=False)
-
-print """
-#
-# Propagate slave to master.
-#
-"""
-slave.reconfigure("box_replication/tarantool_slave_to_master.cfg")
-
-print """
-#
-# Try to insert into slave after it was propagated to master.
-#
-"""
-slave.sql.execute("insert into t0 values (100, 'the tuple #100')",
-		  silent=False)
-slave.sql.execute("select * from t0 where k0 = 100",
-		  silent=False)
-
-print """
-#
-# Try to propagate beholder to slave.
-#
-"""
-beholder.reconfigure("box_replication/tarantool_beholder_to_slave.cfg")
-
-print """
-#
-# Propagate master to slave.
-#
-"""
-master.reconfigure("box_replication/tarantool_to_slave.cfg")
-master.wait_lsn(11)
-master.sql.execute("select * from t0 where k0 = 100",
-		   silent=False)
-
-# Cleanup.
-beholder.stop()
-beholder.cleanup(True)
-secondary_feeder.stop()
-secondary_feeder.cleanup(True)
-slave_feeder.stop()
-slave_feeder.cleanup(True)
-slave.stop()
-slave.cleanup(True)
-server.stop()
-server.deploy(self.suite_ini["config"])
-
-# vim: syntax=python
diff --git a/test/box_replication/consistent.result b/test/box_replication/consistent.result
new file mode 100644
index 0000000000000000000000000000000000000000..ae17a90459000c646fd6601b532a320e5eeb1b8a
--- /dev/null
+++ b/test/box_replication/consistent.result
@@ -0,0 +1,685 @@
+insert to master [0, 10) entries
+insert into t0 values (0, 'mater 0')
+Insert OK, 1 row affected
+insert into t0 values (1, 'mater 1')
+Insert OK, 1 row affected
+insert into t0 values (2, 'mater 2')
+Insert OK, 1 row affected
+insert into t0 values (3, 'mater 3')
+Insert OK, 1 row affected
+insert into t0 values (4, 'mater 4')
+Insert OK, 1 row affected
+insert into t0 values (5, 'mater 5')
+Insert OK, 1 row affected
+insert into t0 values (6, 'mater 6')
+Insert OK, 1 row affected
+insert into t0 values (7, 'mater 7')
+Insert OK, 1 row affected
+insert into t0 values (8, 'mater 8')
+Insert OK, 1 row affected
+insert into t0 values (9, 'mater 9')
+Insert OK, 1 row affected
+select from replica [0, 10) entries
+select * from t0 where k0 = 0
+Found 1 tuple:
+[0, 'mater 0']
+select * from t0 where k0 = 1
+Found 1 tuple:
+[1, 'mater 1']
+select * from t0 where k0 = 2
+Found 1 tuple:
+[2, 'mater 2']
+select * from t0 where k0 = 3
+Found 1 tuple:
+[3, 'mater 3']
+select * from t0 where k0 = 4
+Found 1 tuple:
+[4, 'mater 4']
+select * from t0 where k0 = 5
+Found 1 tuple:
+[5, 'mater 5']
+select * from t0 where k0 = 6
+Found 1 tuple:
+[6, 'mater 6']
+select * from t0 where k0 = 7
+Found 1 tuple:
+[7, 'mater 7']
+select * from t0 where k0 = 8
+Found 1 tuple:
+[8, 'mater 8']
+select * from t0 where k0 = 9
+Found 1 tuple:
+[9, 'mater 9']
+master lsn = 11
+replica lsn = 11
+
+#
+# mater lsn > replica lsn
+#
+
+
+# reconfigure replica to master
+
+reload configuration
+---
+ok
+...
+insert to master [10, 20) entries
+insert into t0 values (10, 'mater 10')
+Insert OK, 1 row affected
+insert into t0 values (11, 'mater 11')
+Insert OK, 1 row affected
+insert into t0 values (12, 'mater 12')
+Insert OK, 1 row affected
+insert into t0 values (13, 'mater 13')
+Insert OK, 1 row affected
+insert into t0 values (14, 'mater 14')
+Insert OK, 1 row affected
+insert into t0 values (15, 'mater 15')
+Insert OK, 1 row affected
+insert into t0 values (16, 'mater 16')
+Insert OK, 1 row affected
+insert into t0 values (17, 'mater 17')
+Insert OK, 1 row affected
+insert into t0 values (18, 'mater 18')
+Insert OK, 1 row affected
+insert into t0 values (19, 'mater 19')
+Insert OK, 1 row affected
+select from master [10, 20) entries
+select * from t0 where k0 = 10
+Found 1 tuple:
+[10, 'mater 10']
+select * from t0 where k0 = 11
+Found 1 tuple:
+[11, 'mater 11']
+select * from t0 where k0 = 12
+Found 1 tuple:
+[12, 'mater 12']
+select * from t0 where k0 = 13
+Found 1 tuple:
+[13, 'mater 13']
+select * from t0 where k0 = 14
+Found 1 tuple:
+[14, 'mater 14']
+select * from t0 where k0 = 15
+Found 1 tuple:
+[15, 'mater 15']
+select * from t0 where k0 = 16
+Found 1 tuple:
+[16, 'mater 16']
+select * from t0 where k0 = 17
+Found 1 tuple:
+[17, 'mater 17']
+select * from t0 where k0 = 18
+Found 1 tuple:
+[18, 'mater 18']
+select * from t0 where k0 = 19
+Found 1 tuple:
+[19, 'mater 19']
+insert to replica [10, 15) entries
+insert into t0 values (10, 'replica 10')
+Insert OK, 1 row affected
+insert into t0 values (11, 'replica 11')
+Insert OK, 1 row affected
+insert into t0 values (12, 'replica 12')
+Insert OK, 1 row affected
+insert into t0 values (13, 'replica 13')
+Insert OK, 1 row affected
+insert into t0 values (14, 'replica 14')
+Insert OK, 1 row affected
+select from replica [10, 15) entries
+select * from t0 where k0 = 10
+Found 1 tuple:
+[10, 'replica 10']
+select * from t0 where k0 = 11
+Found 1 tuple:
+[11, 'replica 11']
+select * from t0 where k0 = 12
+Found 1 tuple:
+[12, 'replica 12']
+select * from t0 where k0 = 13
+Found 1 tuple:
+[13, 'replica 13']
+select * from t0 where k0 = 14
+Found 1 tuple:
+[14, 'replica 14']
+master lsn = 21
+replica lsn = 16
+
+# rollback replica
+
+reload configuration
+---
+ok
+...
+select from replica [10, 20) entries
+select * from t0 where k0 = 10
+Found 1 tuple:
+[10, 'replica 10']
+select * from t0 where k0 = 11
+Found 1 tuple:
+[11, 'replica 11']
+select * from t0 where k0 = 12
+Found 1 tuple:
+[12, 'replica 12']
+select * from t0 where k0 = 13
+Found 1 tuple:
+[13, 'replica 13']
+select * from t0 where k0 = 14
+Found 1 tuple:
+[14, 'replica 14']
+select * from t0 where k0 = 15
+Found 1 tuple:
+[15, 'mater 15']
+select * from t0 where k0 = 16
+Found 1 tuple:
+[16, 'mater 16']
+select * from t0 where k0 = 17
+Found 1 tuple:
+[17, 'mater 17']
+select * from t0 where k0 = 18
+Found 1 tuple:
+[18, 'mater 18']
+select * from t0 where k0 = 19
+Found 1 tuple:
+[19, 'mater 19']
+master lsn = 21
+replica lsn = 21
+
+#
+# master lsn == replica lsn
+#
+
+
+# reconfigure replica to master
+
+reload configuration
+---
+ok
+...
+insert to master [20, 30) entries
+insert into t0 values (20, 'mater 20')
+Insert OK, 1 row affected
+insert into t0 values (21, 'mater 21')
+Insert OK, 1 row affected
+insert into t0 values (22, 'mater 22')
+Insert OK, 1 row affected
+insert into t0 values (23, 'mater 23')
+Insert OK, 1 row affected
+insert into t0 values (24, 'mater 24')
+Insert OK, 1 row affected
+insert into t0 values (25, 'mater 25')
+Insert OK, 1 row affected
+insert into t0 values (26, 'mater 26')
+Insert OK, 1 row affected
+insert into t0 values (27, 'mater 27')
+Insert OK, 1 row affected
+insert into t0 values (28, 'mater 28')
+Insert OK, 1 row affected
+insert into t0 values (29, 'mater 29')
+Insert OK, 1 row affected
+select from master [20, 30) entries
+select * from t0 where k0 = 20
+Found 1 tuple:
+[20, 'mater 20']
+select * from t0 where k0 = 21
+Found 1 tuple:
+[21, 'mater 21']
+select * from t0 where k0 = 22
+Found 1 tuple:
+[22, 'mater 22']
+select * from t0 where k0 = 23
+Found 1 tuple:
+[23, 'mater 23']
+select * from t0 where k0 = 24
+Found 1 tuple:
+[24, 'mater 24']
+select * from t0 where k0 = 25
+Found 1 tuple:
+[25, 'mater 25']
+select * from t0 where k0 = 26
+Found 1 tuple:
+[26, 'mater 26']
+select * from t0 where k0 = 27
+Found 1 tuple:
+[27, 'mater 27']
+select * from t0 where k0 = 28
+Found 1 tuple:
+[28, 'mater 28']
+select * from t0 where k0 = 29
+Found 1 tuple:
+[29, 'mater 29']
+insert to replica [20, 30) entries
+insert into t0 values (20, 'replica 20')
+Insert OK, 1 row affected
+insert into t0 values (21, 'replica 21')
+Insert OK, 1 row affected
+insert into t0 values (22, 'replica 22')
+Insert OK, 1 row affected
+insert into t0 values (23, 'replica 23')
+Insert OK, 1 row affected
+insert into t0 values (24, 'replica 24')
+Insert OK, 1 row affected
+insert into t0 values (25, 'replica 25')
+Insert OK, 1 row affected
+insert into t0 values (26, 'replica 26')
+Insert OK, 1 row affected
+insert into t0 values (27, 'replica 27')
+Insert OK, 1 row affected
+insert into t0 values (28, 'replica 28')
+Insert OK, 1 row affected
+insert into t0 values (29, 'replica 29')
+Insert OK, 1 row affected
+select from replica [20, 30) entries
+select * from t0 where k0 = 20
+Found 1 tuple:
+[20, 'replica 20']
+select * from t0 where k0 = 21
+Found 1 tuple:
+[21, 'replica 21']
+select * from t0 where k0 = 22
+Found 1 tuple:
+[22, 'replica 22']
+select * from t0 where k0 = 23
+Found 1 tuple:
+[23, 'replica 23']
+select * from t0 where k0 = 24
+Found 1 tuple:
+[24, 'replica 24']
+select * from t0 where k0 = 25
+Found 1 tuple:
+[25, 'replica 25']
+select * from t0 where k0 = 26
+Found 1 tuple:
+[26, 'replica 26']
+select * from t0 where k0 = 27
+Found 1 tuple:
+[27, 'replica 27']
+select * from t0 where k0 = 28
+Found 1 tuple:
+[28, 'replica 28']
+select * from t0 where k0 = 29
+Found 1 tuple:
+[29, 'replica 29']
+master lsn = 31
+replica lsn = 31
+
+# rollback replica
+
+reload configuration
+---
+ok
+...
+select from replica [20, 30) entries
+select * from t0 where k0 = 20
+Found 1 tuple:
+[20, 'replica 20']
+select * from t0 where k0 = 21
+Found 1 tuple:
+[21, 'replica 21']
+select * from t0 where k0 = 22
+Found 1 tuple:
+[22, 'replica 22']
+select * from t0 where k0 = 23
+Found 1 tuple:
+[23, 'replica 23']
+select * from t0 where k0 = 24
+Found 1 tuple:
+[24, 'replica 24']
+select * from t0 where k0 = 25
+Found 1 tuple:
+[25, 'replica 25']
+select * from t0 where k0 = 26
+Found 1 tuple:
+[26, 'replica 26']
+select * from t0 where k0 = 27
+Found 1 tuple:
+[27, 'replica 27']
+select * from t0 where k0 = 28
+Found 1 tuple:
+[28, 'replica 28']
+select * from t0 where k0 = 29
+Found 1 tuple:
+[29, 'replica 29']
+master lsn = 31
+replica lsn = 31
+
+#
+# mater lsn < replica lsn
+#
+
+
+#reconfigure replica to master
+
+reload configuration
+---
+ok
+...
+insert to master [30, 40) entries
+insert into t0 values (30, 'mater 30')
+Insert OK, 1 row affected
+insert into t0 values (31, 'mater 31')
+Insert OK, 1 row affected
+insert into t0 values (32, 'mater 32')
+Insert OK, 1 row affected
+insert into t0 values (33, 'mater 33')
+Insert OK, 1 row affected
+insert into t0 values (34, 'mater 34')
+Insert OK, 1 row affected
+insert into t0 values (35, 'mater 35')
+Insert OK, 1 row affected
+insert into t0 values (36, 'mater 36')
+Insert OK, 1 row affected
+insert into t0 values (37, 'mater 37')
+Insert OK, 1 row affected
+insert into t0 values (38, 'mater 38')
+Insert OK, 1 row affected
+insert into t0 values (39, 'mater 39')
+Insert OK, 1 row affected
+select from master [30, 40) entries
+select * from t0 where k0 = 30
+Found 1 tuple:
+[30, 'mater 30']
+select * from t0 where k0 = 31
+Found 1 tuple:
+[31, 'mater 31']
+select * from t0 where k0 = 32
+Found 1 tuple:
+[32, 'mater 32']
+select * from t0 where k0 = 33
+Found 1 tuple:
+[33, 'mater 33']
+select * from t0 where k0 = 34
+Found 1 tuple:
+[34, 'mater 34']
+select * from t0 where k0 = 35
+Found 1 tuple:
+[35, 'mater 35']
+select * from t0 where k0 = 36
+Found 1 tuple:
+[36, 'mater 36']
+select * from t0 where k0 = 37
+Found 1 tuple:
+[37, 'mater 37']
+select * from t0 where k0 = 38
+Found 1 tuple:
+[38, 'mater 38']
+select * from t0 where k0 = 39
+Found 1 tuple:
+[39, 'mater 39']
+insert to replica [30, 50) entries
+insert into t0 values (30, 'replica 30')
+Insert OK, 1 row affected
+insert into t0 values (31, 'replica 31')
+Insert OK, 1 row affected
+insert into t0 values (32, 'replica 32')
+Insert OK, 1 row affected
+insert into t0 values (33, 'replica 33')
+Insert OK, 1 row affected
+insert into t0 values (34, 'replica 34')
+Insert OK, 1 row affected
+insert into t0 values (35, 'replica 35')
+Insert OK, 1 row affected
+insert into t0 values (36, 'replica 36')
+Insert OK, 1 row affected
+insert into t0 values (37, 'replica 37')
+Insert OK, 1 row affected
+insert into t0 values (38, 'replica 38')
+Insert OK, 1 row affected
+insert into t0 values (39, 'replica 39')
+Insert OK, 1 row affected
+insert into t0 values (40, 'replica 40')
+Insert OK, 1 row affected
+insert into t0 values (41, 'replica 41')
+Insert OK, 1 row affected
+insert into t0 values (42, 'replica 42')
+Insert OK, 1 row affected
+insert into t0 values (43, 'replica 43')
+Insert OK, 1 row affected
+insert into t0 values (44, 'replica 44')
+Insert OK, 1 row affected
+insert into t0 values (45, 'replica 45')
+Insert OK, 1 row affected
+insert into t0 values (46, 'replica 46')
+Insert OK, 1 row affected
+insert into t0 values (47, 'replica 47')
+Insert OK, 1 row affected
+insert into t0 values (48, 'replica 48')
+Insert OK, 1 row affected
+insert into t0 values (49, 'replica 49')
+Insert OK, 1 row affected
+select from replica [30, 50) entries
+select * from t0 where k0 = 30
+Found 1 tuple:
+[30, 'replica 30']
+select * from t0 where k0 = 31
+Found 1 tuple:
+[31, 'replica 31']
+select * from t0 where k0 = 32
+Found 1 tuple:
+[32, 'replica 32']
+select * from t0 where k0 = 33
+Found 1 tuple:
+[33, 'replica 33']
+select * from t0 where k0 = 34
+Found 1 tuple:
+[34, 'replica 34']
+select * from t0 where k0 = 35
+Found 1 tuple:
+[35, 'replica 35']
+select * from t0 where k0 = 36
+Found 1 tuple:
+[36, 'replica 36']
+select * from t0 where k0 = 37
+Found 1 tuple:
+[37, 'replica 37']
+select * from t0 where k0 = 38
+Found 1 tuple:
+[38, 'replica 38']
+select * from t0 where k0 = 39
+Found 1 tuple:
+[39, 'replica 39']
+select * from t0 where k0 = 40
+Found 1 tuple:
+[40, 'replica 40']
+select * from t0 where k0 = 41
+Found 1 tuple:
+[41, 'replica 41']
+select * from t0 where k0 = 42
+Found 1 tuple:
+[42, 'replica 42']
+select * from t0 where k0 = 43
+Found 1 tuple:
+[43, 'replica 43']
+select * from t0 where k0 = 44
+Found 1 tuple:
+[44, 'replica 44']
+select * from t0 where k0 = 45
+Found 1 tuple:
+[45, 'replica 45']
+select * from t0 where k0 = 46
+Found 1 tuple:
+[46, 'replica 46']
+select * from t0 where k0 = 47
+Found 1 tuple:
+[47, 'replica 47']
+select * from t0 where k0 = 48
+Found 1 tuple:
+[48, 'replica 48']
+select * from t0 where k0 = 49
+Found 1 tuple:
+[49, 'replica 49']
+master lsn = 41
+replica lsn = 51
+
+# rollback replica
+
+reload configuration
+---
+ok
+...
+select from replica [30, 50) entries
+select * from t0 where k0 = 30
+Found 1 tuple:
+[30, 'replica 30']
+select * from t0 where k0 = 31
+Found 1 tuple:
+[31, 'replica 31']
+select * from t0 where k0 = 32
+Found 1 tuple:
+[32, 'replica 32']
+select * from t0 where k0 = 33
+Found 1 tuple:
+[33, 'replica 33']
+select * from t0 where k0 = 34
+Found 1 tuple:
+[34, 'replica 34']
+select * from t0 where k0 = 35
+Found 1 tuple:
+[35, 'replica 35']
+select * from t0 where k0 = 36
+Found 1 tuple:
+[36, 'replica 36']
+select * from t0 where k0 = 37
+Found 1 tuple:
+[37, 'replica 37']
+select * from t0 where k0 = 38
+Found 1 tuple:
+[38, 'replica 38']
+select * from t0 where k0 = 39
+Found 1 tuple:
+[39, 'replica 39']
+select * from t0 where k0 = 40
+Found 1 tuple:
+[40, 'replica 40']
+select * from t0 where k0 = 41
+Found 1 tuple:
+[41, 'replica 41']
+select * from t0 where k0 = 42
+Found 1 tuple:
+[42, 'replica 42']
+select * from t0 where k0 = 43
+Found 1 tuple:
+[43, 'replica 43']
+select * from t0 where k0 = 44
+Found 1 tuple:
+[44, 'replica 44']
+select * from t0 where k0 = 45
+Found 1 tuple:
+[45, 'replica 45']
+select * from t0 where k0 = 46
+Found 1 tuple:
+[46, 'replica 46']
+select * from t0 where k0 = 47
+Found 1 tuple:
+[47, 'replica 47']
+select * from t0 where k0 = 48
+Found 1 tuple:
+[48, 'replica 48']
+select * from t0 where k0 = 49
+Found 1 tuple:
+[49, 'replica 49']
+insert to master [40, 60) entries
+insert into t0 values (40, 'master 40')
+Insert OK, 1 row affected
+insert into t0 values (41, 'master 41')
+Insert OK, 1 row affected
+insert into t0 values (42, 'master 42')
+Insert OK, 1 row affected
+insert into t0 values (43, 'master 43')
+Insert OK, 1 row affected
+insert into t0 values (44, 'master 44')
+Insert OK, 1 row affected
+insert into t0 values (45, 'master 45')
+Insert OK, 1 row affected
+insert into t0 values (46, 'master 46')
+Insert OK, 1 row affected
+insert into t0 values (47, 'master 47')
+Insert OK, 1 row affected
+insert into t0 values (48, 'master 48')
+Insert OK, 1 row affected
+insert into t0 values (49, 'master 49')
+Insert OK, 1 row affected
+insert into t0 values (50, 'master 50')
+Insert OK, 1 row affected
+insert into t0 values (51, 'master 51')
+Insert OK, 1 row affected
+insert into t0 values (52, 'master 52')
+Insert OK, 1 row affected
+insert into t0 values (53, 'master 53')
+Insert OK, 1 row affected
+insert into t0 values (54, 'master 54')
+Insert OK, 1 row affected
+insert into t0 values (55, 'master 55')
+Insert OK, 1 row affected
+insert into t0 values (56, 'master 56')
+Insert OK, 1 row affected
+insert into t0 values (57, 'master 57')
+Insert OK, 1 row affected
+insert into t0 values (58, 'master 58')
+Insert OK, 1 row affected
+insert into t0 values (59, 'master 59')
+Insert OK, 1 row affected
+select from replica [40, 60) entries
+select * from t0 where k0 = 40
+Found 1 tuple:
+[40, 'replica 40']
+select * from t0 where k0 = 41
+Found 1 tuple:
+[41, 'replica 41']
+select * from t0 where k0 = 42
+Found 1 tuple:
+[42, 'replica 42']
+select * from t0 where k0 = 43
+Found 1 tuple:
+[43, 'replica 43']
+select * from t0 where k0 = 44
+Found 1 tuple:
+[44, 'replica 44']
+select * from t0 where k0 = 45
+Found 1 tuple:
+[45, 'replica 45']
+select * from t0 where k0 = 46
+Found 1 tuple:
+[46, 'replica 46']
+select * from t0 where k0 = 47
+Found 1 tuple:
+[47, 'replica 47']
+select * from t0 where k0 = 48
+Found 1 tuple:
+[48, 'replica 48']
+select * from t0 where k0 = 49
+Found 1 tuple:
+[49, 'replica 49']
+select * from t0 where k0 = 50
+Found 1 tuple:
+[50, 'master 50']
+select * from t0 where k0 = 51
+Found 1 tuple:
+[51, 'master 51']
+select * from t0 where k0 = 52
+Found 1 tuple:
+[52, 'master 52']
+select * from t0 where k0 = 53
+Found 1 tuple:
+[53, 'master 53']
+select * from t0 where k0 = 54
+Found 1 tuple:
+[54, 'master 54']
+select * from t0 where k0 = 55
+Found 1 tuple:
+[55, 'master 55']
+select * from t0 where k0 = 56
+Found 1 tuple:
+[56, 'master 56']
+select * from t0 where k0 = 57
+Found 1 tuple:
+[57, 'master 57']
+select * from t0 where k0 = 58
+Found 1 tuple:
+[58, 'master 58']
+select * from t0 where k0 = 59
+Found 1 tuple:
+[59, 'master 59']
+master lsn = 61
+replica lsn = 61
diff --git a/test/box_replication/consistent.test b/test/box_replication/consistent.test
new file mode 100644
index 0000000000000000000000000000000000000000..16ab112aeb55f3eccd80f35d182791b774056758
--- /dev/null
+++ b/test/box_replication/consistent.test
@@ -0,0 +1,162 @@
+# encoding: tarantool
+import os
+import time
+from lib.tarantool_box_server import TarantoolBoxServer
+
+ID_BEGIN = 0
+ID_STEP = 10
+
+def insert_tuples(server, begin, end, msg = "tuple"):
+    for i in range(begin, end):
+        server.sql.execute("insert into t0 values (%d, '%s %d')" % (i, msg, i), silent=False)
+
+def select_tuples(server, begin, end):
+    # the last lsn is end id + 1
+    server.wait_lsn(end + 1)
+    for i in range(begin, end):
+        server.sql.execute("select * from t0 where k0 = %d" % i, silent=False)
+
+# master server
+master = server
+
+# replica server
+replica = TarantoolBoxServer()
+replica.deploy("box_replication/cfg/replica.cfg",
+               replica.find_exe(self.args.builddir),
+               os.path.join(self.args.vardir, "replica"))
+
+# Id counter
+id = 0
+
+
+print "insert to master [%d, %d) entries" % (id, id + ID_STEP)
+insert_tuples(master, id, id + ID_STEP, "mater")
+
+print "select from replica [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(replica, id, id + ID_STEP)
+id += ID_STEP
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+
+print """
+#
+# mater lsn > replica lsn
+#
+"""
+print """
+# reconfigure replica to master
+"""
+replica.reconfigure("box_replication/cfg/replica_to_master.cfg")
+
+print "insert to master [%d, %d) entries" % (id, id + ID_STEP)
+insert_tuples(master, id, id + ID_STEP, "mater")
+print "select from master [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(master, id, id + ID_STEP)
+
+print "insert to replica [%d, %d) entries" % (id, id + (ID_STEP / 2))
+insert_tuples(replica, id, id + (ID_STEP / 2), "replica")
+print "select from replica [%d, %d) entries" % (id, id + (ID_STEP / 2))
+select_tuples(replica, id, id + (ID_STEP / 2))
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+print """
+# rollback replica
+"""
+replica.reconfigure("box_replication/cfg/replica.cfg")
+
+print "select from replica [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(replica, id, id + ID_STEP)
+id += ID_STEP
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+
+print """
+#
+# master lsn == replica lsn
+#
+"""
+print """
+# reconfigure replica to master
+"""
+replica.reconfigure("box_replication/cfg/replica_to_master.cfg")
+
+print "insert to master [%d, %d) entries" % (id, id + ID_STEP)
+insert_tuples(master, id, id + ID_STEP, "mater")
+print "select from master [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(master, id, id + ID_STEP)
+
+print "insert to replica [%d, %d) entries" % (id, id + ID_STEP)
+insert_tuples(replica, id, id + ID_STEP, "replica")
+print "select from replica [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(replica, id, id + ID_STEP)
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+print """
+# rollback replica
+"""
+replica.reconfigure("box_replication/cfg/replica.cfg")
+
+print "select from replica [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(replica, id, id + ID_STEP)
+id += ID_STEP
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+
+print """
+#
+# mater lsn < replica lsn
+#
+"""
+print """
+#reconfigure replica to master
+"""
+replica.reconfigure("box_replication/cfg/replica_to_master.cfg")
+
+print "insert to master [%d, %d) entries" % (id, id + ID_STEP)
+insert_tuples(master, id, id + ID_STEP, "mater")
+print "select from master [%d, %d) entries" % (id, id + ID_STEP)
+select_tuples(master, id, id + ID_STEP)
+
+print "insert to replica [%d, %d) entries" % (id, id + (ID_STEP * 2))
+insert_tuples(replica, id, id + (ID_STEP * 2), "replica")
+print "select from replica [%d, %d) entries" % (id, id + (ID_STEP * 2))
+select_tuples(replica, id, id + (ID_STEP * 2))
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+print """
+# rollback replica
+"""
+replica.reconfigure("box_replication/cfg/replica.cfg")
+
+print "select from replica [%d, %d) entries" % (id, id + (ID_STEP * 2))
+select_tuples(replica, id, id + (ID_STEP * 2))
+id += ID_STEP
+
+print "insert to master [%d, %d) entries" % (id, id + (ID_STEP * 2))
+insert_tuples(master, id, id + (ID_STEP * 2), "master")
+
+print "select from replica [%d, %d) entries" % (id, id + (ID_STEP * 2))
+select_tuples(replica, id, id + (ID_STEP * 2))
+
+print "master lsn = %s" % master.get_param("lsn")
+print "replica lsn = %s" % replica.get_param("lsn")
+
+# Cleanup.
+replica.stop()
+replica.cleanup(True)
+server.stop()
+server.deploy(self.suite_ini["config"])
+
+# vim: syntax=python
diff --git a/test/box_replication/feeder.cfg b/test/box_replication/feeder.cfg
deleted file mode 100644
index 90b488bca00e8be0418ff4dc7d4a91b091169902..0000000000000000000000000000000000000000
--- a/test/box_replication/feeder.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-pid_file = "tarantool.pid"
-
-logger="tee -a tarantool.log"
-
-wal_feeder_bind_ipaddr = "127.0.0.1"
-wal_feeder_bind_port = 33016
-
-wal_feeder_dir = "../"
diff --git a/test/box_replication/feeder_secondary.cfg b/test/box_replication/feeder_secondary.cfg
deleted file mode 100644
index 83f9c44440203d6146647dcb8dd8b82dcfa4e69d..0000000000000000000000000000000000000000
--- a/test/box_replication/feeder_secondary.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-pid_file = "tarantool.pid"
-
-logger="tee -a tarantool.log"
-
-wal_feeder_bind_ipaddr = "127.0.0.1"
-wal_feeder_bind_port = 33026
-
-wal_feeder_dir = "../"
diff --git a/test/box_replication/feeder_slave.cfg b/test/box_replication/feeder_slave.cfg
deleted file mode 100644
index 39c6e32caa4439c903de2c58d813085d66791768..0000000000000000000000000000000000000000
--- a/test/box_replication/feeder_slave.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-pid_file = "tarantool.pid"
-
-logger="tee -a tarantool.log"
-
-wal_feeder_bind_ipaddr = "127.0.0.1"
-wal_feeder_bind_port = 33116
-
-wal_feeder_dir = "../"
diff --git a/test/box_replication/hot_standby.result b/test/box_replication/hot_standby.result
new file mode 100644
index 0000000000000000000000000000000000000000..9522df29edfa28c7469326482d06d52799b83181
--- /dev/null
+++ b/test/box_replication/hot_standby.result
@@ -0,0 +1,181 @@
+
+# Insert 10 tuples to master
+
+insert into t0 values (1, 'the tuple 1')
+Insert OK, 1 row affected
+insert into t0 values (2, 'the tuple 2')
+Insert OK, 1 row affected
+insert into t0 values (3, 'the tuple 3')
+Insert OK, 1 row affected
+insert into t0 values (4, 'the tuple 4')
+Insert OK, 1 row affected
+insert into t0 values (5, 'the tuple 5')
+Insert OK, 1 row affected
+insert into t0 values (6, 'the tuple 6')
+Insert OK, 1 row affected
+insert into t0 values (7, 'the tuple 7')
+Insert OK, 1 row affected
+insert into t0 values (8, 'the tuple 8')
+Insert OK, 1 row affected
+insert into t0 values (9, 'the tuple 9')
+Insert OK, 1 row affected
+insert into t0 values (10, 'the tuple 10')
+Insert OK, 1 row affected
+
+# Select 10 tuples from master
+
+select * from t0 where k0 = 1
+Found 1 tuple:
+[1, 'the tuple 1']
+select * from t0 where k0 = 2
+Found 1 tuple:
+[2, 'the tuple 2']
+select * from t0 where k0 = 3
+Found 1 tuple:
+[3, 'the tuple 3']
+select * from t0 where k0 = 4
+Found 1 tuple:
+[4, 'the tuple 4']
+select * from t0 where k0 = 5
+Found 1 tuple:
+[5, 'the tuple 5']
+select * from t0 where k0 = 6
+Found 1 tuple:
+[6, 'the tuple 6']
+select * from t0 where k0 = 7
+Found 1 tuple:
+[7, 'the tuple 7']
+select * from t0 where k0 = 8
+Found 1 tuple:
+[8, 'the tuple 8']
+select * from t0 where k0 = 9
+Found 1 tuple:
+[9, 'the tuple 9']
+select * from t0 where k0 = 10
+Found 1 tuple:
+[10, 'the tuple 10']
+
+# Select 10 tuples from replica
+
+select * from t0 where k0 = 1
+Found 1 tuple:
+[1, 'the tuple 1']
+select * from t0 where k0 = 2
+Found 1 tuple:
+[2, 'the tuple 2']
+select * from t0 where k0 = 3
+Found 1 tuple:
+[3, 'the tuple 3']
+select * from t0 where k0 = 4
+Found 1 tuple:
+[4, 'the tuple 4']
+select * from t0 where k0 = 5
+Found 1 tuple:
+[5, 'the tuple 5']
+select * from t0 where k0 = 6
+Found 1 tuple:
+[6, 'the tuple 6']
+select * from t0 where k0 = 7
+Found 1 tuple:
+[7, 'the tuple 7']
+select * from t0 where k0 = 8
+Found 1 tuple:
+[8, 'the tuple 8']
+select * from t0 where k0 = 9
+Found 1 tuple:
+[9, 'the tuple 9']
+select * from t0 where k0 = 10
+Found 1 tuple:
+[10, 'the tuple 10']
+
+# Shutdown master server (now the hot_standby must be a primary server)
+
+
+# Insert 10 tuples to hot_standby
+
+insert into t0 values (11, 'the tuple 11')
+Insert OK, 1 row affected
+insert into t0 values (12, 'the tuple 12')
+Insert OK, 1 row affected
+insert into t0 values (13, 'the tuple 13')
+Insert OK, 1 row affected
+insert into t0 values (14, 'the tuple 14')
+Insert OK, 1 row affected
+insert into t0 values (15, 'the tuple 15')
+Insert OK, 1 row affected
+insert into t0 values (16, 'the tuple 16')
+Insert OK, 1 row affected
+insert into t0 values (17, 'the tuple 17')
+Insert OK, 1 row affected
+insert into t0 values (18, 'the tuple 18')
+Insert OK, 1 row affected
+insert into t0 values (19, 'the tuple 19')
+Insert OK, 1 row affected
+insert into t0 values (20, 'the tuple 20')
+Insert OK, 1 row affected
+
+# Select 10 tuples from hot_standby
+
+select * from t0 where k0 = 11
+Found 1 tuple:
+[11, 'the tuple 11']
+select * from t0 where k0 = 12
+Found 1 tuple:
+[12, 'the tuple 12']
+select * from t0 where k0 = 13
+Found 1 tuple:
+[13, 'the tuple 13']
+select * from t0 where k0 = 14
+Found 1 tuple:
+[14, 'the tuple 14']
+select * from t0 where k0 = 15
+Found 1 tuple:
+[15, 'the tuple 15']
+select * from t0 where k0 = 16
+Found 1 tuple:
+[16, 'the tuple 16']
+select * from t0 where k0 = 17
+Found 1 tuple:
+[17, 'the tuple 17']
+select * from t0 where k0 = 18
+Found 1 tuple:
+[18, 'the tuple 18']
+select * from t0 where k0 = 19
+Found 1 tuple:
+[19, 'the tuple 19']
+select * from t0 where k0 = 20
+Found 1 tuple:
+[20, 'the tuple 20']
+
+# Select 10 tuples from replica
+
+select * from t0 where k0 = 11
+Found 1 tuple:
+[11, 'the tuple 11']
+select * from t0 where k0 = 12
+Found 1 tuple:
+[12, 'the tuple 12']
+select * from t0 where k0 = 13
+Found 1 tuple:
+[13, 'the tuple 13']
+select * from t0 where k0 = 14
+Found 1 tuple:
+[14, 'the tuple 14']
+select * from t0 where k0 = 15
+Found 1 tuple:
+[15, 'the tuple 15']
+select * from t0 where k0 = 16
+Found 1 tuple:
+[16, 'the tuple 16']
+select * from t0 where k0 = 17
+Found 1 tuple:
+[17, 'the tuple 17']
+select * from t0 where k0 = 18
+Found 1 tuple:
+[18, 'the tuple 18']
+select * from t0 where k0 = 19
+Found 1 tuple:
+[19, 'the tuple 19']
+select * from t0 where k0 = 20
+Found 1 tuple:
+[20, 'the tuple 20']
diff --git a/test/box_replication/hot_standby.test b/test/box_replication/hot_standby.test
new file mode 100644
index 0000000000000000000000000000000000000000..b1053fb5d8ff7e111cabf81b33bbc25140a8fe4f
--- /dev/null
+++ b/test/box_replication/hot_standby.test
@@ -0,0 +1,85 @@
+import os
+import time
+from lib.tarantool_box_server import TarantoolBoxServer
+
+# master server
+master = server
+
+# hot standby server
+hot_standby = TarantoolBoxServer()
+hot_standby.deploy("box_replication/cfg/hot_standby.cfg",
+                   hot_standby.find_exe(self.args.builddir),
+                   os.path.join(self.args.vardir, "hot_standby"), need_init=False)
+
+# replica server
+replica = TarantoolBoxServer()
+replica.deploy("box_replication/cfg/replica.cfg",
+               replica.find_exe(self.args.builddir),
+               os.path.join(self.args.vardir, "replica"))
+
+# Begin tuple id
+id = 1
+
+
+print """
+# Insert 10 tuples to master
+"""
+for i in range(id, id + 10):
+    master.sql.execute("insert into t0 values (%d, 'the tuple %d')" % (i, i), silent=False)
+
+
+print """
+# Select 10 tuples from master
+"""
+for i in range(id, id + 10):
+    master.sql.execute("select * from t0 where k0 = %d" % i, silent=False)
+
+
+print """
+# Select 10 tuples from replica
+"""
+replica.wait_lsn(11)
+for i in range(id, id + 10):
+    replica.sql.execute("select * from t0 where k0 = %d" % i, silent=False)
+
+
+print """
+# Shutdown master server (now the hot_standby must be a primary server)
+"""
+server.stop()
+
+id += 10
+
+# White while hot_standby server not bind masters ports
+time.sleep(0.2)
+
+print """
+# Insert 10 tuples to hot_standby
+"""
+for i in range(id, id + 10):
+    hot_standby.sql.execute("insert into t0 values (%d, 'the tuple %d')" % (i, i), silent=False)
+
+
+print """
+# Select 10 tuples from hot_standby
+"""
+for i in range(id, id + 10):
+    hot_standby.sql.execute("select * from t0 where k0 = %d" % i, silent=False)
+
+
+print """
+# Select 10 tuples from replica
+"""
+replica.wait_lsn(21)
+for i in range(id, id + 10):
+    replica.sql.execute("select * from t0 where k0 = %d" % i, silent=False)
+
+
+# Cleanup.
+hot_standby.stop()
+hot_standby.cleanup(True)
+replica.stop()
+replica.cleanup(True)
+server.deploy(self.suite_ini["config"])
+
+# vim: syntax=python
diff --git a/test/box_replication/suite.ini b/test/box_replication/suite.ini
index 830fb400442f24d3681d713b03769b882f0a7ca7..a8c85f387be74c96d7680906e5fab6e6ac934fe8 100644
--- a/test/box_replication/suite.ini
+++ b/test/box_replication/suite.ini
@@ -1,3 +1,3 @@
 [default]
 description = tarantool/box, replication
-config = tarantool.cfg
+config = cfg/master.cfg
diff --git a/test/box_replication/swap.result b/test/box_replication/swap.result
new file mode 100644
index 0000000000000000000000000000000000000000..7ec1f839e09a26132c07fdc9a73ebedb9e3e9086
--- /dev/null
+++ b/test/box_replication/swap.result
@@ -0,0 +1,2380 @@
+test 0 iteration
+insert into t0 values (0, 'tuple 0')
+Insert OK, 1 row affected
+insert into t0 values (1, 'tuple 1')
+Insert OK, 1 row affected
+insert into t0 values (2, 'tuple 2')
+Insert OK, 1 row affected
+insert into t0 values (3, 'tuple 3')
+Insert OK, 1 row affected
+insert into t0 values (4, 'tuple 4')
+Insert OK, 1 row affected
+select * from t0 where k0 = 0
+Found 1 tuple:
+[0, 'tuple 0']
+select * from t0 where k0 = 1
+Found 1 tuple:
+[1, 'tuple 1']
+select * from t0 where k0 = 2
+Found 1 tuple:
+[2, 'tuple 2']
+select * from t0 where k0 = 3
+Found 1 tuple:
+[3, 'tuple 3']
+select * from t0 where k0 = 4
+Found 1 tuple:
+[4, 'tuple 4']
+insert into t0 values (5, 'tuple 5')
+Insert OK, 1 row affected
+insert into t0 values (6, 'tuple 6')
+Insert OK, 1 row affected
+insert into t0 values (7, 'tuple 7')
+Insert OK, 1 row affected
+insert into t0 values (8, 'tuple 8')
+Insert OK, 1 row affected
+insert into t0 values (9, 'tuple 9')
+Insert OK, 1 row affected
+select * from t0 where k0 = 5
+Found 1 tuple:
+[5, 'tuple 5']
+select * from t0 where k0 = 6
+Found 1 tuple:
+[6, 'tuple 6']
+select * from t0 where k0 = 7
+Found 1 tuple:
+[7, 'tuple 7']
+select * from t0 where k0 = 8
+Found 1 tuple:
+[8, 'tuple 8']
+select * from t0 where k0 = 9
+Found 1 tuple:
+[9, 'tuple 9']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (10, 'tuple 10')
+Insert OK, 1 row affected
+insert into t0 values (11, 'tuple 11')
+Insert OK, 1 row affected
+insert into t0 values (12, 'tuple 12')
+Insert OK, 1 row affected
+insert into t0 values (13, 'tuple 13')
+Insert OK, 1 row affected
+insert into t0 values (14, 'tuple 14')
+Insert OK, 1 row affected
+select * from t0 where k0 = 10
+Found 1 tuple:
+[10, 'tuple 10']
+select * from t0 where k0 = 11
+Found 1 tuple:
+[11, 'tuple 11']
+select * from t0 where k0 = 12
+Found 1 tuple:
+[12, 'tuple 12']
+select * from t0 where k0 = 13
+Found 1 tuple:
+[13, 'tuple 13']
+select * from t0 where k0 = 14
+Found 1 tuple:
+[14, 'tuple 14']
+insert into t0 values (15, 'tuple 15')
+Insert OK, 1 row affected
+insert into t0 values (16, 'tuple 16')
+Insert OK, 1 row affected
+insert into t0 values (17, 'tuple 17')
+Insert OK, 1 row affected
+insert into t0 values (18, 'tuple 18')
+Insert OK, 1 row affected
+insert into t0 values (19, 'tuple 19')
+Insert OK, 1 row affected
+select * from t0 where k0 = 15
+Found 1 tuple:
+[15, 'tuple 15']
+select * from t0 where k0 = 16
+Found 1 tuple:
+[16, 'tuple 16']
+select * from t0 where k0 = 17
+Found 1 tuple:
+[17, 'tuple 17']
+select * from t0 where k0 = 18
+Found 1 tuple:
+[18, 'tuple 18']
+select * from t0 where k0 = 19
+Found 1 tuple:
+[19, 'tuple 19']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 1 iteration
+insert into t0 values (20, 'tuple 20')
+Insert OK, 1 row affected
+insert into t0 values (21, 'tuple 21')
+Insert OK, 1 row affected
+insert into t0 values (22, 'tuple 22')
+Insert OK, 1 row affected
+insert into t0 values (23, 'tuple 23')
+Insert OK, 1 row affected
+insert into t0 values (24, 'tuple 24')
+Insert OK, 1 row affected
+select * from t0 where k0 = 20
+Found 1 tuple:
+[20, 'tuple 20']
+select * from t0 where k0 = 21
+Found 1 tuple:
+[21, 'tuple 21']
+select * from t0 where k0 = 22
+Found 1 tuple:
+[22, 'tuple 22']
+select * from t0 where k0 = 23
+Found 1 tuple:
+[23, 'tuple 23']
+select * from t0 where k0 = 24
+Found 1 tuple:
+[24, 'tuple 24']
+insert into t0 values (25, 'tuple 25')
+Insert OK, 1 row affected
+insert into t0 values (26, 'tuple 26')
+Insert OK, 1 row affected
+insert into t0 values (27, 'tuple 27')
+Insert OK, 1 row affected
+insert into t0 values (28, 'tuple 28')
+Insert OK, 1 row affected
+insert into t0 values (29, 'tuple 29')
+Insert OK, 1 row affected
+select * from t0 where k0 = 25
+Found 1 tuple:
+[25, 'tuple 25']
+select * from t0 where k0 = 26
+Found 1 tuple:
+[26, 'tuple 26']
+select * from t0 where k0 = 27
+Found 1 tuple:
+[27, 'tuple 27']
+select * from t0 where k0 = 28
+Found 1 tuple:
+[28, 'tuple 28']
+select * from t0 where k0 = 29
+Found 1 tuple:
+[29, 'tuple 29']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (30, 'tuple 30')
+Insert OK, 1 row affected
+insert into t0 values (31, 'tuple 31')
+Insert OK, 1 row affected
+insert into t0 values (32, 'tuple 32')
+Insert OK, 1 row affected
+insert into t0 values (33, 'tuple 33')
+Insert OK, 1 row affected
+insert into t0 values (34, 'tuple 34')
+Insert OK, 1 row affected
+select * from t0 where k0 = 30
+Found 1 tuple:
+[30, 'tuple 30']
+select * from t0 where k0 = 31
+Found 1 tuple:
+[31, 'tuple 31']
+select * from t0 where k0 = 32
+Found 1 tuple:
+[32, 'tuple 32']
+select * from t0 where k0 = 33
+Found 1 tuple:
+[33, 'tuple 33']
+select * from t0 where k0 = 34
+Found 1 tuple:
+[34, 'tuple 34']
+insert into t0 values (35, 'tuple 35')
+Insert OK, 1 row affected
+insert into t0 values (36, 'tuple 36')
+Insert OK, 1 row affected
+insert into t0 values (37, 'tuple 37')
+Insert OK, 1 row affected
+insert into t0 values (38, 'tuple 38')
+Insert OK, 1 row affected
+insert into t0 values (39, 'tuple 39')
+Insert OK, 1 row affected
+select * from t0 where k0 = 35
+Found 1 tuple:
+[35, 'tuple 35']
+select * from t0 where k0 = 36
+Found 1 tuple:
+[36, 'tuple 36']
+select * from t0 where k0 = 37
+Found 1 tuple:
+[37, 'tuple 37']
+select * from t0 where k0 = 38
+Found 1 tuple:
+[38, 'tuple 38']
+select * from t0 where k0 = 39
+Found 1 tuple:
+[39, 'tuple 39']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 2 iteration
+insert into t0 values (40, 'tuple 40')
+Insert OK, 1 row affected
+insert into t0 values (41, 'tuple 41')
+Insert OK, 1 row affected
+insert into t0 values (42, 'tuple 42')
+Insert OK, 1 row affected
+insert into t0 values (43, 'tuple 43')
+Insert OK, 1 row affected
+insert into t0 values (44, 'tuple 44')
+Insert OK, 1 row affected
+select * from t0 where k0 = 40
+Found 1 tuple:
+[40, 'tuple 40']
+select * from t0 where k0 = 41
+Found 1 tuple:
+[41, 'tuple 41']
+select * from t0 where k0 = 42
+Found 1 tuple:
+[42, 'tuple 42']
+select * from t0 where k0 = 43
+Found 1 tuple:
+[43, 'tuple 43']
+select * from t0 where k0 = 44
+Found 1 tuple:
+[44, 'tuple 44']
+insert into t0 values (45, 'tuple 45')
+Insert OK, 1 row affected
+insert into t0 values (46, 'tuple 46')
+Insert OK, 1 row affected
+insert into t0 values (47, 'tuple 47')
+Insert OK, 1 row affected
+insert into t0 values (48, 'tuple 48')
+Insert OK, 1 row affected
+insert into t0 values (49, 'tuple 49')
+Insert OK, 1 row affected
+select * from t0 where k0 = 45
+Found 1 tuple:
+[45, 'tuple 45']
+select * from t0 where k0 = 46
+Found 1 tuple:
+[46, 'tuple 46']
+select * from t0 where k0 = 47
+Found 1 tuple:
+[47, 'tuple 47']
+select * from t0 where k0 = 48
+Found 1 tuple:
+[48, 'tuple 48']
+select * from t0 where k0 = 49
+Found 1 tuple:
+[49, 'tuple 49']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (50, 'tuple 50')
+Insert OK, 1 row affected
+insert into t0 values (51, 'tuple 51')
+Insert OK, 1 row affected
+insert into t0 values (52, 'tuple 52')
+Insert OK, 1 row affected
+insert into t0 values (53, 'tuple 53')
+Insert OK, 1 row affected
+insert into t0 values (54, 'tuple 54')
+Insert OK, 1 row affected
+select * from t0 where k0 = 50
+Found 1 tuple:
+[50, 'tuple 50']
+select * from t0 where k0 = 51
+Found 1 tuple:
+[51, 'tuple 51']
+select * from t0 where k0 = 52
+Found 1 tuple:
+[52, 'tuple 52']
+select * from t0 where k0 = 53
+Found 1 tuple:
+[53, 'tuple 53']
+select * from t0 where k0 = 54
+Found 1 tuple:
+[54, 'tuple 54']
+insert into t0 values (55, 'tuple 55')
+Insert OK, 1 row affected
+insert into t0 values (56, 'tuple 56')
+Insert OK, 1 row affected
+insert into t0 values (57, 'tuple 57')
+Insert OK, 1 row affected
+insert into t0 values (58, 'tuple 58')
+Insert OK, 1 row affected
+insert into t0 values (59, 'tuple 59')
+Insert OK, 1 row affected
+select * from t0 where k0 = 55
+Found 1 tuple:
+[55, 'tuple 55']
+select * from t0 where k0 = 56
+Found 1 tuple:
+[56, 'tuple 56']
+select * from t0 where k0 = 57
+Found 1 tuple:
+[57, 'tuple 57']
+select * from t0 where k0 = 58
+Found 1 tuple:
+[58, 'tuple 58']
+select * from t0 where k0 = 59
+Found 1 tuple:
+[59, 'tuple 59']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 3 iteration
+insert into t0 values (60, 'tuple 60')
+Insert OK, 1 row affected
+insert into t0 values (61, 'tuple 61')
+Insert OK, 1 row affected
+insert into t0 values (62, 'tuple 62')
+Insert OK, 1 row affected
+insert into t0 values (63, 'tuple 63')
+Insert OK, 1 row affected
+insert into t0 values (64, 'tuple 64')
+Insert OK, 1 row affected
+select * from t0 where k0 = 60
+Found 1 tuple:
+[60, 'tuple 60']
+select * from t0 where k0 = 61
+Found 1 tuple:
+[61, 'tuple 61']
+select * from t0 where k0 = 62
+Found 1 tuple:
+[62, 'tuple 62']
+select * from t0 where k0 = 63
+Found 1 tuple:
+[63, 'tuple 63']
+select * from t0 where k0 = 64
+Found 1 tuple:
+[64, 'tuple 64']
+insert into t0 values (65, 'tuple 65')
+Insert OK, 1 row affected
+insert into t0 values (66, 'tuple 66')
+Insert OK, 1 row affected
+insert into t0 values (67, 'tuple 67')
+Insert OK, 1 row affected
+insert into t0 values (68, 'tuple 68')
+Insert OK, 1 row affected
+insert into t0 values (69, 'tuple 69')
+Insert OK, 1 row affected
+select * from t0 where k0 = 65
+Found 1 tuple:
+[65, 'tuple 65']
+select * from t0 where k0 = 66
+Found 1 tuple:
+[66, 'tuple 66']
+select * from t0 where k0 = 67
+Found 1 tuple:
+[67, 'tuple 67']
+select * from t0 where k0 = 68
+Found 1 tuple:
+[68, 'tuple 68']
+select * from t0 where k0 = 69
+Found 1 tuple:
+[69, 'tuple 69']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (70, 'tuple 70')
+Insert OK, 1 row affected
+insert into t0 values (71, 'tuple 71')
+Insert OK, 1 row affected
+insert into t0 values (72, 'tuple 72')
+Insert OK, 1 row affected
+insert into t0 values (73, 'tuple 73')
+Insert OK, 1 row affected
+insert into t0 values (74, 'tuple 74')
+Insert OK, 1 row affected
+select * from t0 where k0 = 70
+Found 1 tuple:
+[70, 'tuple 70']
+select * from t0 where k0 = 71
+Found 1 tuple:
+[71, 'tuple 71']
+select * from t0 where k0 = 72
+Found 1 tuple:
+[72, 'tuple 72']
+select * from t0 where k0 = 73
+Found 1 tuple:
+[73, 'tuple 73']
+select * from t0 where k0 = 74
+Found 1 tuple:
+[74, 'tuple 74']
+insert into t0 values (75, 'tuple 75')
+Insert OK, 1 row affected
+insert into t0 values (76, 'tuple 76')
+Insert OK, 1 row affected
+insert into t0 values (77, 'tuple 77')
+Insert OK, 1 row affected
+insert into t0 values (78, 'tuple 78')
+Insert OK, 1 row affected
+insert into t0 values (79, 'tuple 79')
+Insert OK, 1 row affected
+select * from t0 where k0 = 75
+Found 1 tuple:
+[75, 'tuple 75']
+select * from t0 where k0 = 76
+Found 1 tuple:
+[76, 'tuple 76']
+select * from t0 where k0 = 77
+Found 1 tuple:
+[77, 'tuple 77']
+select * from t0 where k0 = 78
+Found 1 tuple:
+[78, 'tuple 78']
+select * from t0 where k0 = 79
+Found 1 tuple:
+[79, 'tuple 79']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 4 iteration
+insert into t0 values (80, 'tuple 80')
+Insert OK, 1 row affected
+insert into t0 values (81, 'tuple 81')
+Insert OK, 1 row affected
+insert into t0 values (82, 'tuple 82')
+Insert OK, 1 row affected
+insert into t0 values (83, 'tuple 83')
+Insert OK, 1 row affected
+insert into t0 values (84, 'tuple 84')
+Insert OK, 1 row affected
+select * from t0 where k0 = 80
+Found 1 tuple:
+[80, 'tuple 80']
+select * from t0 where k0 = 81
+Found 1 tuple:
+[81, 'tuple 81']
+select * from t0 where k0 = 82
+Found 1 tuple:
+[82, 'tuple 82']
+select * from t0 where k0 = 83
+Found 1 tuple:
+[83, 'tuple 83']
+select * from t0 where k0 = 84
+Found 1 tuple:
+[84, 'tuple 84']
+insert into t0 values (85, 'tuple 85')
+Insert OK, 1 row affected
+insert into t0 values (86, 'tuple 86')
+Insert OK, 1 row affected
+insert into t0 values (87, 'tuple 87')
+Insert OK, 1 row affected
+insert into t0 values (88, 'tuple 88')
+Insert OK, 1 row affected
+insert into t0 values (89, 'tuple 89')
+Insert OK, 1 row affected
+select * from t0 where k0 = 85
+Found 1 tuple:
+[85, 'tuple 85']
+select * from t0 where k0 = 86
+Found 1 tuple:
+[86, 'tuple 86']
+select * from t0 where k0 = 87
+Found 1 tuple:
+[87, 'tuple 87']
+select * from t0 where k0 = 88
+Found 1 tuple:
+[88, 'tuple 88']
+select * from t0 where k0 = 89
+Found 1 tuple:
+[89, 'tuple 89']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (90, 'tuple 90')
+Insert OK, 1 row affected
+insert into t0 values (91, 'tuple 91')
+Insert OK, 1 row affected
+insert into t0 values (92, 'tuple 92')
+Insert OK, 1 row affected
+insert into t0 values (93, 'tuple 93')
+Insert OK, 1 row affected
+insert into t0 values (94, 'tuple 94')
+Insert OK, 1 row affected
+select * from t0 where k0 = 90
+Found 1 tuple:
+[90, 'tuple 90']
+select * from t0 where k0 = 91
+Found 1 tuple:
+[91, 'tuple 91']
+select * from t0 where k0 = 92
+Found 1 tuple:
+[92, 'tuple 92']
+select * from t0 where k0 = 93
+Found 1 tuple:
+[93, 'tuple 93']
+select * from t0 where k0 = 94
+Found 1 tuple:
+[94, 'tuple 94']
+insert into t0 values (95, 'tuple 95')
+Insert OK, 1 row affected
+insert into t0 values (96, 'tuple 96')
+Insert OK, 1 row affected
+insert into t0 values (97, 'tuple 97')
+Insert OK, 1 row affected
+insert into t0 values (98, 'tuple 98')
+Insert OK, 1 row affected
+insert into t0 values (99, 'tuple 99')
+Insert OK, 1 row affected
+select * from t0 where k0 = 95
+Found 1 tuple:
+[95, 'tuple 95']
+select * from t0 where k0 = 96
+Found 1 tuple:
+[96, 'tuple 96']
+select * from t0 where k0 = 97
+Found 1 tuple:
+[97, 'tuple 97']
+select * from t0 where k0 = 98
+Found 1 tuple:
+[98, 'tuple 98']
+select * from t0 where k0 = 99
+Found 1 tuple:
+[99, 'tuple 99']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 5 iteration
+insert into t0 values (100, 'tuple 100')
+Insert OK, 1 row affected
+insert into t0 values (101, 'tuple 101')
+Insert OK, 1 row affected
+insert into t0 values (102, 'tuple 102')
+Insert OK, 1 row affected
+insert into t0 values (103, 'tuple 103')
+Insert OK, 1 row affected
+insert into t0 values (104, 'tuple 104')
+Insert OK, 1 row affected
+select * from t0 where k0 = 100
+Found 1 tuple:
+[100, 'tuple 100']
+select * from t0 where k0 = 101
+Found 1 tuple:
+[101, 'tuple 101']
+select * from t0 where k0 = 102
+Found 1 tuple:
+[102, 'tuple 102']
+select * from t0 where k0 = 103
+Found 1 tuple:
+[103, 'tuple 103']
+select * from t0 where k0 = 104
+Found 1 tuple:
+[104, 'tuple 104']
+insert into t0 values (105, 'tuple 105')
+Insert OK, 1 row affected
+insert into t0 values (106, 'tuple 106')
+Insert OK, 1 row affected
+insert into t0 values (107, 'tuple 107')
+Insert OK, 1 row affected
+insert into t0 values (108, 'tuple 108')
+Insert OK, 1 row affected
+insert into t0 values (109, 'tuple 109')
+Insert OK, 1 row affected
+select * from t0 where k0 = 105
+Found 1 tuple:
+[105, 'tuple 105']
+select * from t0 where k0 = 106
+Found 1 tuple:
+[106, 'tuple 106']
+select * from t0 where k0 = 107
+Found 1 tuple:
+[107, 'tuple 107']
+select * from t0 where k0 = 108
+Found 1 tuple:
+[108, 'tuple 108']
+select * from t0 where k0 = 109
+Found 1 tuple:
+[109, 'tuple 109']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (110, 'tuple 110')
+Insert OK, 1 row affected
+insert into t0 values (111, 'tuple 111')
+Insert OK, 1 row affected
+insert into t0 values (112, 'tuple 112')
+Insert OK, 1 row affected
+insert into t0 values (113, 'tuple 113')
+Insert OK, 1 row affected
+insert into t0 values (114, 'tuple 114')
+Insert OK, 1 row affected
+select * from t0 where k0 = 110
+Found 1 tuple:
+[110, 'tuple 110']
+select * from t0 where k0 = 111
+Found 1 tuple:
+[111, 'tuple 111']
+select * from t0 where k0 = 112
+Found 1 tuple:
+[112, 'tuple 112']
+select * from t0 where k0 = 113
+Found 1 tuple:
+[113, 'tuple 113']
+select * from t0 where k0 = 114
+Found 1 tuple:
+[114, 'tuple 114']
+insert into t0 values (115, 'tuple 115')
+Insert OK, 1 row affected
+insert into t0 values (116, 'tuple 116')
+Insert OK, 1 row affected
+insert into t0 values (117, 'tuple 117')
+Insert OK, 1 row affected
+insert into t0 values (118, 'tuple 118')
+Insert OK, 1 row affected
+insert into t0 values (119, 'tuple 119')
+Insert OK, 1 row affected
+select * from t0 where k0 = 115
+Found 1 tuple:
+[115, 'tuple 115']
+select * from t0 where k0 = 116
+Found 1 tuple:
+[116, 'tuple 116']
+select * from t0 where k0 = 117
+Found 1 tuple:
+[117, 'tuple 117']
+select * from t0 where k0 = 118
+Found 1 tuple:
+[118, 'tuple 118']
+select * from t0 where k0 = 119
+Found 1 tuple:
+[119, 'tuple 119']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 6 iteration
+insert into t0 values (120, 'tuple 120')
+Insert OK, 1 row affected
+insert into t0 values (121, 'tuple 121')
+Insert OK, 1 row affected
+insert into t0 values (122, 'tuple 122')
+Insert OK, 1 row affected
+insert into t0 values (123, 'tuple 123')
+Insert OK, 1 row affected
+insert into t0 values (124, 'tuple 124')
+Insert OK, 1 row affected
+select * from t0 where k0 = 120
+Found 1 tuple:
+[120, 'tuple 120']
+select * from t0 where k0 = 121
+Found 1 tuple:
+[121, 'tuple 121']
+select * from t0 where k0 = 122
+Found 1 tuple:
+[122, 'tuple 122']
+select * from t0 where k0 = 123
+Found 1 tuple:
+[123, 'tuple 123']
+select * from t0 where k0 = 124
+Found 1 tuple:
+[124, 'tuple 124']
+insert into t0 values (125, 'tuple 125')
+Insert OK, 1 row affected
+insert into t0 values (126, 'tuple 126')
+Insert OK, 1 row affected
+insert into t0 values (127, 'tuple 127')
+Insert OK, 1 row affected
+insert into t0 values (128, 'tuple 128')
+Insert OK, 1 row affected
+insert into t0 values (129, 'tuple 129')
+Insert OK, 1 row affected
+select * from t0 where k0 = 125
+Found 1 tuple:
+[125, 'tuple 125']
+select * from t0 where k0 = 126
+Found 1 tuple:
+[126, 'tuple 126']
+select * from t0 where k0 = 127
+Found 1 tuple:
+[127, 'tuple 127']
+select * from t0 where k0 = 128
+Found 1 tuple:
+[128, 'tuple 128']
+select * from t0 where k0 = 129
+Found 1 tuple:
+[129, 'tuple 129']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (130, 'tuple 130')
+Insert OK, 1 row affected
+insert into t0 values (131, 'tuple 131')
+Insert OK, 1 row affected
+insert into t0 values (132, 'tuple 132')
+Insert OK, 1 row affected
+insert into t0 values (133, 'tuple 133')
+Insert OK, 1 row affected
+insert into t0 values (134, 'tuple 134')
+Insert OK, 1 row affected
+select * from t0 where k0 = 130
+Found 1 tuple:
+[130, 'tuple 130']
+select * from t0 where k0 = 131
+Found 1 tuple:
+[131, 'tuple 131']
+select * from t0 where k0 = 132
+Found 1 tuple:
+[132, 'tuple 132']
+select * from t0 where k0 = 133
+Found 1 tuple:
+[133, 'tuple 133']
+select * from t0 where k0 = 134
+Found 1 tuple:
+[134, 'tuple 134']
+insert into t0 values (135, 'tuple 135')
+Insert OK, 1 row affected
+insert into t0 values (136, 'tuple 136')
+Insert OK, 1 row affected
+insert into t0 values (137, 'tuple 137')
+Insert OK, 1 row affected
+insert into t0 values (138, 'tuple 138')
+Insert OK, 1 row affected
+insert into t0 values (139, 'tuple 139')
+Insert OK, 1 row affected
+select * from t0 where k0 = 135
+Found 1 tuple:
+[135, 'tuple 135']
+select * from t0 where k0 = 136
+Found 1 tuple:
+[136, 'tuple 136']
+select * from t0 where k0 = 137
+Found 1 tuple:
+[137, 'tuple 137']
+select * from t0 where k0 = 138
+Found 1 tuple:
+[138, 'tuple 138']
+select * from t0 where k0 = 139
+Found 1 tuple:
+[139, 'tuple 139']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 7 iteration
+insert into t0 values (140, 'tuple 140')
+Insert OK, 1 row affected
+insert into t0 values (141, 'tuple 141')
+Insert OK, 1 row affected
+insert into t0 values (142, 'tuple 142')
+Insert OK, 1 row affected
+insert into t0 values (143, 'tuple 143')
+Insert OK, 1 row affected
+insert into t0 values (144, 'tuple 144')
+Insert OK, 1 row affected
+select * from t0 where k0 = 140
+Found 1 tuple:
+[140, 'tuple 140']
+select * from t0 where k0 = 141
+Found 1 tuple:
+[141, 'tuple 141']
+select * from t0 where k0 = 142
+Found 1 tuple:
+[142, 'tuple 142']
+select * from t0 where k0 = 143
+Found 1 tuple:
+[143, 'tuple 143']
+select * from t0 where k0 = 144
+Found 1 tuple:
+[144, 'tuple 144']
+insert into t0 values (145, 'tuple 145')
+Insert OK, 1 row affected
+insert into t0 values (146, 'tuple 146')
+Insert OK, 1 row affected
+insert into t0 values (147, 'tuple 147')
+Insert OK, 1 row affected
+insert into t0 values (148, 'tuple 148')
+Insert OK, 1 row affected
+insert into t0 values (149, 'tuple 149')
+Insert OK, 1 row affected
+select * from t0 where k0 = 145
+Found 1 tuple:
+[145, 'tuple 145']
+select * from t0 where k0 = 146
+Found 1 tuple:
+[146, 'tuple 146']
+select * from t0 where k0 = 147
+Found 1 tuple:
+[147, 'tuple 147']
+select * from t0 where k0 = 148
+Found 1 tuple:
+[148, 'tuple 148']
+select * from t0 where k0 = 149
+Found 1 tuple:
+[149, 'tuple 149']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (150, 'tuple 150')
+Insert OK, 1 row affected
+insert into t0 values (151, 'tuple 151')
+Insert OK, 1 row affected
+insert into t0 values (152, 'tuple 152')
+Insert OK, 1 row affected
+insert into t0 values (153, 'tuple 153')
+Insert OK, 1 row affected
+insert into t0 values (154, 'tuple 154')
+Insert OK, 1 row affected
+select * from t0 where k0 = 150
+Found 1 tuple:
+[150, 'tuple 150']
+select * from t0 where k0 = 151
+Found 1 tuple:
+[151, 'tuple 151']
+select * from t0 where k0 = 152
+Found 1 tuple:
+[152, 'tuple 152']
+select * from t0 where k0 = 153
+Found 1 tuple:
+[153, 'tuple 153']
+select * from t0 where k0 = 154
+Found 1 tuple:
+[154, 'tuple 154']
+insert into t0 values (155, 'tuple 155')
+Insert OK, 1 row affected
+insert into t0 values (156, 'tuple 156')
+Insert OK, 1 row affected
+insert into t0 values (157, 'tuple 157')
+Insert OK, 1 row affected
+insert into t0 values (158, 'tuple 158')
+Insert OK, 1 row affected
+insert into t0 values (159, 'tuple 159')
+Insert OK, 1 row affected
+select * from t0 where k0 = 155
+Found 1 tuple:
+[155, 'tuple 155']
+select * from t0 where k0 = 156
+Found 1 tuple:
+[156, 'tuple 156']
+select * from t0 where k0 = 157
+Found 1 tuple:
+[157, 'tuple 157']
+select * from t0 where k0 = 158
+Found 1 tuple:
+[158, 'tuple 158']
+select * from t0 where k0 = 159
+Found 1 tuple:
+[159, 'tuple 159']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 8 iteration
+insert into t0 values (160, 'tuple 160')
+Insert OK, 1 row affected
+insert into t0 values (161, 'tuple 161')
+Insert OK, 1 row affected
+insert into t0 values (162, 'tuple 162')
+Insert OK, 1 row affected
+insert into t0 values (163, 'tuple 163')
+Insert OK, 1 row affected
+insert into t0 values (164, 'tuple 164')
+Insert OK, 1 row affected
+select * from t0 where k0 = 160
+Found 1 tuple:
+[160, 'tuple 160']
+select * from t0 where k0 = 161
+Found 1 tuple:
+[161, 'tuple 161']
+select * from t0 where k0 = 162
+Found 1 tuple:
+[162, 'tuple 162']
+select * from t0 where k0 = 163
+Found 1 tuple:
+[163, 'tuple 163']
+select * from t0 where k0 = 164
+Found 1 tuple:
+[164, 'tuple 164']
+insert into t0 values (165, 'tuple 165')
+Insert OK, 1 row affected
+insert into t0 values (166, 'tuple 166')
+Insert OK, 1 row affected
+insert into t0 values (167, 'tuple 167')
+Insert OK, 1 row affected
+insert into t0 values (168, 'tuple 168')
+Insert OK, 1 row affected
+insert into t0 values (169, 'tuple 169')
+Insert OK, 1 row affected
+select * from t0 where k0 = 165
+Found 1 tuple:
+[165, 'tuple 165']
+select * from t0 where k0 = 166
+Found 1 tuple:
+[166, 'tuple 166']
+select * from t0 where k0 = 167
+Found 1 tuple:
+[167, 'tuple 167']
+select * from t0 where k0 = 168
+Found 1 tuple:
+[168, 'tuple 168']
+select * from t0 where k0 = 169
+Found 1 tuple:
+[169, 'tuple 169']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (170, 'tuple 170')
+Insert OK, 1 row affected
+insert into t0 values (171, 'tuple 171')
+Insert OK, 1 row affected
+insert into t0 values (172, 'tuple 172')
+Insert OK, 1 row affected
+insert into t0 values (173, 'tuple 173')
+Insert OK, 1 row affected
+insert into t0 values (174, 'tuple 174')
+Insert OK, 1 row affected
+select * from t0 where k0 = 170
+Found 1 tuple:
+[170, 'tuple 170']
+select * from t0 where k0 = 171
+Found 1 tuple:
+[171, 'tuple 171']
+select * from t0 where k0 = 172
+Found 1 tuple:
+[172, 'tuple 172']
+select * from t0 where k0 = 173
+Found 1 tuple:
+[173, 'tuple 173']
+select * from t0 where k0 = 174
+Found 1 tuple:
+[174, 'tuple 174']
+insert into t0 values (175, 'tuple 175')
+Insert OK, 1 row affected
+insert into t0 values (176, 'tuple 176')
+Insert OK, 1 row affected
+insert into t0 values (177, 'tuple 177')
+Insert OK, 1 row affected
+insert into t0 values (178, 'tuple 178')
+Insert OK, 1 row affected
+insert into t0 values (179, 'tuple 179')
+Insert OK, 1 row affected
+select * from t0 where k0 = 175
+Found 1 tuple:
+[175, 'tuple 175']
+select * from t0 where k0 = 176
+Found 1 tuple:
+[176, 'tuple 176']
+select * from t0 where k0 = 177
+Found 1 tuple:
+[177, 'tuple 177']
+select * from t0 where k0 = 178
+Found 1 tuple:
+[178, 'tuple 178']
+select * from t0 where k0 = 179
+Found 1 tuple:
+[179, 'tuple 179']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 9 iteration
+insert into t0 values (180, 'tuple 180')
+Insert OK, 1 row affected
+insert into t0 values (181, 'tuple 181')
+Insert OK, 1 row affected
+insert into t0 values (182, 'tuple 182')
+Insert OK, 1 row affected
+insert into t0 values (183, 'tuple 183')
+Insert OK, 1 row affected
+insert into t0 values (184, 'tuple 184')
+Insert OK, 1 row affected
+select * from t0 where k0 = 180
+Found 1 tuple:
+[180, 'tuple 180']
+select * from t0 where k0 = 181
+Found 1 tuple:
+[181, 'tuple 181']
+select * from t0 where k0 = 182
+Found 1 tuple:
+[182, 'tuple 182']
+select * from t0 where k0 = 183
+Found 1 tuple:
+[183, 'tuple 183']
+select * from t0 where k0 = 184
+Found 1 tuple:
+[184, 'tuple 184']
+insert into t0 values (185, 'tuple 185')
+Insert OK, 1 row affected
+insert into t0 values (186, 'tuple 186')
+Insert OK, 1 row affected
+insert into t0 values (187, 'tuple 187')
+Insert OK, 1 row affected
+insert into t0 values (188, 'tuple 188')
+Insert OK, 1 row affected
+insert into t0 values (189, 'tuple 189')
+Insert OK, 1 row affected
+select * from t0 where k0 = 185
+Found 1 tuple:
+[185, 'tuple 185']
+select * from t0 where k0 = 186
+Found 1 tuple:
+[186, 'tuple 186']
+select * from t0 where k0 = 187
+Found 1 tuple:
+[187, 'tuple 187']
+select * from t0 where k0 = 188
+Found 1 tuple:
+[188, 'tuple 188']
+select * from t0 where k0 = 189
+Found 1 tuple:
+[189, 'tuple 189']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (190, 'tuple 190')
+Insert OK, 1 row affected
+insert into t0 values (191, 'tuple 191')
+Insert OK, 1 row affected
+insert into t0 values (192, 'tuple 192')
+Insert OK, 1 row affected
+insert into t0 values (193, 'tuple 193')
+Insert OK, 1 row affected
+insert into t0 values (194, 'tuple 194')
+Insert OK, 1 row affected
+select * from t0 where k0 = 190
+Found 1 tuple:
+[190, 'tuple 190']
+select * from t0 where k0 = 191
+Found 1 tuple:
+[191, 'tuple 191']
+select * from t0 where k0 = 192
+Found 1 tuple:
+[192, 'tuple 192']
+select * from t0 where k0 = 193
+Found 1 tuple:
+[193, 'tuple 193']
+select * from t0 where k0 = 194
+Found 1 tuple:
+[194, 'tuple 194']
+insert into t0 values (195, 'tuple 195')
+Insert OK, 1 row affected
+insert into t0 values (196, 'tuple 196')
+Insert OK, 1 row affected
+insert into t0 values (197, 'tuple 197')
+Insert OK, 1 row affected
+insert into t0 values (198, 'tuple 198')
+Insert OK, 1 row affected
+insert into t0 values (199, 'tuple 199')
+Insert OK, 1 row affected
+select * from t0 where k0 = 195
+Found 1 tuple:
+[195, 'tuple 195']
+select * from t0 where k0 = 196
+Found 1 tuple:
+[196, 'tuple 196']
+select * from t0 where k0 = 197
+Found 1 tuple:
+[197, 'tuple 197']
+select * from t0 where k0 = 198
+Found 1 tuple:
+[198, 'tuple 198']
+select * from t0 where k0 = 199
+Found 1 tuple:
+[199, 'tuple 199']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 10 iteration
+insert into t0 values (200, 'tuple 200')
+Insert OK, 1 row affected
+insert into t0 values (201, 'tuple 201')
+Insert OK, 1 row affected
+insert into t0 values (202, 'tuple 202')
+Insert OK, 1 row affected
+insert into t0 values (203, 'tuple 203')
+Insert OK, 1 row affected
+insert into t0 values (204, 'tuple 204')
+Insert OK, 1 row affected
+select * from t0 where k0 = 200
+Found 1 tuple:
+[200, 'tuple 200']
+select * from t0 where k0 = 201
+Found 1 tuple:
+[201, 'tuple 201']
+select * from t0 where k0 = 202
+Found 1 tuple:
+[202, 'tuple 202']
+select * from t0 where k0 = 203
+Found 1 tuple:
+[203, 'tuple 203']
+select * from t0 where k0 = 204
+Found 1 tuple:
+[204, 'tuple 204']
+insert into t0 values (205, 'tuple 205')
+Insert OK, 1 row affected
+insert into t0 values (206, 'tuple 206')
+Insert OK, 1 row affected
+insert into t0 values (207, 'tuple 207')
+Insert OK, 1 row affected
+insert into t0 values (208, 'tuple 208')
+Insert OK, 1 row affected
+insert into t0 values (209, 'tuple 209')
+Insert OK, 1 row affected
+select * from t0 where k0 = 205
+Found 1 tuple:
+[205, 'tuple 205']
+select * from t0 where k0 = 206
+Found 1 tuple:
+[206, 'tuple 206']
+select * from t0 where k0 = 207
+Found 1 tuple:
+[207, 'tuple 207']
+select * from t0 where k0 = 208
+Found 1 tuple:
+[208, 'tuple 208']
+select * from t0 where k0 = 209
+Found 1 tuple:
+[209, 'tuple 209']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (210, 'tuple 210')
+Insert OK, 1 row affected
+insert into t0 values (211, 'tuple 211')
+Insert OK, 1 row affected
+insert into t0 values (212, 'tuple 212')
+Insert OK, 1 row affected
+insert into t0 values (213, 'tuple 213')
+Insert OK, 1 row affected
+insert into t0 values (214, 'tuple 214')
+Insert OK, 1 row affected
+select * from t0 where k0 = 210
+Found 1 tuple:
+[210, 'tuple 210']
+select * from t0 where k0 = 211
+Found 1 tuple:
+[211, 'tuple 211']
+select * from t0 where k0 = 212
+Found 1 tuple:
+[212, 'tuple 212']
+select * from t0 where k0 = 213
+Found 1 tuple:
+[213, 'tuple 213']
+select * from t0 where k0 = 214
+Found 1 tuple:
+[214, 'tuple 214']
+insert into t0 values (215, 'tuple 215')
+Insert OK, 1 row affected
+insert into t0 values (216, 'tuple 216')
+Insert OK, 1 row affected
+insert into t0 values (217, 'tuple 217')
+Insert OK, 1 row affected
+insert into t0 values (218, 'tuple 218')
+Insert OK, 1 row affected
+insert into t0 values (219, 'tuple 219')
+Insert OK, 1 row affected
+select * from t0 where k0 = 215
+Found 1 tuple:
+[215, 'tuple 215']
+select * from t0 where k0 = 216
+Found 1 tuple:
+[216, 'tuple 216']
+select * from t0 where k0 = 217
+Found 1 tuple:
+[217, 'tuple 217']
+select * from t0 where k0 = 218
+Found 1 tuple:
+[218, 'tuple 218']
+select * from t0 where k0 = 219
+Found 1 tuple:
+[219, 'tuple 219']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 11 iteration
+insert into t0 values (220, 'tuple 220')
+Insert OK, 1 row affected
+insert into t0 values (221, 'tuple 221')
+Insert OK, 1 row affected
+insert into t0 values (222, 'tuple 222')
+Insert OK, 1 row affected
+insert into t0 values (223, 'tuple 223')
+Insert OK, 1 row affected
+insert into t0 values (224, 'tuple 224')
+Insert OK, 1 row affected
+select * from t0 where k0 = 220
+Found 1 tuple:
+[220, 'tuple 220']
+select * from t0 where k0 = 221
+Found 1 tuple:
+[221, 'tuple 221']
+select * from t0 where k0 = 222
+Found 1 tuple:
+[222, 'tuple 222']
+select * from t0 where k0 = 223
+Found 1 tuple:
+[223, 'tuple 223']
+select * from t0 where k0 = 224
+Found 1 tuple:
+[224, 'tuple 224']
+insert into t0 values (225, 'tuple 225')
+Insert OK, 1 row affected
+insert into t0 values (226, 'tuple 226')
+Insert OK, 1 row affected
+insert into t0 values (227, 'tuple 227')
+Insert OK, 1 row affected
+insert into t0 values (228, 'tuple 228')
+Insert OK, 1 row affected
+insert into t0 values (229, 'tuple 229')
+Insert OK, 1 row affected
+select * from t0 where k0 = 225
+Found 1 tuple:
+[225, 'tuple 225']
+select * from t0 where k0 = 226
+Found 1 tuple:
+[226, 'tuple 226']
+select * from t0 where k0 = 227
+Found 1 tuple:
+[227, 'tuple 227']
+select * from t0 where k0 = 228
+Found 1 tuple:
+[228, 'tuple 228']
+select * from t0 where k0 = 229
+Found 1 tuple:
+[229, 'tuple 229']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (230, 'tuple 230')
+Insert OK, 1 row affected
+insert into t0 values (231, 'tuple 231')
+Insert OK, 1 row affected
+insert into t0 values (232, 'tuple 232')
+Insert OK, 1 row affected
+insert into t0 values (233, 'tuple 233')
+Insert OK, 1 row affected
+insert into t0 values (234, 'tuple 234')
+Insert OK, 1 row affected
+select * from t0 where k0 = 230
+Found 1 tuple:
+[230, 'tuple 230']
+select * from t0 where k0 = 231
+Found 1 tuple:
+[231, 'tuple 231']
+select * from t0 where k0 = 232
+Found 1 tuple:
+[232, 'tuple 232']
+select * from t0 where k0 = 233
+Found 1 tuple:
+[233, 'tuple 233']
+select * from t0 where k0 = 234
+Found 1 tuple:
+[234, 'tuple 234']
+insert into t0 values (235, 'tuple 235')
+Insert OK, 1 row affected
+insert into t0 values (236, 'tuple 236')
+Insert OK, 1 row affected
+insert into t0 values (237, 'tuple 237')
+Insert OK, 1 row affected
+insert into t0 values (238, 'tuple 238')
+Insert OK, 1 row affected
+insert into t0 values (239, 'tuple 239')
+Insert OK, 1 row affected
+select * from t0 where k0 = 235
+Found 1 tuple:
+[235, 'tuple 235']
+select * from t0 where k0 = 236
+Found 1 tuple:
+[236, 'tuple 236']
+select * from t0 where k0 = 237
+Found 1 tuple:
+[237, 'tuple 237']
+select * from t0 where k0 = 238
+Found 1 tuple:
+[238, 'tuple 238']
+select * from t0 where k0 = 239
+Found 1 tuple:
+[239, 'tuple 239']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 12 iteration
+insert into t0 values (240, 'tuple 240')
+Insert OK, 1 row affected
+insert into t0 values (241, 'tuple 241')
+Insert OK, 1 row affected
+insert into t0 values (242, 'tuple 242')
+Insert OK, 1 row affected
+insert into t0 values (243, 'tuple 243')
+Insert OK, 1 row affected
+insert into t0 values (244, 'tuple 244')
+Insert OK, 1 row affected
+select * from t0 where k0 = 240
+Found 1 tuple:
+[240, 'tuple 240']
+select * from t0 where k0 = 241
+Found 1 tuple:
+[241, 'tuple 241']
+select * from t0 where k0 = 242
+Found 1 tuple:
+[242, 'tuple 242']
+select * from t0 where k0 = 243
+Found 1 tuple:
+[243, 'tuple 243']
+select * from t0 where k0 = 244
+Found 1 tuple:
+[244, 'tuple 244']
+insert into t0 values (245, 'tuple 245')
+Insert OK, 1 row affected
+insert into t0 values (246, 'tuple 246')
+Insert OK, 1 row affected
+insert into t0 values (247, 'tuple 247')
+Insert OK, 1 row affected
+insert into t0 values (248, 'tuple 248')
+Insert OK, 1 row affected
+insert into t0 values (249, 'tuple 249')
+Insert OK, 1 row affected
+select * from t0 where k0 = 245
+Found 1 tuple:
+[245, 'tuple 245']
+select * from t0 where k0 = 246
+Found 1 tuple:
+[246, 'tuple 246']
+select * from t0 where k0 = 247
+Found 1 tuple:
+[247, 'tuple 247']
+select * from t0 where k0 = 248
+Found 1 tuple:
+[248, 'tuple 248']
+select * from t0 where k0 = 249
+Found 1 tuple:
+[249, 'tuple 249']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (250, 'tuple 250')
+Insert OK, 1 row affected
+insert into t0 values (251, 'tuple 251')
+Insert OK, 1 row affected
+insert into t0 values (252, 'tuple 252')
+Insert OK, 1 row affected
+insert into t0 values (253, 'tuple 253')
+Insert OK, 1 row affected
+insert into t0 values (254, 'tuple 254')
+Insert OK, 1 row affected
+select * from t0 where k0 = 250
+Found 1 tuple:
+[250, 'tuple 250']
+select * from t0 where k0 = 251
+Found 1 tuple:
+[251, 'tuple 251']
+select * from t0 where k0 = 252
+Found 1 tuple:
+[252, 'tuple 252']
+select * from t0 where k0 = 253
+Found 1 tuple:
+[253, 'tuple 253']
+select * from t0 where k0 = 254
+Found 1 tuple:
+[254, 'tuple 254']
+insert into t0 values (255, 'tuple 255')
+Insert OK, 1 row affected
+insert into t0 values (256, 'tuple 256')
+Insert OK, 1 row affected
+insert into t0 values (257, 'tuple 257')
+Insert OK, 1 row affected
+insert into t0 values (258, 'tuple 258')
+Insert OK, 1 row affected
+insert into t0 values (259, 'tuple 259')
+Insert OK, 1 row affected
+select * from t0 where k0 = 255
+Found 1 tuple:
+[255, 'tuple 255']
+select * from t0 where k0 = 256
+Found 1 tuple:
+[256, 'tuple 256']
+select * from t0 where k0 = 257
+Found 1 tuple:
+[257, 'tuple 257']
+select * from t0 where k0 = 258
+Found 1 tuple:
+[258, 'tuple 258']
+select * from t0 where k0 = 259
+Found 1 tuple:
+[259, 'tuple 259']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 13 iteration
+insert into t0 values (260, 'tuple 260')
+Insert OK, 1 row affected
+insert into t0 values (261, 'tuple 261')
+Insert OK, 1 row affected
+insert into t0 values (262, 'tuple 262')
+Insert OK, 1 row affected
+insert into t0 values (263, 'tuple 263')
+Insert OK, 1 row affected
+insert into t0 values (264, 'tuple 264')
+Insert OK, 1 row affected
+select * from t0 where k0 = 260
+Found 1 tuple:
+[260, 'tuple 260']
+select * from t0 where k0 = 261
+Found 1 tuple:
+[261, 'tuple 261']
+select * from t0 where k0 = 262
+Found 1 tuple:
+[262, 'tuple 262']
+select * from t0 where k0 = 263
+Found 1 tuple:
+[263, 'tuple 263']
+select * from t0 where k0 = 264
+Found 1 tuple:
+[264, 'tuple 264']
+insert into t0 values (265, 'tuple 265')
+Insert OK, 1 row affected
+insert into t0 values (266, 'tuple 266')
+Insert OK, 1 row affected
+insert into t0 values (267, 'tuple 267')
+Insert OK, 1 row affected
+insert into t0 values (268, 'tuple 268')
+Insert OK, 1 row affected
+insert into t0 values (269, 'tuple 269')
+Insert OK, 1 row affected
+select * from t0 where k0 = 265
+Found 1 tuple:
+[265, 'tuple 265']
+select * from t0 where k0 = 266
+Found 1 tuple:
+[266, 'tuple 266']
+select * from t0 where k0 = 267
+Found 1 tuple:
+[267, 'tuple 267']
+select * from t0 where k0 = 268
+Found 1 tuple:
+[268, 'tuple 268']
+select * from t0 where k0 = 269
+Found 1 tuple:
+[269, 'tuple 269']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (270, 'tuple 270')
+Insert OK, 1 row affected
+insert into t0 values (271, 'tuple 271')
+Insert OK, 1 row affected
+insert into t0 values (272, 'tuple 272')
+Insert OK, 1 row affected
+insert into t0 values (273, 'tuple 273')
+Insert OK, 1 row affected
+insert into t0 values (274, 'tuple 274')
+Insert OK, 1 row affected
+select * from t0 where k0 = 270
+Found 1 tuple:
+[270, 'tuple 270']
+select * from t0 where k0 = 271
+Found 1 tuple:
+[271, 'tuple 271']
+select * from t0 where k0 = 272
+Found 1 tuple:
+[272, 'tuple 272']
+select * from t0 where k0 = 273
+Found 1 tuple:
+[273, 'tuple 273']
+select * from t0 where k0 = 274
+Found 1 tuple:
+[274, 'tuple 274']
+insert into t0 values (275, 'tuple 275')
+Insert OK, 1 row affected
+insert into t0 values (276, 'tuple 276')
+Insert OK, 1 row affected
+insert into t0 values (277, 'tuple 277')
+Insert OK, 1 row affected
+insert into t0 values (278, 'tuple 278')
+Insert OK, 1 row affected
+insert into t0 values (279, 'tuple 279')
+Insert OK, 1 row affected
+select * from t0 where k0 = 275
+Found 1 tuple:
+[275, 'tuple 275']
+select * from t0 where k0 = 276
+Found 1 tuple:
+[276, 'tuple 276']
+select * from t0 where k0 = 277
+Found 1 tuple:
+[277, 'tuple 277']
+select * from t0 where k0 = 278
+Found 1 tuple:
+[278, 'tuple 278']
+select * from t0 where k0 = 279
+Found 1 tuple:
+[279, 'tuple 279']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 14 iteration
+insert into t0 values (280, 'tuple 280')
+Insert OK, 1 row affected
+insert into t0 values (281, 'tuple 281')
+Insert OK, 1 row affected
+insert into t0 values (282, 'tuple 282')
+Insert OK, 1 row affected
+insert into t0 values (283, 'tuple 283')
+Insert OK, 1 row affected
+insert into t0 values (284, 'tuple 284')
+Insert OK, 1 row affected
+select * from t0 where k0 = 280
+Found 1 tuple:
+[280, 'tuple 280']
+select * from t0 where k0 = 281
+Found 1 tuple:
+[281, 'tuple 281']
+select * from t0 where k0 = 282
+Found 1 tuple:
+[282, 'tuple 282']
+select * from t0 where k0 = 283
+Found 1 tuple:
+[283, 'tuple 283']
+select * from t0 where k0 = 284
+Found 1 tuple:
+[284, 'tuple 284']
+insert into t0 values (285, 'tuple 285')
+Insert OK, 1 row affected
+insert into t0 values (286, 'tuple 286')
+Insert OK, 1 row affected
+insert into t0 values (287, 'tuple 287')
+Insert OK, 1 row affected
+insert into t0 values (288, 'tuple 288')
+Insert OK, 1 row affected
+insert into t0 values (289, 'tuple 289')
+Insert OK, 1 row affected
+select * from t0 where k0 = 285
+Found 1 tuple:
+[285, 'tuple 285']
+select * from t0 where k0 = 286
+Found 1 tuple:
+[286, 'tuple 286']
+select * from t0 where k0 = 287
+Found 1 tuple:
+[287, 'tuple 287']
+select * from t0 where k0 = 288
+Found 1 tuple:
+[288, 'tuple 288']
+select * from t0 where k0 = 289
+Found 1 tuple:
+[289, 'tuple 289']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (290, 'tuple 290')
+Insert OK, 1 row affected
+insert into t0 values (291, 'tuple 291')
+Insert OK, 1 row affected
+insert into t0 values (292, 'tuple 292')
+Insert OK, 1 row affected
+insert into t0 values (293, 'tuple 293')
+Insert OK, 1 row affected
+insert into t0 values (294, 'tuple 294')
+Insert OK, 1 row affected
+select * from t0 where k0 = 290
+Found 1 tuple:
+[290, 'tuple 290']
+select * from t0 where k0 = 291
+Found 1 tuple:
+[291, 'tuple 291']
+select * from t0 where k0 = 292
+Found 1 tuple:
+[292, 'tuple 292']
+select * from t0 where k0 = 293
+Found 1 tuple:
+[293, 'tuple 293']
+select * from t0 where k0 = 294
+Found 1 tuple:
+[294, 'tuple 294']
+insert into t0 values (295, 'tuple 295')
+Insert OK, 1 row affected
+insert into t0 values (296, 'tuple 296')
+Insert OK, 1 row affected
+insert into t0 values (297, 'tuple 297')
+Insert OK, 1 row affected
+insert into t0 values (298, 'tuple 298')
+Insert OK, 1 row affected
+insert into t0 values (299, 'tuple 299')
+Insert OK, 1 row affected
+select * from t0 where k0 = 295
+Found 1 tuple:
+[295, 'tuple 295']
+select * from t0 where k0 = 296
+Found 1 tuple:
+[296, 'tuple 296']
+select * from t0 where k0 = 297
+Found 1 tuple:
+[297, 'tuple 297']
+select * from t0 where k0 = 298
+Found 1 tuple:
+[298, 'tuple 298']
+select * from t0 where k0 = 299
+Found 1 tuple:
+[299, 'tuple 299']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 15 iteration
+insert into t0 values (300, 'tuple 300')
+Insert OK, 1 row affected
+insert into t0 values (301, 'tuple 301')
+Insert OK, 1 row affected
+insert into t0 values (302, 'tuple 302')
+Insert OK, 1 row affected
+insert into t0 values (303, 'tuple 303')
+Insert OK, 1 row affected
+insert into t0 values (304, 'tuple 304')
+Insert OK, 1 row affected
+select * from t0 where k0 = 300
+Found 1 tuple:
+[300, 'tuple 300']
+select * from t0 where k0 = 301
+Found 1 tuple:
+[301, 'tuple 301']
+select * from t0 where k0 = 302
+Found 1 tuple:
+[302, 'tuple 302']
+select * from t0 where k0 = 303
+Found 1 tuple:
+[303, 'tuple 303']
+select * from t0 where k0 = 304
+Found 1 tuple:
+[304, 'tuple 304']
+insert into t0 values (305, 'tuple 305')
+Insert OK, 1 row affected
+insert into t0 values (306, 'tuple 306')
+Insert OK, 1 row affected
+insert into t0 values (307, 'tuple 307')
+Insert OK, 1 row affected
+insert into t0 values (308, 'tuple 308')
+Insert OK, 1 row affected
+insert into t0 values (309, 'tuple 309')
+Insert OK, 1 row affected
+select * from t0 where k0 = 305
+Found 1 tuple:
+[305, 'tuple 305']
+select * from t0 where k0 = 306
+Found 1 tuple:
+[306, 'tuple 306']
+select * from t0 where k0 = 307
+Found 1 tuple:
+[307, 'tuple 307']
+select * from t0 where k0 = 308
+Found 1 tuple:
+[308, 'tuple 308']
+select * from t0 where k0 = 309
+Found 1 tuple:
+[309, 'tuple 309']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (310, 'tuple 310')
+Insert OK, 1 row affected
+insert into t0 values (311, 'tuple 311')
+Insert OK, 1 row affected
+insert into t0 values (312, 'tuple 312')
+Insert OK, 1 row affected
+insert into t0 values (313, 'tuple 313')
+Insert OK, 1 row affected
+insert into t0 values (314, 'tuple 314')
+Insert OK, 1 row affected
+select * from t0 where k0 = 310
+Found 1 tuple:
+[310, 'tuple 310']
+select * from t0 where k0 = 311
+Found 1 tuple:
+[311, 'tuple 311']
+select * from t0 where k0 = 312
+Found 1 tuple:
+[312, 'tuple 312']
+select * from t0 where k0 = 313
+Found 1 tuple:
+[313, 'tuple 313']
+select * from t0 where k0 = 314
+Found 1 tuple:
+[314, 'tuple 314']
+insert into t0 values (315, 'tuple 315')
+Insert OK, 1 row affected
+insert into t0 values (316, 'tuple 316')
+Insert OK, 1 row affected
+insert into t0 values (317, 'tuple 317')
+Insert OK, 1 row affected
+insert into t0 values (318, 'tuple 318')
+Insert OK, 1 row affected
+insert into t0 values (319, 'tuple 319')
+Insert OK, 1 row affected
+select * from t0 where k0 = 315
+Found 1 tuple:
+[315, 'tuple 315']
+select * from t0 where k0 = 316
+Found 1 tuple:
+[316, 'tuple 316']
+select * from t0 where k0 = 317
+Found 1 tuple:
+[317, 'tuple 317']
+select * from t0 where k0 = 318
+Found 1 tuple:
+[318, 'tuple 318']
+select * from t0 where k0 = 319
+Found 1 tuple:
+[319, 'tuple 319']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 16 iteration
+insert into t0 values (320, 'tuple 320')
+Insert OK, 1 row affected
+insert into t0 values (321, 'tuple 321')
+Insert OK, 1 row affected
+insert into t0 values (322, 'tuple 322')
+Insert OK, 1 row affected
+insert into t0 values (323, 'tuple 323')
+Insert OK, 1 row affected
+insert into t0 values (324, 'tuple 324')
+Insert OK, 1 row affected
+select * from t0 where k0 = 320
+Found 1 tuple:
+[320, 'tuple 320']
+select * from t0 where k0 = 321
+Found 1 tuple:
+[321, 'tuple 321']
+select * from t0 where k0 = 322
+Found 1 tuple:
+[322, 'tuple 322']
+select * from t0 where k0 = 323
+Found 1 tuple:
+[323, 'tuple 323']
+select * from t0 where k0 = 324
+Found 1 tuple:
+[324, 'tuple 324']
+insert into t0 values (325, 'tuple 325')
+Insert OK, 1 row affected
+insert into t0 values (326, 'tuple 326')
+Insert OK, 1 row affected
+insert into t0 values (327, 'tuple 327')
+Insert OK, 1 row affected
+insert into t0 values (328, 'tuple 328')
+Insert OK, 1 row affected
+insert into t0 values (329, 'tuple 329')
+Insert OK, 1 row affected
+select * from t0 where k0 = 325
+Found 1 tuple:
+[325, 'tuple 325']
+select * from t0 where k0 = 326
+Found 1 tuple:
+[326, 'tuple 326']
+select * from t0 where k0 = 327
+Found 1 tuple:
+[327, 'tuple 327']
+select * from t0 where k0 = 328
+Found 1 tuple:
+[328, 'tuple 328']
+select * from t0 where k0 = 329
+Found 1 tuple:
+[329, 'tuple 329']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (330, 'tuple 330')
+Insert OK, 1 row affected
+insert into t0 values (331, 'tuple 331')
+Insert OK, 1 row affected
+insert into t0 values (332, 'tuple 332')
+Insert OK, 1 row affected
+insert into t0 values (333, 'tuple 333')
+Insert OK, 1 row affected
+insert into t0 values (334, 'tuple 334')
+Insert OK, 1 row affected
+select * from t0 where k0 = 330
+Found 1 tuple:
+[330, 'tuple 330']
+select * from t0 where k0 = 331
+Found 1 tuple:
+[331, 'tuple 331']
+select * from t0 where k0 = 332
+Found 1 tuple:
+[332, 'tuple 332']
+select * from t0 where k0 = 333
+Found 1 tuple:
+[333, 'tuple 333']
+select * from t0 where k0 = 334
+Found 1 tuple:
+[334, 'tuple 334']
+insert into t0 values (335, 'tuple 335')
+Insert OK, 1 row affected
+insert into t0 values (336, 'tuple 336')
+Insert OK, 1 row affected
+insert into t0 values (337, 'tuple 337')
+Insert OK, 1 row affected
+insert into t0 values (338, 'tuple 338')
+Insert OK, 1 row affected
+insert into t0 values (339, 'tuple 339')
+Insert OK, 1 row affected
+select * from t0 where k0 = 335
+Found 1 tuple:
+[335, 'tuple 335']
+select * from t0 where k0 = 336
+Found 1 tuple:
+[336, 'tuple 336']
+select * from t0 where k0 = 337
+Found 1 tuple:
+[337, 'tuple 337']
+select * from t0 where k0 = 338
+Found 1 tuple:
+[338, 'tuple 338']
+select * from t0 where k0 = 339
+Found 1 tuple:
+[339, 'tuple 339']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 17 iteration
+insert into t0 values (340, 'tuple 340')
+Insert OK, 1 row affected
+insert into t0 values (341, 'tuple 341')
+Insert OK, 1 row affected
+insert into t0 values (342, 'tuple 342')
+Insert OK, 1 row affected
+insert into t0 values (343, 'tuple 343')
+Insert OK, 1 row affected
+insert into t0 values (344, 'tuple 344')
+Insert OK, 1 row affected
+select * from t0 where k0 = 340
+Found 1 tuple:
+[340, 'tuple 340']
+select * from t0 where k0 = 341
+Found 1 tuple:
+[341, 'tuple 341']
+select * from t0 where k0 = 342
+Found 1 tuple:
+[342, 'tuple 342']
+select * from t0 where k0 = 343
+Found 1 tuple:
+[343, 'tuple 343']
+select * from t0 where k0 = 344
+Found 1 tuple:
+[344, 'tuple 344']
+insert into t0 values (345, 'tuple 345')
+Insert OK, 1 row affected
+insert into t0 values (346, 'tuple 346')
+Insert OK, 1 row affected
+insert into t0 values (347, 'tuple 347')
+Insert OK, 1 row affected
+insert into t0 values (348, 'tuple 348')
+Insert OK, 1 row affected
+insert into t0 values (349, 'tuple 349')
+Insert OK, 1 row affected
+select * from t0 where k0 = 345
+Found 1 tuple:
+[345, 'tuple 345']
+select * from t0 where k0 = 346
+Found 1 tuple:
+[346, 'tuple 346']
+select * from t0 where k0 = 347
+Found 1 tuple:
+[347, 'tuple 347']
+select * from t0 where k0 = 348
+Found 1 tuple:
+[348, 'tuple 348']
+select * from t0 where k0 = 349
+Found 1 tuple:
+[349, 'tuple 349']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (350, 'tuple 350')
+Insert OK, 1 row affected
+insert into t0 values (351, 'tuple 351')
+Insert OK, 1 row affected
+insert into t0 values (352, 'tuple 352')
+Insert OK, 1 row affected
+insert into t0 values (353, 'tuple 353')
+Insert OK, 1 row affected
+insert into t0 values (354, 'tuple 354')
+Insert OK, 1 row affected
+select * from t0 where k0 = 350
+Found 1 tuple:
+[350, 'tuple 350']
+select * from t0 where k0 = 351
+Found 1 tuple:
+[351, 'tuple 351']
+select * from t0 where k0 = 352
+Found 1 tuple:
+[352, 'tuple 352']
+select * from t0 where k0 = 353
+Found 1 tuple:
+[353, 'tuple 353']
+select * from t0 where k0 = 354
+Found 1 tuple:
+[354, 'tuple 354']
+insert into t0 values (355, 'tuple 355')
+Insert OK, 1 row affected
+insert into t0 values (356, 'tuple 356')
+Insert OK, 1 row affected
+insert into t0 values (357, 'tuple 357')
+Insert OK, 1 row affected
+insert into t0 values (358, 'tuple 358')
+Insert OK, 1 row affected
+insert into t0 values (359, 'tuple 359')
+Insert OK, 1 row affected
+select * from t0 where k0 = 355
+Found 1 tuple:
+[355, 'tuple 355']
+select * from t0 where k0 = 356
+Found 1 tuple:
+[356, 'tuple 356']
+select * from t0 where k0 = 357
+Found 1 tuple:
+[357, 'tuple 357']
+select * from t0 where k0 = 358
+Found 1 tuple:
+[358, 'tuple 358']
+select * from t0 where k0 = 359
+Found 1 tuple:
+[359, 'tuple 359']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 18 iteration
+insert into t0 values (360, 'tuple 360')
+Insert OK, 1 row affected
+insert into t0 values (361, 'tuple 361')
+Insert OK, 1 row affected
+insert into t0 values (362, 'tuple 362')
+Insert OK, 1 row affected
+insert into t0 values (363, 'tuple 363')
+Insert OK, 1 row affected
+insert into t0 values (364, 'tuple 364')
+Insert OK, 1 row affected
+select * from t0 where k0 = 360
+Found 1 tuple:
+[360, 'tuple 360']
+select * from t0 where k0 = 361
+Found 1 tuple:
+[361, 'tuple 361']
+select * from t0 where k0 = 362
+Found 1 tuple:
+[362, 'tuple 362']
+select * from t0 where k0 = 363
+Found 1 tuple:
+[363, 'tuple 363']
+select * from t0 where k0 = 364
+Found 1 tuple:
+[364, 'tuple 364']
+insert into t0 values (365, 'tuple 365')
+Insert OK, 1 row affected
+insert into t0 values (366, 'tuple 366')
+Insert OK, 1 row affected
+insert into t0 values (367, 'tuple 367')
+Insert OK, 1 row affected
+insert into t0 values (368, 'tuple 368')
+Insert OK, 1 row affected
+insert into t0 values (369, 'tuple 369')
+Insert OK, 1 row affected
+select * from t0 where k0 = 365
+Found 1 tuple:
+[365, 'tuple 365']
+select * from t0 where k0 = 366
+Found 1 tuple:
+[366, 'tuple 366']
+select * from t0 where k0 = 367
+Found 1 tuple:
+[367, 'tuple 367']
+select * from t0 where k0 = 368
+Found 1 tuple:
+[368, 'tuple 368']
+select * from t0 where k0 = 369
+Found 1 tuple:
+[369, 'tuple 369']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (370, 'tuple 370')
+Insert OK, 1 row affected
+insert into t0 values (371, 'tuple 371')
+Insert OK, 1 row affected
+insert into t0 values (372, 'tuple 372')
+Insert OK, 1 row affected
+insert into t0 values (373, 'tuple 373')
+Insert OK, 1 row affected
+insert into t0 values (374, 'tuple 374')
+Insert OK, 1 row affected
+select * from t0 where k0 = 370
+Found 1 tuple:
+[370, 'tuple 370']
+select * from t0 where k0 = 371
+Found 1 tuple:
+[371, 'tuple 371']
+select * from t0 where k0 = 372
+Found 1 tuple:
+[372, 'tuple 372']
+select * from t0 where k0 = 373
+Found 1 tuple:
+[373, 'tuple 373']
+select * from t0 where k0 = 374
+Found 1 tuple:
+[374, 'tuple 374']
+insert into t0 values (375, 'tuple 375')
+Insert OK, 1 row affected
+insert into t0 values (376, 'tuple 376')
+Insert OK, 1 row affected
+insert into t0 values (377, 'tuple 377')
+Insert OK, 1 row affected
+insert into t0 values (378, 'tuple 378')
+Insert OK, 1 row affected
+insert into t0 values (379, 'tuple 379')
+Insert OK, 1 row affected
+select * from t0 where k0 = 375
+Found 1 tuple:
+[375, 'tuple 375']
+select * from t0 where k0 = 376
+Found 1 tuple:
+[376, 'tuple 376']
+select * from t0 where k0 = 377
+Found 1 tuple:
+[377, 'tuple 377']
+select * from t0 where k0 = 378
+Found 1 tuple:
+[378, 'tuple 378']
+select * from t0 where k0 = 379
+Found 1 tuple:
+[379, 'tuple 379']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+test 19 iteration
+insert into t0 values (380, 'tuple 380')
+Insert OK, 1 row affected
+insert into t0 values (381, 'tuple 381')
+Insert OK, 1 row affected
+insert into t0 values (382, 'tuple 382')
+Insert OK, 1 row affected
+insert into t0 values (383, 'tuple 383')
+Insert OK, 1 row affected
+insert into t0 values (384, 'tuple 384')
+Insert OK, 1 row affected
+select * from t0 where k0 = 380
+Found 1 tuple:
+[380, 'tuple 380']
+select * from t0 where k0 = 381
+Found 1 tuple:
+[381, 'tuple 381']
+select * from t0 where k0 = 382
+Found 1 tuple:
+[382, 'tuple 382']
+select * from t0 where k0 = 383
+Found 1 tuple:
+[383, 'tuple 383']
+select * from t0 where k0 = 384
+Found 1 tuple:
+[384, 'tuple 384']
+insert into t0 values (385, 'tuple 385')
+Insert OK, 1 row affected
+insert into t0 values (386, 'tuple 386')
+Insert OK, 1 row affected
+insert into t0 values (387, 'tuple 387')
+Insert OK, 1 row affected
+insert into t0 values (388, 'tuple 388')
+Insert OK, 1 row affected
+insert into t0 values (389, 'tuple 389')
+Insert OK, 1 row affected
+select * from t0 where k0 = 385
+Found 1 tuple:
+[385, 'tuple 385']
+select * from t0 where k0 = 386
+Found 1 tuple:
+[386, 'tuple 386']
+select * from t0 where k0 = 387
+Found 1 tuple:
+[387, 'tuple 387']
+select * from t0 where k0 = 388
+Found 1 tuple:
+[388, 'tuple 388']
+select * from t0 where k0 = 389
+Found 1 tuple:
+[389, 'tuple 389']
+swap servers
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
+insert into t0 values (390, 'tuple 390')
+Insert OK, 1 row affected
+insert into t0 values (391, 'tuple 391')
+Insert OK, 1 row affected
+insert into t0 values (392, 'tuple 392')
+Insert OK, 1 row affected
+insert into t0 values (393, 'tuple 393')
+Insert OK, 1 row affected
+insert into t0 values (394, 'tuple 394')
+Insert OK, 1 row affected
+select * from t0 where k0 = 390
+Found 1 tuple:
+[390, 'tuple 390']
+select * from t0 where k0 = 391
+Found 1 tuple:
+[391, 'tuple 391']
+select * from t0 where k0 = 392
+Found 1 tuple:
+[392, 'tuple 392']
+select * from t0 where k0 = 393
+Found 1 tuple:
+[393, 'tuple 393']
+select * from t0 where k0 = 394
+Found 1 tuple:
+[394, 'tuple 394']
+insert into t0 values (395, 'tuple 395')
+Insert OK, 1 row affected
+insert into t0 values (396, 'tuple 396')
+Insert OK, 1 row affected
+insert into t0 values (397, 'tuple 397')
+Insert OK, 1 row affected
+insert into t0 values (398, 'tuple 398')
+Insert OK, 1 row affected
+insert into t0 values (399, 'tuple 399')
+Insert OK, 1 row affected
+select * from t0 where k0 = 395
+Found 1 tuple:
+[395, 'tuple 395']
+select * from t0 where k0 = 396
+Found 1 tuple:
+[396, 'tuple 396']
+select * from t0 where k0 = 397
+Found 1 tuple:
+[397, 'tuple 397']
+select * from t0 where k0 = 398
+Found 1 tuple:
+[398, 'tuple 398']
+select * from t0 where k0 = 399
+Found 1 tuple:
+[399, 'tuple 399']
+rollback servers configuration
+reload configuration
+---
+ok
+...
+reload configuration
+---
+ok
+...
diff --git a/test/box_replication/swap.test b/test/box_replication/swap.test
new file mode 100644
index 0000000000000000000000000000000000000000..54a4187942c4169fa9a780224fbbf6bbb4429f0f
--- /dev/null
+++ b/test/box_replication/swap.test
@@ -0,0 +1,76 @@
+# encoding: tarantool
+import os
+import time
+from lib.tarantool_box_server import TarantoolBoxServer
+
+REPEAT = 20
+ID_BEGIN = 0
+ID_STEP = 5
+
+def insert_tuples(server, begin, end, msg = "tuple"):
+    for i in range(begin, end):
+        server.sql.execute("insert into t0 values (%d, '%s %d')" % (i, msg, i), silent=False)
+
+def select_tuples(server, begin, end):
+    # the last lsn is end id + 1
+    server.wait_lsn(end + 1)
+    for i in range(begin, end):
+        server.sql.execute("select * from t0 where k0 = %d" % i, silent=False)
+
+# master server
+master = server
+
+# replica server
+replica = TarantoolBoxServer()
+replica.deploy("box_replication/cfg/replica.cfg",
+               replica.find_exe(self.args.builddir),
+               os.path.join(self.args.vardir, "replica"))
+
+id = ID_BEGIN
+for i in range(REPEAT):
+    print "test %d iteration" % i
+
+    # insert to master
+    insert_tuples(master, id, id + ID_STEP)
+    # select from replica
+    select_tuples(replica, id, id + ID_STEP)
+    id += ID_STEP
+
+    # insert to master
+    insert_tuples(master, id, id + ID_STEP)
+    # select from replica
+    select_tuples(replica, id, id + ID_STEP)
+    id += ID_STEP
+
+    print "swap servers"
+    # reconfigure replica to master
+    replica.reconfigure("box_replication/cfg/replica_to_master.cfg", silent = False)
+    # reconfigure master to replica
+    master.reconfigure("box_replication/cfg/master_to_replica.cfg", silent = False)
+
+    # insert to replica
+    insert_tuples(replica, id, id + ID_STEP)
+    # select from master
+    select_tuples(master, id, id + ID_STEP)
+    id += ID_STEP
+
+    # insert to replica
+    insert_tuples(replica, id, id + ID_STEP)
+    # select from master
+    select_tuples(master, id, id + ID_STEP)
+    id += ID_STEP
+
+    print "rollback servers configuration"
+    # reconfigure replica to master
+    master.reconfigure("box_replication/cfg/master.cfg", silent = False)
+    # reconfigure master to replica
+    replica.reconfigure("box_replication/cfg/replica.cfg", silent = False)
+
+
+# Cleanup.
+replica.stop()
+replica.cleanup(True)
+server.stop()
+server.deploy(self.suite_ini["config"])
+
+# vim: syntax=python
diff --git a/test/box_replication/tarantool_beholder.cfg b/test/box_replication/tarantool_beholder.cfg
deleted file mode 100644
index 6e74dbd891b52c979fc2ca76e87062f21cc9ab24..0000000000000000000000000000000000000000
--- a/test/box_replication/tarantool_beholder.cfg
+++ /dev/null
@@ -1,13 +0,0 @@
-slab_alloc_arena=0.05
-pid_file = "tarantool.pid"
-
-primary_port = 33013
-secondary_port = 33024
-admin_port = 33025
-
-logger="tee -a tarantool.log"
-namespace[0].enabled = 1
-namespace[0].index[0].type = "HASH"
-namespace[0].index[0].unique = 1
-namespace[0].index[0].key_field[0].fieldno = 0
-namespace[0].index[0].key_field[0].type = "NUM"
diff --git a/test/box_replication/tarantool_slave_secondary_feeder_replication.cfg b/test/box_replication/tarantool_slave_secondary_feeder_replication.cfg
deleted file mode 100644
index cd918ba1226da0b3e0b4114e91f2bc10ebf035dd..0000000000000000000000000000000000000000
--- a/test/box_replication/tarantool_slave_secondary_feeder_replication.cfg
+++ /dev/null
@@ -1,17 +0,0 @@
-slab_alloc_arena=0.05
-pid_file = "tarantool.pid"
-
-primary_port = 33113
-secondary_port = 33114
-admin_port = 33115
-
-logger="tee -a tarantool.log"
-namespace[0].enabled = 1
-namespace[0].index[0].type = "HASH"
-namespace[0].index[0].unique = 1
-namespace[0].index[0].key_field[0].fieldno = 0
-namespace[0].index[0].key_field[0].type = "NUM"
-
-remote_hot_standby = 1
-wal_feeder_ipaddr = "127.0.0.1"
-wal_feeder_port = 33026
diff --git a/test/lib/server.py b/test/lib/server.py
index 2c8d47d733e0421a7b2168256f133a57fa7425d5..ab3ff8f7a7b661b066e5fae29fb02e141c573490 100644
--- a/test/lib/server.py
+++ b/test/lib/server.py
@@ -229,7 +229,7 @@ class Server(object):
         self.pid = None
 
     def deploy(self, config=None, binary=None, vardir=None,
-               mem=None, start_and_exit=None, gdb=None, valgrind=None, silent=True):
+               mem=None, start_and_exit=None, gdb=None, valgrind=None, silent=True, need_init=True):
         if config != None: self.config = config
         if binary != None: self.binary = binary
         if vardir != None: self.vardir = vardir
@@ -240,7 +240,8 @@ class Server(object):
 
         self.configure(self.config)
         self.install(self.binary, self.vardir, self.mem, silent)
-        self.init()
+        if need_init:
+            self.init()
         self.start(self.start_and_exit, self.gdb, self.valgrind, silent)
 
     def restart(self):
diff --git a/test/lib/tarantool_box_server.py b/test/lib/tarantool_box_server.py
index c170d1f18f4252c01ab8ddcfaae01bd66769802c..849b235dc1d39053ae6605f6d5232180d556fb12 100644
--- a/test/lib/tarantool_box_server.py
+++ b/test/lib/tarantool_box_server.py
@@ -1,19 +1,14 @@
+import time
 import shutil
 import subprocess
 import yaml
 import ConfigParser
 from tarantool_server import TarantoolServer, TarantoolConfigFile
-from admin_connection import AdminConnection 
+from admin_connection import AdminConnection
 from box_connection import BoxConnection
 from memcached_connection import MemcachedConnection
 import time
 
-#try:
-#    import memcache
-#    has_memcached = True
-#except ImportError:
-#    has_memcached = False
-
 class TarantoolBoxServer(TarantoolServer):
     def __new__(cls, core="tarantool", module="box"):
         return TarantoolServer.__new__(cls)
@@ -53,10 +48,15 @@ class TarantoolBoxServer(TarantoolServer):
                               stdout = subprocess.PIPE,
                               stderr = subprocess.PIPE)
 
+    def get_param(self, param):
+        data = self.admin.execute("show info\n", silent = True)
+        info = yaml.load(data)["info"]
+        return info[param]
+
     def wait_lsn(self, lsn):
         while True:
-            data = self.admin.execute("show info\n", silent=True)
-            info = yaml.load(data)["info"]
-            if (int(info["lsn"]) >= lsn):
+            curr_lsn = int(self.get_param("lsn"))
+            if (curr_lsn >= lsn):
                 break
             time.sleep(0.01)
+
diff --git a/test/lib/tarantool_feeder_server.py b/test/lib/tarantool_feeder_server.py
deleted file mode 100644
index 2a4b7979c568b650ac54c36c4698c61bb0bdf791..0000000000000000000000000000000000000000
--- a/test/lib/tarantool_feeder_server.py
+++ /dev/null
@@ -1,18 +0,0 @@
-import ConfigParser
-from tarantool_server import TarantoolServer, TarantoolConfigFile
-
-class TarantoolFeederServer(TarantoolServer):
-    def __new__(cls, core="tarantool", module="feeder"):
-        return TarantoolServer.__new__(cls)
-
-    def __init__(self, core="tarantool", module="feeder"):
-        TarantoolServer.__init__(self, core, module)
-
-    def configure(self, config):
-        TarantoolServer.configure(self, config)
-        with open(self.config) as fp:
-            dummy_section_name = "tarantool"
-            config = ConfigParser.ConfigParser()
-            config.readfp(TarantoolConfigFile(fp, dummy_section_name))
-            self.port = int(config.get(dummy_section_name, "wal_feeder_bind_port"))
-