diff --git a/lib/resolve.c b/lib/resolve.c
index 1408d3289657f7c22af77bfd3c9936e4a99a826c..bb365ff75201a2f94e0eaf65dd452fd6d77fb7f8 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -10,61 +10,90 @@
 #include <libknot/rrset-dump.h>
 #include <common/print.h>
 
+#ifndef NDEBUG
+static void print_result(struct kr_result *result)
+{
+	char *qnamestr = knot_dname_to_str(knot_pkt_qname(result->ans));
+	char *cnamestr = knot_dname_to_str(result->cname);
+	printf("resolution of %s -> %s\n", qnamestr, cnamestr);
+	free(qnamestr); free(cnamestr);
+
+	printf("rcode = %d (%u RR)\n", knot_wire_get_rcode(result->ans->wire), result->ans->rrset_count);
+	char strbuf[4096] = {0};
+	int buflen = sizeof(strbuf);
+	knot_dump_style_t style = {0};
+	for (unsigned i = 0; i < result->ans->rrset_count; ++i) {
+		int r = knot_rrset_txt_dump(&result->ans->rr[i], strbuf, buflen, &style);
+		if (r > 0) buflen -= r;
+	}
+
+	printf("%s", strbuf);
+	printf("queries: %u\n", result->nr_queries);
+	printf("rtt %.02f msecs\n", time_diff(&result->t_start, &result->t_end));
+}
+
+#define print_step(s...) \
+do { \
+	char *_qstr = knot_dname_to_str(ctx->sname); \
+	char _astr[SOCKADDR_STRLEN]; \
+	sockaddr_tostr(&kr_slist_top(ctx)->addr, _astr, sizeof(_astr)); \
+	char *_soastr = knot_dname_to_str(kr_slist_top(ctx)->name); \
+	printf("[%s] at %s (soa %s) ", _qstr, _astr, _soastr); \
+	printf(s); \
+	printf("\n"); \
+} while(0)
+#else
+static void print_result(struct kr_result *result) {}
+#define print_step
+#endif
+
 int kr_resolve(struct kr_context* ctx, struct kr_result* result,
-                     const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
+               const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
 {
-	/* TODO: how to load all the layers? no API support yet */
-	ctx->sname = knot_dname_copy(qname, ctx->mm);
+	if (ctx == NULL || result == NULL || qname == NULL) {
+		return -1;
+	}
+
+	ctx->sname = qname;
 	ctx->sclass = qclass;
 	ctx->stype = qtype;
+	ctx->state = NS_PROC_MORE;
 	kr_result_init(ctx, result);
 
 	struct layer_param param;
 	param.ctx = ctx;
 	param.result = result;
 
-	/* TODO: read root hints. */
-	struct sockaddr_in root_addr = uv_ip4_addr("198.41.0.4", 53);
-	kr_slist_add(ctx, knot_dname_copy((const uint8_t *)"", NULL), (struct sockaddr *)&root_addr);
-
-	/* Resolve. */
-	struct knot_requestor req;
-	knot_requestor_init(&req, LAYER_ITERATE, ctx->mm);
-	struct timeval tv = { 5, 0 };
-	struct kr_ns *ns = NULL;
-	struct knot_request *tx = NULL;
-	int watchdog = 0;
+	/* TODO: how to load all the layers? no API support yet */
+	struct timeval timeout = { 5, 0 };
+	struct knot_requestor requestor;
+	knot_requestor_init(&requestor, LAYER_ITERATE, ctx->pool);
+
 	while(ctx->state != NS_PROC_DONE) {
-		ns = kr_slist_top(ctx);
-		tx = knot_requestor_make(&req, (const struct sockaddr *)&ns->addr,
-		                         NULL, NULL);
-		knot_requestor_enqueue(&req, tx, &param);
-		knot_requestor_exec(&req, &tv);
-
-		/* TODO: restart if sname != originating */
-		if (qname != ctx->sname) {
-			printf("we didn't resolve the cname target...yet\n");
-		}
+		/* Sort preference list to the SNAME and pick a NS. */
+		kr_slist_sort(ctx);
+		struct kr_ns *ns = kr_slist_top(ctx);
 
-		/* TODO: safety check, remove */
-		assert(++watchdog < 10);
-	}
-	knot_requestor_clear(&req);
+		print_step("iterating");
 
-	char *qnamestr = knot_dname_to_str(qname);
-	char *cnamestr = knot_dname_to_str(ctx->sname);
-	printf("resolution of %s -> %s\n", qnamestr, cnamestr);
-	free(qnamestr); free(cnamestr);
-	printf("rcode = %d (%u RR)\n", knot_wire_get_rcode(result->ans->wire), result->ans->rrset_count);
-	char strbuf[4096] = {0}; int buflen = sizeof(strbuf);
-	knot_dump_style_t style = {0};
-	for (unsigned i = 0; i < result->ans->rrset_count; ++i) {
-		int r = knot_rrset_txt_dump(&result->ans->rr[i], strbuf, buflen, &style);
-		if (r > 0) buflen -= r;
+		/* Resolve. */
+		struct knot_request *tx = knot_requestor_make(&requestor,
+		                         (const struct sockaddr *)&ns->addr,
+		                         NULL, NULL, 0);
+		knot_requestor_enqueue(&requestor, tx, &param);
+		int ret = knot_requestor_exec(&requestor, &timeout);
+		/* TODO: soft remove, retry later */
+		if (ret != 0) {
+			print_step("server failure %d", ret);
+			kr_slist_pop(ctx);
+		}
 	}
-	printf("%s", strbuf);
-	printf("queries: %u\n", result->nr_queries);
-	printf("rtt %.02f msecs\n", time_diff(&result->t_start, &result->t_end));
+
+	print_step(" ---> done");
+
+	knot_requestor_clear(&requestor);
+
+	print_result(result);
 
 	return 0;
 }
diff --git a/lib/resolve.h b/lib/resolve.h
index 3adc30597bacb583ae9e238a00a377211645fe9f..fd69484e59eb753a7a797f3142946e9d0905c2e7 100644
--- a/lib/resolve.h
+++ b/lib/resolve.h
@@ -18,4 +18,4 @@ limitations under the License.
 #include "context.h"
 
 int kr_resolve(struct kr_context* ctx, struct kr_result* result,
-                     const knot_dname_t *qname, uint16_t qclass, uint16_t qtype);
\ No newline at end of file
+               const knot_dname_t *qname, uint16_t qclass, uint16_t qtype);
\ No newline at end of file
diff --git a/tests/context.c b/tests/context.c
index 86698c600f9cf63d6df585f1d477b20ad807f16e..cb9494a356b3e28d3e516cdeabb64e83ef5b6f1b 100644
--- a/tests/context.c
+++ b/tests/context.c
@@ -13,7 +13,7 @@ static void tests_ctx_create(void **state)
 	mm_ctx_init(&mm);
 	struct kr_context ctx;
 	assert_int_equal(kr_context_init(&ctx, &mm), 0);
-	assert_int_equal(kr_context_close(&ctx), 0);
+	assert_int_equal(kr_context_deinit(&ctx), 0);
 }
 
 int main(void)
diff --git a/tests/resolve.c b/tests/resolve.c
index 8435d2fb860809e1d1b6305face0c6ae3b8ba361..05c55e2cf6a2aae013c596be7b8d7853f7a779c2 100644
--- a/tests/resolve.c
+++ b/tests/resolve.c
@@ -17,7 +17,7 @@ void test_resolve_sync(void **state)
 	const knot_dname_t *qname = (const uint8_t *)"\x06""dnssec""\x02""cz";
 	int ret = kr_resolve(&ctx, &res, qname, KNOT_CLASS_IN, KNOT_RRTYPE_A);
 	assert_int_equal(ret, 0);
-	kr_context_close(&ctx);
+	kr_result_deinit(&res);
 }
 
 int main(void)