diff --git a/daemon/worker.c b/daemon/worker.c
index 26a913a37fd085cf2837334d71ee218e7fb9a3bc..1043629bd106dbc178d87e4a9658cf49d1f47372 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -117,6 +117,7 @@ static void qr_task_timeout(uv_timer_t *req)
 {
 	struct qr_task *task = req->data;
 	if (task->next_handle) {
+		uv_cancel((uv_req_t *)&task->ioreq);
 		io_stop_read(task->next_handle);
 		qr_task_step(task, NULL);
 	}
@@ -182,7 +183,9 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
 {
 	/* Cancel timeout if active, close handle. */
 	if (task->next_handle) {
-		uv_close(task->next_handle, (uv_close_cb) free);
+		if (!uv_is_closing(task->next_handle)) {
+			uv_close(task->next_handle, (uv_close_cb) free);
+		}
 		uv_timer_stop(&task->timeout);
 		task->next_handle = NULL;
 	}
@@ -214,10 +217,10 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
 	task->next_handle->data = task;
 	if (sock_type == SOCK_STREAM) {
 		uv_connect_t *connect = &task->ioreq.connect;
+		connect->data = task;
 		if (uv_tcp_connect(connect, (uv_tcp_t *)task->next_handle, addr, qr_task_on_connect) != 0) {
 			return qr_task_step(task, NULL);
 		}
-		connect->data = task;
 	} else {
 		if (qr_task_send(task, task->next_handle, addr, next_query) != 0) {
 			return qr_task_step(task, NULL);
diff --git a/lib/layer/pktcache.c b/lib/layer/pktcache.c
index fb627685cc07988ca87772cdfabbf1856dc1ebff..050aec156255e35320b7e1c11b12af6f0289cdd5 100644
--- a/lib/layer/pktcache.c
+++ b/lib/layer/pktcache.c
@@ -24,6 +24,7 @@
 
 #define DEBUG_MSG(fmt...) QRDEBUG(kr_rplan_current(rplan), " pc ",  fmt)
 #define DEFAULT_MAXTTL (15 * 60)
+#define DEFAULT_NOTTL (5) /* Short-time "no data" retention to avoid bursts */
 
 static inline uint8_t get_tag(knot_pkt_t *pkt)
 {
@@ -47,7 +48,9 @@ static void adjust_ttl(knot_rrset_t *rr, uint32_t drift)
 	for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) {
 		knot_rdata_t *rd = knot_rdataset_at(&rr->rrs, i);
 		uint32_t ttl = knot_rdata_ttl(rd);
-		knot_rdata_set_ttl(rd, ttl - drift);
+		if (ttl >= drift) {
+			knot_rdata_set_ttl(rd, ttl - drift);
+		}
 	}
 }
 
@@ -96,6 +99,9 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
 	if (!qry || ctx->state & (KNOT_STATE_DONE|KNOT_STATE_FAIL)) {
 		return ctx->state;
 	}
+	if (knot_pkt_qclass(pkt) != KNOT_CLASS_IN) {
+		return ctx->state; /* Only IN class */
+	}
 
 	/* Fetch packet from cache */
 	namedb_txn_t txn;
@@ -119,7 +125,7 @@ static int peek(knot_layer_t *ctx, knot_pkt_t *pkt)
 
 static uint32_t packet_ttl(knot_pkt_t *pkt)
 {
-	uint32_t ttl = 0;
+	uint32_t ttl = DEFAULT_NOTTL;
 	/* Fetch SOA from authority. */
 	const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
 	for (unsigned i = 0; i < ns->count; ++i) {
@@ -134,6 +140,10 @@ static uint32_t packet_ttl(knot_pkt_t *pkt)
 		const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
 		for (unsigned k = 0; k < sec->count; ++k) {
 			const knot_rrset_t *rr = knot_pkt_rr(sec, k);
+			/* Skip OPT and TSIG */
+			if (rr->type == KNOT_RRTYPE_OPT || rr->type == KNOT_RRTYPE_TSIG) {
+				continue;
+			}
 			for (uint16_t i = 0; i < rr->rrs.rr_count; ++i) {
 				knot_rdata_t *rd = knot_rdataset_at(&rr->rrs, i);
 				if (knot_rdata_ttl(rd) < ttl) {
@@ -149,12 +159,16 @@ static int stash(knot_layer_t *ctx)
 {
 	struct kr_request *req = ctx->data;
 	struct kr_rplan *rplan = &req->rplan;
-	if (EMPTY_LIST(rplan->resolved) || ctx->state == KNOT_STATE_FAIL) {
+	if (EMPTY_LIST(rplan->resolved) || ctx->state & KNOT_STATE_FAIL) {
 		return ctx->state; /* Don't cache anything if failed. */
 	}
-	knot_pkt_t *pkt = req->answer;
 	struct kr_query *qry = TAIL(rplan->resolved);
-	if (qry->flags & QUERY_CACHED || !(kr_response_classify(pkt) & (PKT_NODATA|PKT_NXDOMAIN))) {
+	knot_pkt_t *pkt = req->answer;
+	if (knot_pkt_qclass(pkt) != KNOT_CLASS_IN) {
+		return ctx->state; /* Only IN class */
+	}
+	int pkt_class = kr_response_classify(pkt);
+	if (qry->flags & QUERY_CACHED || !(pkt_class & (PKT_NODATA|PKT_NXDOMAIN))) {
 		return ctx->state; /* Cache only negative, not-cached answers. */
 	}
 	uint32_t ttl = packet_ttl(pkt);
diff --git a/lib/resolve.c b/lib/resolve.c
index 23d4744408cb142e77b279ae83c521066e04738b..92cee2d76529652599c0c5e2824469fe00075a6c 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -347,6 +347,8 @@ int kr_resolve_consume(struct kr_request *request, knot_pkt_t *packet)
 	/* Pop query if resolved. */
 	if (qry->flags & QUERY_RESOLVED) {
 		kr_rplan_pop(rplan, qry);
+	} else { /* Clear query flags for next attempt */
+		qry->flags &= ~QUERY_CACHED;
 	}
 
 	knot_overlay_reset(&request->overlay);