diff --git a/daemon/worker.c b/daemon/worker.c
index 2d13e0ba3e1b63b9d2ac4785e4d407e51a5d372f..c3542ceb8190dbaebd807324f2f8f48f95b57b7d 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -451,16 +451,18 @@ static void on_write(uv_write_t *req, int status)
 
 #if defined(ENABLE_COOKIES)
 /** Update DNS cookie data in packet. */
-static bool subreq_update_cookies(uv_udp_t *handle, struct sockaddr *srvr_addr,
-                                  struct kr_cache *cookie_cache,
-                                  knot_pkt_t *pkt)
+static bool subreq_update_cookies(struct qr_task *task, uv_udp_t *handle,
+                                  struct sockaddr *srvr_addr, knot_pkt_t *pkt)
 {
+	assert(task);
 	assert(handle);
 	assert(srvr_addr);
 	assert(pkt);
 
+	struct kr_cookie_settings *clnt_sett = &task->req.ctx->cookie_ctx.clnt;
+
 	/* Cookies disabled or packet has no ENDS section. */
-	if (!kr_glob_cookie_ctx.clnt.enabled || !pkt->opt_rr) {
+	if (!clnt_sett->enabled || !pkt->opt_rr) {
 		return true;
 	}
 
@@ -484,7 +486,8 @@ static bool subreq_update_cookies(uv_udp_t *handle, struct sockaddr *srvr_addr,
 	}
 #endif /* 0 */
 
-	kr_request_put_cookie(&kr_glob_cookie_ctx.clnt.current, cookie_cache,
+	kr_request_put_cookie(&clnt_sett->current,
+	                      &task->worker->engine->resolver.cache,
 	                      (struct sockaddr*) sockaddr_ptr, srvr_addr, pkt);
 
 	return true;
@@ -513,13 +516,15 @@ static int qr_task_send(struct qr_task *task, uv_handle_t *handle, struct sockad
 	if (handle->type == UV_UDP) {
 #if defined(ENABLE_COOKIES)
 		/* The actual server IP address is needed before generating the
-		 * actual cookie. Also the resolver somehow mangles the query
-		 * packets before building the query i.e. the space needed for
-		 * the cookie cannot be allocated in the cookie layer. */
+		 * actual cookie. If we don't know the server address then we
+		 * also don't know the actual cookie size.
+		 * Also the resolver somehow mangles the query packets before
+		 * building the query i.e. the space needed for the cookie
+		 * cannot be allocated in the cookie layer. */
 		if (knot_wire_get_qr(pkt->wire) == 0) {
 			/* Update DNS cookies data in query. */
-			subreq_update_cookies((uv_udp_t *) handle, addr,
-			                      &task->worker->engine->resolver.cache, pkt);
+			subreq_update_cookies(task, (uv_udp_t *) handle, addr,
+			                      pkt);
 		}
 #endif /* defined(ENABLE_COOKIES) */
 
diff --git a/lib/cookies/control.c b/lib/cookies/control.c
index 87b9dc52dfd315bc21ebff2caf866e8e0db0a14c..6e0fec3c502e21f8d70f9b94dc14eb3d0b99eb31 100644
--- a/lib/cookies/control.c
+++ b/lib/cookies/control.c
@@ -14,10 +14,20 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <string.h>
+
 #include "lib/cookies/control.h"
 
-struct kr_cookie_ctx kr_glob_cookie_ctx = {
-	.clnt = { false, { NULL, -1 }, { NULL, -1} },
-	.srvr = { false, { NULL, -1 }, { NULL, -1} },
-	.cache_ttl = DFLT_COOKIE_TTL
-};
+void kr_cookie_ctx_init(struct kr_cookie_ctx *ctx)
+{
+	if (!ctx) {
+		return;
+	}
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->clnt.current.alg_id = ctx->clnt.recent.alg_id = -1;
+	ctx->srvr.current.alg_id = ctx->srvr.recent.alg_id = -1;
+
+	ctx->cache_ttl = DFLT_COOKIE_TTL;
+}
diff --git a/lib/cookies/control.h b/lib/cookies/control.h
index 97e6e5ad98a7ef11dc83b84c8a63cc92304a5abc..beb544c2c281bd30bb0fb27d127ac4bffa92b9a1 100644
--- a/lib/cookies/control.h
+++ b/lib/cookies/control.h
@@ -16,13 +16,10 @@
 
 #pragma once
 
-#include <libknot/rrtype/opt-cookie.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdlib.h>
 
-#include "lib/cookies/alg_containers.h"
-#include "lib/cache.h"
 #include "lib/defines.h"
 
 /** Holds secret quantity. */
@@ -56,6 +53,9 @@ struct kr_cookie_ctx {
 	uint32_t cache_ttl; /**< TTL used when caching cookies */
 };
 
-/** Global cookie control context. */
+/**
+ * @brief Initialises cookie control context.
+ * @param ctx cookie control context
+ */
 KR_EXPORT
-extern struct kr_cookie_ctx kr_glob_cookie_ctx;
+void kr_cookie_ctx_init(struct kr_cookie_ctx *ctx);
diff --git a/lib/cookies/helper.h b/lib/cookies/helper.h
index ad780972d2323c00d22f0636b2b38c478ea583c1..ddacbc11654299e4a83190d3b9b26bf340c1695d 100644
--- a/lib/cookies/helper.h
+++ b/lib/cookies/helper.h
@@ -16,10 +16,13 @@
 
 #pragma once
 
+#include <libknot/rrtype/opt-cookie.h>
 #include <libknot/packet/pkt.h>
 
+#include "lib/cookies/alg_containers.h"
 #include "lib/cookies/control.h"
 #include "lib/cookies/nonce.h"
+#include "lib/cache.h"
 #include "lib/defines.h"
 
 /**
diff --git a/lib/layer/cookiemonster.c b/lib/layer/cookiemonster.c
index 73032f7b087f6ebdc01c1676d0401433d0fc5257..cf60a8e1f9542135cd7a647e316b5c1d02087307 100644
--- a/lib/layer/cookiemonster.c
+++ b/lib/layer/cookiemonster.c
@@ -308,8 +308,9 @@ static int check_response(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	struct kr_request *req = ctx->data;
 	struct kr_query *qry = req->current_query;
+	struct kr_cookie_ctx *cookie_ctx = &req->ctx->cookie_ctx;
 
-	if (!kr_glob_cookie_ctx.clnt.enabled || (qry->flags & QUERY_TCP)) {
+	if (!cookie_ctx->clnt.enabled || (qry->flags & QUERY_TCP)) {
 		return ctx->state;
 	}
 
@@ -338,8 +339,8 @@ static int check_response(knot_layer_t *ctx, knot_pkt_t *pkt)
 		return ctx->state;
 	}
 
-	if (!check_cookie_content_and_cache(&kr_glob_cookie_ctx.clnt,
-	                                    kr_glob_cookie_ctx.cache_ttl, qry,
+	if (!check_cookie_content_and_cache(&cookie_ctx->clnt,
+	                                    cookie_ctx->cache_ttl, qry,
 	                                    pkt_cookie_opt, cookie_cache)) {
 		return KNOT_STATE_FAIL;
 	}
@@ -383,13 +384,15 @@ static inline uint8_t *req_cookie_option(struct kr_request *req)
 
 static int check_request(knot_layer_t *ctx, void *module_param)
 {
-	if (!kr_glob_cookie_ctx.srvr.enabled) {
+	struct kr_request *req = ctx->data;
+	struct kr_cookie_settings *srvr_sett = &req->ctx->cookie_ctx.srvr;
+
+	if (!srvr_sett->enabled) {
 		/* TODO -- IS there a way how to determine whether the original
 		 * request came via TCP? */
 		return ctx->state;
 	}
 
-	struct kr_request *req = ctx->data;
 	uint8_t *req_cookie_opt = req_cookie_option(req);
 	if (!req_cookie_opt) {
 		return ctx->state; /* Don't do anything without cookies. */
@@ -406,7 +409,6 @@ static int check_request(knot_layer_t *ctx, void *module_param)
 
 	bool ignore_badcookie = true; /* TODO -- Occasionally ignore? */
 
-	struct kr_cookie_settings *srvr_sett = &kr_glob_cookie_ctx.srvr;
 	if (!req->qsource.addr ||
 	    !srvr_sett->current.secr || (srvr_sett->current.alg_id < 0)) {
 		DEBUG_MSG(NULL, "%s\n", "missing server cookie context");
diff --git a/lib/resolve.c b/lib/resolve.c
index 5d11b54cc428ac38911278dcce51619d34031d07..94511d502035c4fe1128b253d68c222085956fdd 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -273,7 +273,7 @@ static int edns_create(knot_pkt_t *pkt, knot_pkt_t *template, struct kr_request
 	pkt->opt_rr = knot_rrset_copy(req->ctx->opt_rr, &pkt->mm);
 #if defined(ENABLE_COOKIES)
 	size_t wire_size = knot_edns_wire_size(pkt->opt_rr);
-	if (kr_glob_cookie_ctx.clnt.enabled) {
+	if (req->ctx->cookie_ctx.clnt.enabled) {
 		wire_size += KR_COOKIE_OPT_MAX_LEN;
 	}
 	return knot_pkt_reserve(pkt, wire_size);
@@ -462,7 +462,7 @@ static int resolve_query(struct kr_request *request, const knot_pkt_t *packet)
 		 * so such queries are handled directly here. */
 		struct knot_dns_cookies cookies = { 0, };
 		uint8_t *cookie_opt = kr_is_cookie_query(packet);
-		if (cookie_opt && kr_glob_cookie_ctx.clnt.enabled) {
+		if (cookie_opt && request->ctx->cookie_ctx.clnt.enabled) {
 			if (kr_ok() != kr_parse_cookie_opt(cookie_opt,
 			                                   &cookies)) {
 				/* TODO -- KNOT_RCODE_FORMERR? */
@@ -471,7 +471,7 @@ static int resolve_query(struct kr_request *request, const knot_pkt_t *packet)
 		}
 
 		return cookie_answer(request->qsource.addr,
-		                     &kr_glob_cookie_ctx.srvr,
+		                     &request->ctx->cookie_ctx.srvr,
 		                     &cookies, request->answer);
 #else /* !defined(ENABLE_COOKIES) */
 		return KNOT_STATE_FAIL;
diff --git a/lib/resolve.h b/lib/resolve.h
index 1f5fbecfab4ed1cbdb91402716969b0d6584459d..a2f116f69b1879afdc8056309ac479763e04acec 100644
--- a/lib/resolve.h
+++ b/lib/resolve.h
@@ -19,6 +19,7 @@
 #include <netinet/in.h>
 #include <libknot/packet/pkt.h>
 
+#include "lib/cookies/control.h"
 #include "lib/layer.h"
 #include "lib/generic/map.h"
 #include "lib/generic/array.h"
@@ -92,6 +93,11 @@ struct kr_context
 	kr_nsrep_lru_t *cache_rtt;
 	kr_nsrep_lru_t *cache_rep;
 	module_array_t *modules;
+#if defined(ENABLE_COOKIES)
+	/* The structure should not be held within the cookies module because
+	 * of better access. */
+	struct kr_cookie_ctx cookie_ctx;
+#endif /* defined(ENABLE_COOKIES) */
 	knot_mm_t *pool;
 };
 
diff --git a/modules/cookiectl/cookiectl.c b/modules/cookiectl/cookiectl.c
index 8f1d16b759f720c666a87690cf1faf60ded3a57a..fe62a765e519996d3b986cc1d312a746036a709a 100644
--- a/modules/cookiectl/cookiectl.c
+++ b/modules/cookiectl/cookiectl.c
@@ -16,6 +16,7 @@
 
 #include <assert.h>
 #include <ccan/json/json.h>
+#include <libknot/rrtype/opt-cookie.h>
 #include <libknot/db/db_lmdb.h>
 #include <stdlib.h>
 #include <string.h>
@@ -399,11 +400,14 @@ char *read_config(struct kr_cookie_ctx *ctx)
  */
 static char *cookiectl_config(void *env, struct kr_module *module, const char *args)
 {
+	struct kr_cookie_ctx *cookie_ctx = module->data;
+	assert(cookie_ctx);
+
 	/* Apply configuration, if any. */
-	apply_config(&kr_glob_cookie_ctx, args);
+	apply_config(cookie_ctx, args);
 
 	/* Return current configuration. */
-	return read_config(&kr_glob_cookie_ctx);
+	return read_config(cookie_ctx);
 }
 
 /*
@@ -415,7 +419,9 @@ int cookiectl_init(struct kr_module *module)
 {
 	struct engine *engine = module->data;
 
-	memset(&kr_glob_cookie_ctx, 0, sizeof(kr_glob_cookie_ctx));
+	struct kr_cookie_ctx *cookie_ctx = &engine->resolver.cookie_ctx;
+
+	kr_cookie_ctx_init(cookie_ctx);
 
 	struct kr_cookie_secret *cs = new_cookie_secret(KNOT_OPT_COOKIE_CLNT,
 	                                                true);
@@ -427,25 +433,24 @@ int cookiectl_init(struct kr_module *module)
 		return kr_error(ENOMEM);
 	}
 
-	const knot_lookup_t *lookup;
-
-	kr_glob_cookie_ctx.clnt.enabled = false;
-	kr_glob_cookie_ctx.clnt.current.secr = cs;
-	lookup = knot_lookup_by_name(kr_cc_alg_names, "FNV-64");
-	assert(lookup);
-	kr_glob_cookie_ctx.clnt.current.alg_id = lookup->id;
-	kr_glob_cookie_ctx.clnt.recent.alg_id = -1;
+	const knot_lookup_t *clookup = knot_lookup_by_name(kr_cc_alg_names,
+	                                                   "FNV-64");
+	const knot_lookup_t *slookup = knot_lookup_by_name(kr_sc_alg_names,
+	                                                   "FNV-64");
+	if (!clookup || !slookup) {
+		free(cs);
+		free(ss);
+		return kr_error(ENOKEY);
+	}
 
-	kr_glob_cookie_ctx.srvr.enabled = false;
-	kr_glob_cookie_ctx.srvr.current.secr = ss;
-	lookup = knot_lookup_by_name(kr_sc_alg_names, "FNV-64");
-	assert(lookup);
-	kr_glob_cookie_ctx.srvr.current.alg_id = lookup->id;
-	kr_glob_cookie_ctx.srvr.recent.alg_id = -1;
+	cookie_ctx->clnt.current.secr = cs;
+	cookie_ctx->clnt.current.alg_id = clookup->id;
 
-	kr_glob_cookie_ctx.cache_ttl = DFLT_COOKIE_TTL;
+	cookie_ctx->srvr.current.secr = ss;
+	cookie_ctx->srvr.current.alg_id = slookup->id;
 
-	module->data = NULL;
+	/* Replace engine pointer. */
+	module->data = cookie_ctx;
 
 	return kr_ok();
 }
@@ -453,21 +458,25 @@ int cookiectl_init(struct kr_module *module)
 KR_EXPORT
 int cookiectl_deinit(struct kr_module *module)
 {
-	kr_glob_cookie_ctx.clnt.enabled = false;
+	struct engine *engine = module->data;
+
+	struct kr_cookie_ctx *cookie_ctx = module->data;
+
+	cookie_ctx->clnt.enabled = false;
 
-	free(kr_glob_cookie_ctx.clnt.recent.secr);
-	kr_glob_cookie_ctx.clnt.recent.secr = NULL;
+	free(cookie_ctx->clnt.recent.secr);
+	cookie_ctx->clnt.recent.secr = NULL;
 
-	free(kr_glob_cookie_ctx.clnt.current.secr);
-	kr_glob_cookie_ctx.clnt.current.secr = NULL;
+	free(cookie_ctx->clnt.current.secr);
+	cookie_ctx->clnt.current.secr = NULL;
 
-	kr_glob_cookie_ctx.srvr.enabled = false;
+	cookie_ctx->srvr.enabled = false;
 
-	free(kr_glob_cookie_ctx.srvr.recent.secr);
-	kr_glob_cookie_ctx.srvr.recent.secr = NULL;
+	free(cookie_ctx->srvr.recent.secr);
+	cookie_ctx->srvr.recent.secr = NULL;
 
-	free(kr_glob_cookie_ctx.srvr.current.secr);
-	kr_glob_cookie_ctx.srvr.current.secr = NULL;
+	free(cookie_ctx->srvr.current.secr);
+	cookie_ctx->srvr.current.secr = NULL;
 
 	return kr_ok();
 }