diff --git a/NEWS b/NEWS
index de5801ca8334ddff8e49a3c1ec88e0030fcddee8..e726aaa76a5d4f1e69176d7e719e90ad41cf3739 100644
--- a/NEWS
+++ b/NEWS
@@ -18,7 +18,7 @@ Bugfixes
 --------
 - http module: only run prometheus in parent process if using --forks=N,
   as the submodule collects metrics from all sub-processes as well.
-- TLS fixes for corner cases (!714, !700)
+- TLS fixes for corner cases (!700, !714, !721)
 - fix build with -DNOVERBOSELOG (#424)
 - policy.{FORWARD,TLS_FORWARD,STUB}: respect net.ipv{4,6} setting (!710)
 
diff --git a/daemon/io.c b/daemon/io.c
index 90d2dbb2640c791381632cc59a98539c5e0108a8..f7086ca533e1aa85ffc5fecf8fc8b5de2b60a24f 100644
--- a/daemon/io.c
+++ b/daemon/io.c
@@ -181,6 +181,10 @@ void tcp_timeout_trigger(uv_timer_t *timer)
 			char *peer_str = kr_straddr(peer);
 			kr_log_verbose("[io] => closing connection to '%s'\n",
 				       peer_str ? peer_str : "");
+			if (session_flags(s)->outgoing) {
+				worker_del_tcp_waiting(worker, peer);
+				worker_del_tcp_connected(worker, peer);
+			}
 			session_close(s);
 		}
 	}
diff --git a/daemon/session.c b/daemon/session.c
index 209dbb6d7c7afea8d0350e3f7cb543f970000c3f..db238233db8ecf82c37f0732ed93cd946697e0f9 100644
--- a/daemon/session.c
+++ b/daemon/session.c
@@ -102,12 +102,6 @@ void session_close(struct session *session)
 	uv_handle_t *handle = session->handle;
 	io_stop_read(handle);
 	session->sflags.closing = true;
-	if (session->peer.ip.sa_family != AF_UNSPEC && handle->type == UV_TCP) {
-		struct worker_ctx *worker = handle->loop->data;
-		struct sockaddr *peer = &session->peer.ip;
-		worker_del_tcp_connected(worker, peer);
-		session->sflags.connected = false;
-	}
 
 	if (!uv_is_closing((uv_handle_t *)&session->timeout)) {
 		uv_timer_stop(&session->timeout);
diff --git a/daemon/worker.c b/daemon/worker.c
index f02dd1e47ba80f5ff69421cfab2474210eb90018..98be1e6a1236904c0c37deff6fadab73dab230bc 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -117,8 +117,6 @@ static struct session* worker_find_tcp_connected(struct worker_ctx *worker,
 static int worker_add_tcp_waiting(struct worker_ctx *worker,
 				  const struct sockaddr *addr,
 				  struct session *session);
-static int worker_del_tcp_waiting(struct worker_ctx *worker,
-				  const struct sockaddr *addr);
 static struct session* worker_find_tcp_waiting(struct worker_ctx *worker,
 					       const struct sockaddr *addr);
 static void on_tcp_connect_timeout(uv_timer_t *timer);
@@ -752,8 +750,7 @@ static int session_tls_hs_cb(struct session *session, int status)
 
 	if (ret != kr_ok()) {
 		/* Something went wrong.
-		 * Session isn't in the list of waiting sessions,
-		 * or addition to the list of connected sessions failed,
+		 * Either addition to the list of connected sessions
 		 * or write to upstream failed. */
 		worker_del_tcp_connected(worker, peer);
 		session_waitinglist_finalize(session, KR_STATE_FAIL);
@@ -774,8 +771,11 @@ static int send_waiting(struct session *session)
 		struct qr_task *t = session_waitinglist_get(session);
 		ret = qr_task_send(t, session, NULL, NULL);
 		if (ret != 0) {
+			struct worker_ctx *worker = t->ctx->worker;
+			struct sockaddr *peer = session_get_peer(session);
 			session_waitinglist_finalize(session, KR_STATE_FAIL);
 			session_tasklist_finalize(session, KR_STATE_FAIL);
+			worker_del_tcp_connected(worker, peer);
 			session_close(session);
 			break;
 		}
@@ -865,7 +865,6 @@ static void on_connect(uv_connect_t *req, int status)
 
 	ret = send_waiting(session);
 	if (ret != 0) {
-		worker_del_tcp_connected(worker, peer);
 		return;
 	}
 
@@ -1209,6 +1208,7 @@ static int tcp_task_existing_connection(struct session *session, struct qr_task
 		/* Error, finalize task with SERVFAIL and
 		 * close connection to upstream. */
 		session_tasklist_finalize(session, KR_STATE_FAIL);
+		worker_del_tcp_connected(worker, session_get_peer(session));
 		session_close(session);
 		return kr_error(EINVAL);
 	}
@@ -1620,8 +1620,8 @@ static int worker_add_tcp_waiting(struct worker_ctx *worker,
 	return map_add_tcp_session(&worker->tcp_waiting, addr, session);
 }
 
-static int worker_del_tcp_waiting(struct worker_ctx *worker,
-				  const struct sockaddr* addr)
+int worker_del_tcp_waiting(struct worker_ctx *worker,
+			   const struct sockaddr* addr)
 {
 	assert(addr && tcpsess_key(addr));
 	return map_del_tcp_session(&worker->tcp_waiting, addr);
@@ -1645,6 +1645,7 @@ int worker_end_tcp(struct session *session)
 	struct worker_ctx *worker = handle->loop->data;
 	struct sockaddr *peer = session_get_peer(session);
 
+	worker_del_tcp_waiting(worker, peer);
 	worker_del_tcp_connected(worker, peer);
 	session_flags(session)->connected = false;
 
diff --git a/daemon/worker.h b/daemon/worker.h
index 3d9ade8bc48d40af8413f24a940aefb8c3d4ba86..f56e10d0651e176c09e118ace8272d839c32ef45 100644
--- a/daemon/worker.h
+++ b/daemon/worker.h
@@ -91,7 +91,8 @@ int worker_add_tcp_connected(struct worker_ctx *worker,
 			     struct session *session);
 int worker_del_tcp_connected(struct worker_ctx *worker,
 			     const struct sockaddr *addr);
-
+int worker_del_tcp_waiting(struct worker_ctx *worker,
+			   const struct sockaddr* addr);
 knot_pkt_t *worker_task_get_pktbuf(const struct qr_task *task);
 
 struct request_ctx *worker_task_get_request(struct qr_task *task);