diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index 6662443f30453315c0d04b9cb868a563475ba0d1..f246acc011d1d8ea43fbb3c7ae78d6b7ef378eda 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -70,6 +70,55 @@ static void xfr_request_deinit(knot_ns_xfr_t *r)
 	}
 }
 
+/*!
+ * \brief Clean pending transfer data.
+ */
+static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
+{
+	int ret = KNOTD_EOK;
+	knot_changesets_t *chs = 0;
+
+	dbg_xfr_verb("Cleaning up after XFR-in.\n");
+	
+	switch(data->type) {
+	case XFR_TYPE_AIN:
+		if (data->flags & XFR_FLAG_AXFR_FINISHED) {
+			knot_zone_contents_deep_free(
+				&data->new_contents, 1);
+		} else {
+			if (data->data) {
+				xfrin_constructed_zone_t *constr_zone =
+					(xfrin_constructed_zone_t *)data->data;
+				knot_zone_contents_deep_free(
+						&(constr_zone->contents), 0);
+				xfrin_free_orphan_rrsigs(&(constr_zone->rrsigs));
+				free(data->data);
+				data->data = 0;
+			}
+		}
+		break;
+	case XFR_TYPE_IIN:
+		if (data->data) {
+			chs = (knot_changesets_t *)data->data;
+			knot_free_changesets(&chs);
+			data->data = NULL;
+		}
+
+		// this function is called before new contents are created
+		assert(data->new_contents == NULL);
+
+		break;
+	}
+
+	/* Cleanup other data - so that the structure may be reused. */
+	data->packet_nr = 0;
+	data->tsig_data_size = 0;
+
+	dbg_xfr_detail("Done.\n");
+	
+	return ret;
+}
+
 /*! \brief Free allocated xfer descriptor (also deinitializes). */
 static void xfr_free_task(knot_ns_xfr_t *task)
 {
@@ -90,21 +139,34 @@ static void xfr_free_task(knot_ns_xfr_t *task)
 	}
 	
 	/* Unlock if XFR/IN.*/
-	if (task->type == XFR_TYPE_AIN || task->type == XFR_TYPE_IIN) {
+	int is_xfer = task->type == XFR_TYPE_AIN || task->type == XFR_TYPE_IIN;
+	if (is_xfer) {
 		knot_zone_t *zone = task->zone;
 		zonedata_t *zd = (zonedata_t *)knot_zone_data(zone);
 		if (zd) {
 			zd->xfr_in.wrkr = 0;
 			pthread_mutex_unlock(&zd->xfr_in.lock);
 		}
+		
+		/* Free TSIG buffers. */
+		if (task->digest) {
+			free(task->digest);
+			task->digest = NULL;
+			task->digest_size = 0;
+		}
+		if (task->tsig_data) {
+			free(task->tsig_data);
+			task->tsig_data = NULL;
+			task->tsig_data_size = 0;
+		}
 	}
 	
-	/* No further access to zone. */
-	knot_zone_release(task->zone);
-	
-	/* Deinitialize */
-	xfr_request_deinit(task);
 	if (!task->session_closed) {
+		/* Cleanup pending request. */
+		if (is_xfer) {
+			xfr_xfrin_cleanup(w, task);
+		}
+		
 		/* Remove fd-related data. */
 		xfrhandler_t *h = w->master;
 		pthread_mutex_lock(&h->tasks_mx);
@@ -112,6 +174,12 @@ static void xfr_free_task(knot_ns_xfr_t *task)
 		pthread_mutex_unlock(&h->tasks_mx);
 		close(task->session);
 	}
+	
+	/* No further access to zone. */
+	knot_zone_release(task->zone);
+	
+	/* Deinitialize */
+	xfr_request_deinit(task);
 	free(task);
 }
 
@@ -271,55 +339,6 @@ static knot_ns_xfr_t *xfr_register_task(xfrworker_t *w, const knot_ns_xfr_t *req
 	return t;
 }
 
-/*!
- * \brief Clean pending transfer data.
- */
-static int xfr_xfrin_cleanup(xfrworker_t *w, knot_ns_xfr_t *data)
-{
-	int ret = KNOTD_EOK;
-	knot_changesets_t *chs = 0;
-
-	dbg_xfr_verb("Cleaning up after XFR-in.\n");
-	
-	switch(data->type) {
-	case XFR_TYPE_AIN:
-		if (data->flags & XFR_FLAG_AXFR_FINISHED) {
-			knot_zone_contents_deep_free(
-				&data->new_contents, 1);
-		} else {
-			if (data->data) {
-				xfrin_constructed_zone_t *constr_zone =
-					(xfrin_constructed_zone_t *)data->data;
-				knot_zone_contents_deep_free(
-						&(constr_zone->contents), 0);
-				xfrin_free_orphan_rrsigs(&(constr_zone->rrsigs));
-				free(data->data);
-				data->data = 0;
-			}
-		}
-		break;
-	case XFR_TYPE_IIN:
-		if (data->data) {
-			chs = (knot_changesets_t *)data->data;
-			knot_free_changesets(&chs);
-			data->data = NULL;
-		}
-
-		// this function is called before new contents are created
-		assert(data->new_contents == NULL);
-
-		break;
-	}
-
-	/* Cleanup other data - so that the structure may be reused. */
-	data->packet_nr = 0;
-	data->tsig_data_size = 0;
-
-	dbg_xfr_detail("Done.\n");
-	
-	return ret;
-}
-
 /*!
  * \brief Finalize XFR/IN transfer.
  *
@@ -750,18 +769,6 @@ int xfr_process_event(xfrworker_t *w, int fd, knot_ns_xfr_t *data, uint8_t *buf,
 			xfr_xfrin_cleanup(w, data);
 		}
 		
-		/* Free TSIG buffers. */
-		if (data->digest) {
-			free(data->digest);
-			data->digest = 0;
-			data->digest_size = 0;
-		}
-		if (data->tsig_data) {
-			free(data->tsig_data);
-			data->tsig_data = 0;
-			data->tsig_data_size = 0;
-		}
-		
 		/* Disconnect. */
 		result = KNOTD_ECONNREFUSED; /* Make it disconnect. */
 	}
diff --git a/src/libknot/nameserver/name-server.h b/src/libknot/nameserver/name-server.h
index 5592ab466709f5c4ccbf443d7d74d27984e9c5e3..3fe12103c446f4694481d188c361de361c1a057d 100644
--- a/src/libknot/nameserver/name-server.h
+++ b/src/libknot/nameserver/name-server.h
@@ -145,7 +145,7 @@ static const size_t KNOT_NS_TSIG_DATA_MAX_SIZE = 100 * 64 * 1024;
 enum knot_ns_xfr_flag_t {
 	XFR_FLAG_TCP = 1 << 0, /*!< XFR request is on TCP. */
 	XFR_FLAG_UDP = 1 << 1,  /*!< XFR request is on UDP. */
-	XFR_FLAG_AXFR_FINISHED = 1 << 2
+	XFR_FLAG_AXFR_FINISHED = 1 << 2 /*!< Transfer is finished. */
 };
 
 typedef enum knot_ns_transport {