diff --git a/daemon/engine.h b/daemon/engine.h
index d7acd94d8a8d8db8c8ccd6e3eaa2b4ff7840585a..bb1f9c37cdc0a1df9acccac4504f0da6cc880015 100644
--- a/daemon/engine.h
+++ b/daemon/engine.h
@@ -39,6 +39,6 @@ int engine_start(struct engine *engine);
 void engine_stop(struct engine *engine);
 int engine_register(struct engine *engine, const char *module);
 int engine_unregister(struct engine *engine, const char *module);
-/** Return engine light userdata. */
 void engine_lualib(struct engine *engine, const char *name, int (*lib_cb) (struct lua_State *));
+/** Return engine light userdata. */
 struct engine *engine_luaget(struct lua_State *L);
diff --git a/daemon/io.c b/daemon/io.c
index 6f7e01187b50f75f3e5b33128e210aae55250350..548100371c3e5cc541833ab68f95abd2f1f6e3e9 100644
--- a/daemon/io.c
+++ b/daemon/io.c
@@ -56,7 +56,7 @@ void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
 
 	/* UDP requests are oneshot, always close afterwards */
 	if (handle->data && !uv_is_closing((uv_handle_t *)handle)) { /* Do not free master socket */
-		uv_close((uv_handle_t *)handle, handle_free);
+		io_close((uv_handle_t *)handle);
 	}
 
 	/* Check the incoming wire length. */
@@ -96,7 +96,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
 
 	/* Check for connection close */
 	if (nread <= 0) {
-		uv_close((uv_handle_t *)handle, handle_free);
+		io_close((uv_handle_t *)handle);
 		return;
 	} else if (nread < 2) {
 		/* Not enough bytes to read length */
@@ -175,6 +175,11 @@ uv_handle_t *io_create(uv_loop_t *loop, int type)
 	}
 }
 
+void io_close(uv_handle_t *handle)
+{
+	uv_close(handle, (uv_close_cb) handle_free);
+}
+
 int io_start_read(uv_handle_t *handle)
 {
 	if (handle->type == UV_UDP) {
@@ -191,4 +196,4 @@ int io_stop_read(uv_handle_t *handle)
 	} else {
 		return uv_read_stop((uv_stream_t *)handle);
 	}
-}
\ No newline at end of file
+}
diff --git a/daemon/io.h b/daemon/io.h
index 815387f0a7c348c19243a12a3920877f0e14fbe0..83e01a0683228e235b87f98263dfe6eeecbc43dc 100644
--- a/daemon/io.h
+++ b/daemon/io.h
@@ -25,5 +25,6 @@ void udp_unbind(struct endpoint *ep);
 int tcp_bind(struct endpoint *ep, struct sockaddr *addr);
 void tcp_unbind(struct endpoint *ep);
 uv_handle_t *io_create(uv_loop_t *loop, int type);
+void io_close(uv_handle_t *handle);
 int io_start_read(uv_handle_t *handle);
 int io_stop_read(uv_handle_t *handle);
\ No newline at end of file
diff --git a/daemon/worker.c b/daemon/worker.c
index 732b309774861e779b39cfb5ce7977ebb22495e3..55fbbd9a475b17f619c1c3967957f0b9aacc7f3f 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -15,7 +15,6 @@
  */
 
 #include <uv.h>
-
 #include <libknot/packet/pkt.h>
 #include <libknot/internal/net.h>
 #include <libknot/internal/mempool.h>
@@ -43,8 +42,11 @@ struct qr_task
 		} addr;
 		uv_handle_t *handle;
 	} source;
+	uint16_t iter_count;
+	uint16_t flags;
 };
 
+/* Forward decls */
 static int qr_task_step(struct qr_task *task, knot_pkt_t *packet);
 
 static int parse_query(knot_pkt_t *query)
@@ -71,6 +73,7 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha
 	/* Create worker task */
 	struct engine *engine = worker->engine;
 	struct qr_task *task = mm_alloc(&pool, sizeof(*task));
+	memset(task, 0, sizeof(*task));
 	if (!task) {
 		mp_delete(pool.ctx);
 		return NULL;
@@ -98,7 +101,7 @@ static struct qr_task *qr_task_create(struct worker_ctx *worker, uv_handle_t *ha
 	return task;
 }
 
-static void qr_task_close(uv_handle_t *handle)
+static void qr_task_free(uv_handle_t *handle)
 {
 	struct qr_task *task = handle->data;
 	mp_delete(task->req.pool.ctx);
@@ -123,9 +126,8 @@ static void qr_task_on_send(uv_req_t* req, int status)
 			if (status == 0 && task->next_handle) {
 				io_start_read(task->next_handle);
 			}
-		} else {
-			/* Finalize task */
-			uv_close((uv_handle_t *)&task->timeout, qr_task_close);
+		} else { /* Finalize task */
+			uv_close((uv_handle_t *)&task->timeout, qr_task_free);
 		}
 	}
 }
@@ -163,7 +165,6 @@ static void qr_task_on_connect(uv_connect_t *connect, int status)
 static int qr_task_finalize(struct qr_task *task, int state)
 {
 	kr_resolve_finish(&task->req, state);
-	uv_timer_stop(&task->timeout);
 	qr_task_send(task, task->source.handle, (struct sockaddr *)&task->source.addr, task->req.answer);
 	return state == KNOT_STATE_DONE ? 0 : kr_error(EIO);
 }
@@ -188,6 +189,11 @@ static int qr_task_step(struct qr_task *task, knot_pkt_t *packet)
 		return qr_task_finalize(task, state);
 	}
 
