diff --git a/src/doveadm/doveadm-mail-server.c b/src/doveadm/doveadm-mail-server.c
index 5d393882e..f016b095d 100644
--- a/src/doveadm/doveadm-mail-server.c
+++ b/src/doveadm/doveadm-mail-server.c
@@ -16,6 +16,49 @@
 #include "doveadm-server.h"
 #include "doveadm-mail.h"
 
+// Linked list to store ioloop
+struct Node {
+	struct ioloop* ioloop;
+	struct Node* next;
+};
+
+// Helper function to insert new Node in the beginning of the linked list
+void push(struct Node** head, struct ioloop* ioloop) {
+	// Allocate the new Node in the heap and set its data
+	struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
+	newNode->ioloop = ioloop;
+
+	// Set the .next pointer of the new Node to point to the current first node of the list.
+	newNode->next = *head;
+
+	// Change the head pointer to point to the new Node, so it is now the first node in the list.
+	*head = newNode;
+}
+
+// The opposite of Push(). Takes a non-empty list and removes the front
+// node, and returns the data which was in that node.
+struct ioloop* pop(struct Node** headRef) {
+	// Underflow condition
+	if (*headRef == NULL) {
+		return NULL;
+	}
+
+	struct Node* head = *headRef;
+	// Pull out data before node is deleted
+	struct ioloop* result = head->ioloop;
+
+	// Unlink the head node for the caller
+	(*headRef) = (*headRef)->next;
+
+	// Free the head node
+	free(head);
+
+	// Don't forget to return the data from link
+	return result;
+}
+
+struct Node* server_ioloop_head = NULL;
+
 #define DOVEADM_SERVER_CONNECTIONS_MAX 4
 #define DOVEADM_SERVER_QUEUE_MAX 16
 
@@ -58,6 +101,12 @@ doveadm_server_get(struct doveadm_mail_cmd_context *ctx, const char *name)
 			     ctx->set->doveadm_worker_count);
 		p_array_init(&server->queue, server_pool,
 			     DOVEADM_SERVER_QUEUE_MAX);
+
+		server->ioloop = io_loop_create();
+		if (server->ioloop) {
+			push(&server_ioloop_head, server->ioloop);
+		}
+
 		hash_table_insert(servers, dup_name, server);
 	}
 	return server;
@@ -104,7 +153,11 @@ static void doveadm_cmd_callback(int exit_code, const char *error,
 		i_error("%s: Command %s failed for %s: %s",
 			server->name, cmd_ctx->cmd->name, username, error);
 		internal_failure = TRUE;
-		io_loop_stop(current_ioloop);
+		if (server->ioloop) {
+			io_loop_stop(server->ioloop);
+		} else {
+			io_loop_stop(current_ioloop);
+		}
 		return;
 	case EX_NOUSER:
 		i_error("%s: No such user: %s", server->name, username);
@@ -130,7 +183,11 @@ static void doveadm_cmd_callback(int exit_code, const char *error,
 		}
 	}
 
-	io_loop_stop(current_ioloop);
+	if (server->ioloop) {
+		io_loop_stop(server->ioloop);
+	} else {
+		io_loop_stop(current_ioloop);
+	}
 }
 
 static void doveadm_mail_server_handle(struct server_connection *conn,
@@ -167,9 +224,17 @@ static void doveadm_mail_server_handle(struct server_connection *conn,
 static void doveadm_server_flush_one(struct doveadm_server *server)
 {
 	unsigned int count = array_count(&server->queue);
+	struct ioloop* prev_ioloop;
 
 	do {
-		io_loop_run(current_ioloop);
+		if (server->ioloop) {
+			prev_ioloop = current_ioloop;
+			io_loop_set_current(server->ioloop);
+			io_loop_run(server->ioloop);
+			io_loop_set_current(prev_ioloop);
+		} else {
+			io_loop_run(current_ioloop);
+		}
 	} while (array_count(&server->queue) == count &&
 		 doveadm_server_have_used_connections(server) &&
 		 !DOVEADM_MAIL_SERVER_FAILED());
@@ -377,6 +442,20 @@ static void doveadm_servers_destroy_all_connections(void)
 	hash_table_iterate_deinit(&iter);
 }
 
+static void doveadm_servers_destroy_all_ioloop(void)
+{
+	struct ioloop* prev_ioloop;
+	struct ioloop* ioloop;
+
+	while (server_ioloop_head) {
+		ioloop = pop(&server_ioloop_head);
+		if (ioloop) {
+			io_loop_set_current(ioloop);
+			io_loop_destroy(&ioloop);
+		}
+	}
+}
+
 void doveadm_mail_server_flush(void)
 {
 	struct doveadm_server *server;
@@ -391,6 +470,7 @@ void doveadm_mail_server_flush(void)
 		doveadm_server_flush_one(server);
 
 	doveadm_servers_destroy_all_connections();
+	doveadm_servers_destroy_all_ioloop();
 	if (master_service_is_killed(master_service))
 		i_error("Aborted");
 	if (DOVEADM_MAIL_SERVER_FAILED())
diff --git a/src/doveadm/doveadm-server.h b/src/doveadm/doveadm-server.h
index e111b4a85..60aed9269 100644
--- a/src/doveadm/doveadm-server.h
+++ b/src/doveadm/doveadm-server.h
@@ -29,6 +29,8 @@ struct doveadm_server {
 
 	ARRAY(struct server_connection *) connections;
 	ARRAY_TYPE(string) queue;
+
+	struct ioloop *ioloop;
 };
 
 #endif
