diff --git a/src/knot/nameserver/internet.c b/src/knot/nameserver/internet.c
index fbffd55513fccecc28bcb13bc4d087a094b81fdc..9101641ba4f9822213d41d636e8bdac4d6d81b15 100644
--- a/src/knot/nameserver/internet.c
+++ b/src/knot/nameserver/internet.c
@@ -451,10 +451,17 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata)
 	dbg_ns("%s(%p, %p)\n", __func__, pkt, qdata);
 
 	/* Name is covered by wildcard. */
-	const knot_node_t *wildcard_node = knot_node_wildcard_child(qdata->encloser);
-	if (wildcard_node) {
+	if (knot_node_has_wildcard_child(qdata->encloser)) {
 		dbg_ns("%s: name %p covered by wildcard\n", __func__, qdata->name);
+
+		/* Find wildcard child in the zone. */
+		const knot_node_t *wildcard_node =
+		                knot_zone_contents_find_wildcard_child(
+		                        qdata->zone->contents, qdata->encloser);
+
 		qdata->node = wildcard_node;
+		assert(qdata->node != NULL);
+
 		/* keep encloser */
 		qdata->previous = NULL;
 
@@ -463,7 +470,7 @@ static int name_not_found(knot_pkt_t *pkt, struct query_data *qdata)
 
 		/* Put to wildcard node list. */
 		if (wildcard_visit(qdata, wildcard_node, qdata->name) != KNOT_EOK) {
-				next_state = ERROR;
+			next_state = ERROR;
 		}
 
 		return next_state;
diff --git a/src/knot/updates/xfr-in.c b/src/knot/updates/xfr-in.c
index 90f4e83c86377e1d26f627e7e016fffdbcb7ee6c..c29b4aaeb99193cd501623c4d00cb7309dc01f38 100644
--- a/src/knot/updates/xfr-in.c
+++ b/src/knot/updates/xfr-in.c
@@ -987,8 +987,9 @@ static int xfrin_mark_empty(knot_node_t **node_p, void *data)
 		}
 		knot_node_set_empty(node);
 		if (node->parent) {
-			if (node->parent->wildcard_child == node) {
-				node->parent->wildcard_child = NULL;
+			if (knot_node_has_wildcard_child(node->parent)
+			    && knot_dname_is_wildcard(node->owner)) {
+				knot_node_clear_wildcard_child(node->parent);
 			}
 			node->parent->children--;
 			// Recurse using the parent node
diff --git a/src/knot/zone/node.c b/src/knot/zone/node.c
index 8a131da05a5e79c1a059b02e87b09287b4134911..fd2dd524ea35faed2b9bdbdb3948d83ced5531a6 100644
--- a/src/knot/zone/node.c
+++ b/src/knot/zone/node.c
@@ -377,37 +377,27 @@ knot_dname_t *knot_node_get_owner(const knot_node_t *node)
 
 /*----------------------------------------------------------------------------*/
 
-knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node)
+void knot_node_set_wildcard_child(knot_node_t *node)
 {
 	if (node == NULL) {
-		return NULL;
+		return;
 	}
 
-	return node->wildcard_child;
+	knot_node_flags_set(node, KNOT_NODE_FLAGS_WILDCARD_CHILD);
 }
 
 /*----------------------------------------------------------------------------*/
 
-void knot_node_set_wildcard_child(knot_node_t *node,
-                                  knot_node_t *wildcard_child)
+int knot_node_has_wildcard_child(const knot_node_t *node)
 {
-	if (node == NULL) {
-		return;
-	}
-
-	node->wildcard_child = wildcard_child;
-//	assert(wildcard_child->parent == node);
+	return knot_node_flags_get(node, KNOT_NODE_FLAGS_WILDCARD_CHILD);
 }
 
 /*----------------------------------------------------------------------------*/
 
-const knot_node_t *knot_node_wildcard_child(const knot_node_t *node)
+void knot_node_clear_wildcard_child(knot_node_t *node)
 {
-	if (node == NULL) {
-		return NULL;
-	}
-
-	return knot_node_get_wildcard_child(node);
+	knot_node_flags_clear(node, KNOT_NODE_FLAGS_WILDCARD_CHILD);
 }
 
 /*----------------------------------------------------------------------------*/
@@ -641,4 +631,3 @@ bool knot_node_rrtype_exists(const knot_node_t *node, uint16_t type)
 {
 	return knot_node_rrs(node, type) != NULL;
 }
-
diff --git a/src/knot/zone/node.h b/src/knot/zone/node.h
index 42fd2908697e5945565bd84d02a2e4fbaa86bccb..51dbf2d3e4a4a3ffcaca7e003fdb52818c332cfe 100644
--- a/src/knot/zone/node.h
+++ b/src/knot/zone/node.h
@@ -48,9 +48,6 @@ struct knot_node {
 	/*! \brief Type-ordered array of RRSets belonging to this node. */
 	struct rr_data *rrs;
 
-	/*! \brief Wildcard node being the direct descendant of this node. */
-	struct knot_node *wildcard_child;
-
 	/*!
 	 * \brief Previous node in canonical order.
 	 *
@@ -75,10 +72,7 @@ struct knot_node {
 	/*!
 	 * \brief Various flags.
 	 *
-	 *   0x01 - node is a delegation point
-	 *   0x02 - node is non-authoritative (under a delegation point)
-	 *   0x04 - NSEC(3) was removed from the node.
-	 *   0x10 - node is empty and will be deleted after update
+	 * \ref knot_node_flags_t
 	 */
 	uint8_t flags;
 };
@@ -106,6 +100,8 @@ typedef enum {
 	/*! \brief Node is empty and will be deleted after update.
 	 *  \todo Remove after dname refactoring, update description in node. */
 	KNOT_NODE_FLAGS_EMPTY = 1 << 4,
+	/*! \brief Node has a wildcard child. */
+	KNOT_NODE_FLAGS_WILDCARD_CHILD = 1 << 5
 } knot_node_flags_t;
 
 /*----------------------------------------------------------------------------*/
@@ -260,29 +256,37 @@ void knot_node_set_nsec3_node(knot_node_t *node, knot_node_t *nsec3_node);
 const knot_dname_t *knot_node_owner(const knot_node_t *node);
 
 /*!
- * \todo Document me.
+ * \brief Returns the owner of the node as a non-const reference.
+ *
+ * \param node Node to get the owner of.
+ *
+ * \return Owner of the given node.
  */
 knot_dname_t *knot_node_get_owner(const knot_node_t *node);
 
 /*!
- * \brief Returns the wildcard child of the node.
- *
- * \param node Node to get the owner of.
+ * \brief Sets the wildcard child flag of the node.
  *
- * \return Wildcard child of the given node or NULL if it has none.
+ * \param node Node that has wildcard.
  */
-const knot_node_t *knot_node_wildcard_child(const knot_node_t *node);
+void knot_node_set_wildcard_child(knot_node_t *node);
 
 /*!
- * \brief Sets the wildcard child of the node.
+ * \brief Checks if node has a wildcard child.
  *
- * \param node Node to set the wildcard child of.
- * \param wildcard_child Wildcard child of the node.
+ * \param node Node to check.
+ *
+ * \retval > 0 if the node has a wildcard child.
+ * \retval 0 otherwise.
  */
-void knot_node_set_wildcard_child(knot_node_t *node,
-                                  knot_node_t *wildcard_child);
+int knot_node_has_wildcard_child(const knot_node_t *node);
 
-knot_node_t *knot_node_get_wildcard_child(const knot_node_t *node);
+/*!
+ * \brief Clears the node's wildcard child flag.
+ *
+ * \param node Node to clear the flag in.
+ */
+void knot_node_clear_wildcard_child(knot_node_t *node);
 
 /*!
  * \brief Mark the node as a delegation point.
diff --git a/src/knot/zone/zone-contents.c b/src/knot/zone/zone-contents.c
index ff9155fe2958eb6b5e4d750b542285b05384e034..00227537f37e90a1b0fb8c6c8af5b928583fbdb3 100644
--- a/src/knot/zone/zone-contents.c
+++ b/src/knot/zone/zone-contents.c
@@ -175,8 +175,12 @@ static int discover_additionals(struct rr_data *rr_data,
 		/* Try to find node for the dname in the RDATA. */
 		dname = knot_rrs_name(rrs, i, rr_data->type);
 		knot_zone_contents_find_dname(zone, dname, &node, &encloser, &prev);
-		if (node == NULL && encloser && encloser->wildcard_child) {
-			node = encloser->wildcard_child;
+		if (node == NULL && encloser
+		    && knot_node_has_wildcard_child(encloser)) {
+			/* Find wildcard child in the zone. */
+			node = knot_zone_contents_find_wildcard_child(zone,
+			                                              encloser);
+			assert(node != NULL);
 		}
 
 		rr_data->additional[i] = (knot_node_t *)node;
@@ -200,11 +204,14 @@ static int adjust_pointers(knot_node_t **tnode, void *data)
 		args->first_node = node;
 	}
 
+	// clear Removed NSEC flag so that no relicts remain
+	knot_node_clear_removed_nsec(node);
+
 	// check if this node is not a wildcard child of its parent
 
 	if (knot_dname_is_wildcard(knot_node_owner(node))) {
 		assert(knot_node_parent(node) != NULL);
-		knot_node_set_wildcard_child(knot_node_get_parent(node), node);
+		knot_node_set_wildcard_child(knot_node_get_parent(node));
 	}
 
 	// set flags (delegation point, non-authoritative)
@@ -551,7 +558,7 @@ dbg_zone_exec_detail(
 
 		// check if the node is not wildcard child of the parent
 		if (knot_dname_is_wildcard(knot_node_owner(node))) {
-			knot_node_set_wildcard_child(zone->apex, node);
+			knot_node_set_wildcard_child(zone->apex);
 		}
 	} else {
 		while (parent != NULL &&
@@ -575,7 +582,7 @@ dbg_zone_exec_detail(
 			/* Update node pointers. */
 			knot_node_set_parent(node, next_node);
 			if (knot_dname_is_wildcard(knot_node_owner(node))) {
-				knot_node_set_wildcard_child(next_node, node);
+				knot_node_set_wildcard_child(next_node);
 			}
 
 			++zone->node_count;
@@ -1119,6 +1126,20 @@ const knot_node_t *knot_zone_contents_apex(
 
 /*----------------------------------------------------------------------------*/
 
+const knot_node_t *knot_zone_contents_find_wildcard_child(
+                const knot_zone_contents_t *contents, const knot_node_t *parent)
+{
+	if (contents == NULL || parent == NULL || parent->owner == NULL) {
+		return NULL;
+	}
+
+	knot_dname_t wildcard[KNOT_DNAME_MAXLEN] = { 0x01, '*' };
+	knot_dname_to_wire(wildcard + 2, parent->owner, KNOT_DNAME_MAXLEN - 2);
+	return knot_zone_contents_find_node(contents, wildcard);
+}
+
+/*----------------------------------------------------------------------------*/
+
 static int knot_zone_contents_adjust_nodes(knot_zone_tree_t *nodes,
                                            knot_zone_adjust_arg_t *adjust_arg,
                                            knot_zone_tree_apply_cb_t callback)
diff --git a/src/knot/zone/zone-contents.h b/src/knot/zone/zone-contents.h
index 4331a98451d340da117c68dcaf1b96d14133423f..0233e4b778949b98cf92aaa8e83f9f862dbc8477 100644
--- a/src/knot/zone/zone-contents.h
+++ b/src/knot/zone/zone-contents.h
@@ -199,6 +199,9 @@ int knot_zone_contents_find_nsec3_for_name(
 const knot_node_t *knot_zone_contents_apex(
 	const knot_zone_contents_t *contents);
 
+const knot_node_t *knot_zone_contents_find_wildcard_child(
+               const knot_zone_contents_t *contents, const knot_node_t *parent);
+
 /*!
  * \brief Sets parent and previous pointers and node flags. (cheap operation)
  *        For both normal and NSEC3 tree