+	/* Iteration limit */
+	if (++task->iter_count > KR_ITER_LIMIT) {
+		return qr_task_finalize(task, KNOT_STATE_FAIL);
+	}
+
 	/* Create connection for iterative query */
 	uv_handle_t *source_handle = task->source.handle;
 	task->next_handle = io_create(source_handle->loop, sock_type);
@@ -233,7 +239,6 @@ int worker_exec(struct worker_ctx *worker, uv_handle_t *handle, knot_pkt_t *quer
 	struct qr_task *task = handle->data;
 	bool is_master_socket = (!task);
 	if (is_master_socket) {
-		/* Accept only queries */
 		if (knot_wire_get_qr(query->wire)) {
 			return kr_error(EINVAL); /* Ignore. */
 		}
diff --git a/lib/defines.h b/lib/defines.h
index 141f219557df72af09e1b7b5f38297ec84595925..773314a11b1de3cd81f89d36c2641f9ba8342022 100644
--- a/lib/defines.h
+++ b/lib/defines.h
@@ -33,7 +33,7 @@
  * @cond internal
  */
 #define KR_CONN_RTT_MAX 5000 /* Timeout for network activity */
-#define ITER_LIMIT 50        /* Built-in iterator limit */
+#define KR_ITER_LIMIT 50        /* Built-in iterator limit */
 
 /*
  * Timers.
diff --git a/lib/layer/iterate.c b/lib/layer/iterate.c
index f7673cce31fe47cbdf2cf6a4da5434acc56d74d9..d13d876c03708bf412c1d256ca0ba95e7b99f93d 100644
--- a/lib/layer/iterate.c
+++ b/lib/layer/iterate.c
@@ -276,7 +276,9 @@ static int process_answer(knot_pkt_t *pkt, struct kr_request *req)
 	 */
 	bool is_final = (query->parent == NULL);
 	int pkt_class = response_classify(pkt);
-	if (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname) && (pkt_class & (PKT_NXDOMAIN|PKT_NODATA))) {
+	if (!knot_dname_is_equal(knot_pkt_qname(pkt), query->sname) &&
+	    (pkt_class & (PKT_NOERROR|PKT_NXDOMAIN|PKT_NODATA))) {
+		DEBUG_MSG("<= found cut, retrying with non-minimized name\n");
 		query->flags |= QUERY_NO_MINIMIZE;
 		return KNOT_STATE_DONE;
 	}
@@ -301,6 +303,7 @@ static int process_answer(knot_pkt_t *pkt, struct kr_request *req)
 
 	/* Follow canonical name as next SNAME. */
 	if (cname != query->sname) {
+		DEBUG_MSG("<= cname chain, following\n");
 		(void) kr_rplan_push(&req->rplan, query->parent, cname, query->sclass, query->stype);
 	} else {
 		if (query->parent == NULL) {
diff --git a/lib/resolve.c b/lib/resolve.c
index 4c1b912008452f5a483b796b86943578f7159631..281efe69ece50cd5846db456cfd14ecafc0c7be0 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -168,8 +168,8 @@ int kr_resolve(struct kr_context* ctx, knot_pkt_t *answer,
 	int state = kr_resolve_query(&request, qname, qclass, qtype);
 	while (state == KNOT_STATE_PRODUCE) {
 		/* Hardlimit on iterative queries */
-		if (++iter_count > ITER_LIMIT) {
-			DEBUG_MSG("iteration limit %d reached\n", ITER_LIMIT);
+		if (++iter_count > KR_ITER_LIMIT) {
+			DEBUG_MSG("iteration limit %d reached\n", KR_ITER_LIMIT);
 			state = KNOT_STATE_FAIL;
 			break;
 		}
diff --git a/tests/testdata/iter_minim_nonempty.rpl b/tests/testdata/iter_minim_nonempty.rpl
new file mode 100644
index 0000000000000000000000000000000000000000..44e88349c05f01b219e93023ffcf186b4c0dfec1
--- /dev/null
+++ b/tests/testdata/iter_minim_nonempty.rpl
@@ -0,0 +1,125 @@
+; config options
+server:
+	target-fetch-policy: "0 0 0 0 0"
+	query-minimization: on
+
+stub-zone:
+	name: "."
+	stub-addr: 193.0.14.129 	# K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test query minimization with terminal in resolution path.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+	ADDRESS 193.0.14.129 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS	K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.	IN	A	193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net. IN NS	K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.	IN	A	193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+gtld-servers.net. IN NS
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+a.gtld-servers.net. IN AAAA
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com.	IN NS	lame-addr.gtld-servers.net.
+com.	IN NS	a.gtld-servers.net.
+SECTION ADDITIONAL
+lame-addr.gtld-servers.net.	IN 	A	1.1.1.1
+a.gtld-servers.net.	IN 	A	192.5.6.30
+ENTRY_END
+RANGE_END
+
+; lame.gtld-servers.net.
+RANGE_BEGIN 0 100
+	ADDRESS 1.1.1.1
+
+EANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+	ADDRESS 192.5.6.30
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN CNAME nowhere.
+SECTION AUTHORITY
+com.	IN NS	a.gtld-servers.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+www.example.com.	IN NS	blackhole.
+SECTION AUTHORITY
+com.	IN NS	a.gtld-servers.net.
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN NS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN NS
+SECTION ANSWER
+www.example.com. IN NS blackhole.
+ENTRY_END
+
+SCENARIO_END