diff --git a/src/knot/modules/cookies/cookies.c b/src/knot/modules/cookies/cookies.c
index fbc9c9eb22ffbf404beca9b8bfe8f2f6c6975ff1..c85528d6fe2e2f0704ff6039d23f546c0871b263 100644
--- a/src/knot/modules/cookies/cookies.c
+++ b/src/knot/modules/cookies/cookies.c
@@ -149,11 +149,6 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt,
 
 	cookies_ctx_t *ctx = knotd_mod_ctx(mod);
 
-	// DNS cookies are ignored in the case of the TCP connection.
-	if (!(qdata->params->flags & KNOTD_QUERY_FLAG_LIMIT_SIZE)) {
-		return state;
-	}
-
 	// Check if the cookie option is present.
 	uint8_t *cookie_opt = knot_pkt_edns_option(qdata->query,
 	                                           KNOT_EDNS_OPTION_COOKIE);
@@ -192,7 +187,18 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt,
 	// Compare server cookie.
 	ret = knot_edns_cookie_server_check(&sc, &cc, &params);
 	if (ret != KNOT_EOK) {
-		if (ATOMIC_GET(ctx->badcookie_ctr) > BADCOOKIE_CTR_INIT) {
+		// TCP server should take the authentication provided by the use
+		// of TCP into account and SHOULD process the request and provide
+		// a normal response.
+		if (!(qdata->params->flags & KNOTD_QUERY_FLAG_LIMIT_SIZE)) {
+			if (knot_edns_cookie_server_generate(&sc, &cc, &params) != KNOT_EOK ||
+			    put_cookie(qdata, pkt, &cc, &sc) != KNOT_EOK)
+			{
+				return KNOTD_STATE_FAIL;
+			}
+
+			return state;
+		} else if (ATOMIC_GET(ctx->badcookie_ctr) > BADCOOKIE_CTR_INIT) {
 			// Silently drop the response.
 			update_ctr(ctx);
 			knotd_mod_stats_incr(mod, qdata->params->thread_id, 1, 0, 1);
@@ -202,13 +208,9 @@ static knotd_state_t cookies_process(knotd_state_t state, knot_pkt_t *pkt,
 				update_ctr(ctx);
 			}
 
-			ret = knot_edns_cookie_server_generate(&sc, &cc, &params);
-			if (ret != KNOT_EOK) {
-				return KNOTD_STATE_FAIL;
-			}
-
-			ret = put_cookie(qdata, pkt, &cc, &sc);
-			if (ret != KNOT_EOK) {
+			if (knot_edns_cookie_server_generate(&sc, &cc, &params) != KNOT_EOK ||
+			    put_cookie(qdata, pkt, &cc, &sc) != KNOT_EOK)
+			{
 				return KNOTD_STATE_FAIL;
 			}
 
diff --git a/tests-extra/tests/modules/cookies/test.py b/tests-extra/tests/modules/cookies/test.py
index fa23b6c40120fabc56647c3225cebfcd50125ee8..3be0096879e796a71042c78156c05ffd5163f0e7 100644
--- a/tests-extra/tests/modules/cookies/test.py
+++ b/tests-extra/tests/modules/cookies/test.py
@@ -40,6 +40,16 @@ def check_rcode(server, query, rcode, msg):
     compare(response.rcode(), rcode, msg)
     return response
 
+def check_rcode_tcp(server, query, rcode, msg):
+    try:
+        response = dns.query.tcp(query, server.addr, port=server.port, timeout=1)
+    except dns.exception.Timeout:
+        response = None
+    if response is None:
+        return None
+    compare(response.rcode(), rcode, msg)
+    return response
+
 t = Test(stress=False)
 
 ModCookies.check()
@@ -61,6 +71,11 @@ check_rcode(knot, query, rcodeNoerror, "NO EDNS")
 query = dns.message.make_query("dns1.example.com", "A", use_edns=True)
 check_rcode(knot, query, rcodeNoerror, "NO COOKIE OPT")
 
+# Try a query without a server cookie over TCP
+cookieOpt = dns.edns.option_from_wire(cookieOpcode, clientCookie, 0, clientCookieLen)
+query = dns.message.make_query("dns1.example.com", "A", use_edns=True, options=[cookieOpt])
+response = check_rcode_tcp(knot, query, rcodeNoerror, "ONLY CLIENT COOKIE [TCP]")
+
 # Try a query without a server cookie
 cookieOpt = dns.edns.option_from_wire(cookieOpcode, clientCookie, 0, clientCookieLen)
 query = dns.message.make_query("dns1.example.com", "A", use_edns=True, options=[cookieOpt])