diff --git a/src/knot/dnssec/nsec-chain.c b/src/knot/dnssec/nsec-chain.c
index cfaa609c77b03033c4914c774a274f3726f36577..38f112966adb7bef2545cf52e5c430dc4651ef61 100644
--- a/src/knot/dnssec/nsec-chain.c
+++ b/src/knot/dnssec/nsec-chain.c
@@ -401,6 +401,19 @@ int nsec_check_new_connects(zone_tree_t *tree, nsec_chain_iterate_data_t *data)
 	return zone_tree_apply(tree, nsec_check_prev_next, data);
 }
 
+static int check_subtree_optout(zone_node_t *node, void *ctx)
+{
+	bool *res = ctx;
+	if ((node->flags & NODE_FLAGS_NONAUTH) || !*res) {
+		return KNOT_EOK;
+	}
+	if (node_nsec3_get(node) != NULL &&
+	    node_rdataset(node_nsec3_get(node), KNOT_RRTYPE_NSEC3) != NULL) {
+		*res = false;
+	}
+	return KNOT_EOK;
+}
+
 static int check_nsec_bitmap(zone_node_t *node, void *ctx)
 {
 	nsec_chain_iterate_data_t *data = ctx;
@@ -419,6 +432,13 @@ static int check_nsec_bitmap(zone_node_t *node, void *ctx)
 	}
 	bool may_no_nsec = (data->nsec3_params != NULL && !(node->flags & NODE_FLAGS_SUBTREE_AUTH));
 	knot_rdataset_t *nsec = node_rdataset(nsec_node, data->nsec_type);
+	if (may_no_nsec && nsec == NULL) {
+		int ret = zone_tree_sub_apply(data->update->new_cont->nodes, node->owner,
+		                              true, check_subtree_optout, &may_no_nsec);
+		if (ret != KNOT_EOK) {
+			return ret;
+		}
+	}
 	if ((nsec == NULL || nsec->count != 1) && !shall_no_nsec && !may_no_nsec) {
 		data->update->validation_hint.node = (nsec_node == NULL ? node->owner : nsec_node->owner);
 		data->update->validation_hint.rrtype = KNOT_RRTYPE_ANY;
diff --git a/tests-extra/tests/dnssec/validate/data/optout.ent.zone b/tests-extra/tests/dnssec/validate/data/optout.ent.zone
new file mode 100644
index 0000000000000000000000000000000000000000..b3e8b969c1a021dbcbd94ef8f912a22ef18ca4f1
--- /dev/null
+++ b/tests-extra/tests/dnssec/validate/data/optout.ent.zone
@@ -0,0 +1,80 @@
+; File written on Tue Aug 31 18:50:37 2021
+; dnssec_signzone version 9.16.8-Ubuntu
+optout.ent.		3600	IN SOA	a.optout.ent. a.optout.ent. (
+					1000000001 ; serial
+					10800      ; refresh (3 hours)
+					10         ; retry (10 seconds)
+					1209600    ; expire (2 weeks)
+					7200       ; minimum (2 hours)
+					)
+			3600	RRSIG	SOA 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					ipEvc00KUrW66efVnH32XGVnWblmQHWKyqf3
+					5EB6jMI6SVqmqfYaL0o9hahKOeib1OP14BPy
+					NN0aUmiNtEX+iw== )
+			3600	NS	a.optout.ent.
+			3600	RRSIG	NS 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					lnElW2h0idPtUIFmPVTi5D1biG9SuEwGd08R
+					ANEVC1JF0Cz7nBkqw7s1S3QNRVVFXw1eqi5w
+					aHoprR/YHbwr4g== )
+			3600	MX	10 a.optout.ent.
+			3600	RRSIG	MX 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					k/kNDfVFcrP9/3/CWoI0VK938i0GoWXsxnOc
+					dzWjp1seFKVRJqsj3xRRqdlyV6Zikh9/Y01t
+					Vl4ihxxzs5jj5A== )
+			3600	DNSKEY	257 3 13 (
+					JxNLxVlreytQBDK6mG44UQ1//gB5uW1pgEk3
+					hC1mUHaa9qdXUOuoEx2tjyqmC7Rw/G+8IVpH
+					C7Zp6GC6xvdhJw==
+					) ; KSK; alg = ECDSAP256SHA256 ; key id = 6971
+			3600	RRSIG	DNSKEY 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					n/Oz/yb6x24pAxgdrUfSu5AtJdVqRPnzsN39
+					2WbWsASaMPGvFqVuwalN69+qoKVVI72zxKKI
+					lfOs98fN5vFRWw== )
+			0	NSEC3PARAM 1 0 10 484E7FFF154B5357
+			0	RRSIG	NSEC3PARAM 13 2 0 (
+					20601231235959 20210831155037 6971 optout.ent.
+					mfS0OsUnl8WTKJAcNzDYXxmMKjrVhwQLhSak
+					TgJxDxKpnuVIWYq6+8aX4xWLp/b5cN/b99Ws
+					Ji0zdZ+amZwMaA== )
+deleg.ent.optout.ent.	3600	IN NS	out-of-bailiwick.example.
+8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 (
+					9SE9KJAM42S8ACFVJNU1QRVABUK9O20T
+					NS SOA MX RRSIG DNSKEY NSEC3PARAM )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					Ps7x9+9H56bkWb9rTOgzDat4ofnuLEHkA/TH
+					5rT/XE3SShLLth6uDIQq8mQjwuTdK/kQjekm
+					0ZNAAm9sqcYVZg== )
+a.optout.ent.		3600	IN A	1.2.3.4
+			3600	RRSIG	A 13 3 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					lVnzQ/IBtihiTWZZy62+9usJe6J475lU2Bbr
+					EctWkqotdGCks1XZT5g8R97YX6Ku2rpnsfKh
+					Ong6tdbBhKDMoA== )
+CEP7K90BHDB9DJ525KIG0325P07HAK7R.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 (
+					KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3
+					A RRSIG )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					NVXZDgzlq9Mp/bBAZ5uJYvgGOb8liEpIeGYn
+					hNF+ocC4Mg+IDauCreqPdwL3uX2fJTD7TO2t
+					JISmliby/QJmIQ== )
+9SE9KJAM42S8ACFVJNU1QRVABUK9O20T.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 (
+					CEP7K90BHDB9DJ525KIG0325P07HAK7R )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					/C1aqFdx57ObTiz4nQVDrDRbSFgVxCeJT3PR
+					KEp3MmspTC6MTikLvLAyETnrLuaIWggtx0x1
+					f2kwjpZcbKnMZg== )
+KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 (
+					8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2
+					NS )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					bpSSNo7+Bz6f3UMM/756LVSYKGIf6FlfBK5E
+					V98AbR8Mg29IXOt9Fq5vgegm2FVvlgtgppl2
+					ewViHCEBZAuHSg== )
diff --git a/tests-extra/tests/dnssec/validate/data/optout.ent.zone.2 b/tests-extra/tests/dnssec/validate/data/optout.ent.zone.2
new file mode 100644
index 0000000000000000000000000000000000000000..0a201527487d76056a19fbf3137eb9fd2d748dbd
--- /dev/null
+++ b/tests-extra/tests/dnssec/validate/data/optout.ent.zone.2
@@ -0,0 +1,73 @@
+; File written on Tue Aug 31 18:50:37 2021
+; dnssec_signzone version 9.16.8-Ubuntu
+optout.ent.		3600	IN SOA	a.optout.ent. a.optout.ent. (
+					1000000003 ; serial
+					10800      ; refresh (3 hours)
+					10         ; retry (10 seconds)
+					1209600    ; expire (2 weeks)
+					7200       ; minimum (2 hours)
+					)
+			3600	RRSIG	SOA 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					cJM4ESx60urM2UquyD+2CnFqBmW/pffMbfUt
+					BPrjNByacG/Tgeoi5PhF/Piv6Ce5Hnni4GBj
+					IoyY5TnGXEceRQ== )
+			3600	NS	a.optout.ent.
+			3600	RRSIG	NS 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					lnElW2h0idPtUIFmPVTi5D1biG9SuEwGd08R
+					ANEVC1JF0Cz7nBkqw7s1S3QNRVVFXw1eqi5w
+					aHoprR/YHbwr4g== )
+			3600	MX	10 a.optout.ent.
+			3600	RRSIG	MX 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					k/kNDfVFcrP9/3/CWoI0VK938i0GoWXsxnOc
+					dzWjp1seFKVRJqsj3xRRqdlyV6Zikh9/Y01t
+					Vl4ihxxzs5jj5A== )
+			3600	DNSKEY	257 3 13 (
+					JxNLxVlreytQBDK6mG44UQ1//gB5uW1pgEk3
+					hC1mUHaa9qdXUOuoEx2tjyqmC7Rw/G+8IVpH
+					C7Zp6GC6xvdhJw==
+					) ; KSK; alg = ECDSAP256SHA256 ; key id = 6971
+			3600	RRSIG	DNSKEY 13 2 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					n/Oz/yb6x24pAxgdrUfSu5AtJdVqRPnzsN39
+					2WbWsASaMPGvFqVuwalN69+qoKVVI72zxKKI
+					lfOs98fN5vFRWw== )
+			0	NSEC3PARAM 1 0 10 484E7FFF154B5357
+			0	RRSIG	NSEC3PARAM 13 2 0 (
+					20601231235959 20210831155037 6971 optout.ent.
+					mfS0OsUnl8WTKJAcNzDYXxmMKjrVhwQLhSak
+					TgJxDxKpnuVIWYq6+8aX4xWLp/b5cN/b99Ws
+					Ji0zdZ+amZwMaA== )
+deleg.ent.optout.ent.	3600	IN NS	out-of-bailiwick.example.
+a.optout.ent.		3600	IN A	1.2.3.4
+			3600	RRSIG	A 13 3 3600 (
+					20601231235959 20210831155037 6971 optout.ent.
+					lVnzQ/IBtihiTWZZy62+9usJe6J475lU2Bbr
+					EctWkqotdGCks1XZT5g8R97YX6Ku2rpnsfKh
+					Ong6tdbBhKDMoA== )
+8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2.optout.ent. 7200 IN NSEC3 1 1 10 484E7FFF154B5357 (
+					CEP7K90BHDB9DJ525KIG0325P07HAK7R
+					NS SOA MX RRSIG DNSKEY NSEC3PARAM )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					siQxUHoSdNgxZ8FLpvR801dRP+fP2lDriEkq
+					4+V2R9r+3SV48dOCfYySMXgxepoG8dlZhGSA
+					G4oCLO5OxETeRg== )
+CEP7K90BHDB9DJ525KIG0325P07HAK7R.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 (
+					KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3
+					A RRSIG )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					NVXZDgzlq9Mp/bBAZ5uJYvgGOb8liEpIeGYn
+					hNF+ocC4Mg+IDauCreqPdwL3uX2fJTD7TO2t
+					JISmliby/QJmIQ== )
+KU64EQGJN5I9HO9GRU9QMA4A333C6MJ3.optout.ent. 7200 IN NSEC3 1 0 10 484E7FFF154B5357 (
+					8DOAQD6MB2N59P3MCI8POSR8RMI2BSH2
+					NS )
+			7200	RRSIG	NSEC3 13 3 7200 (
+					20601231235959 20210831155037 6971 optout.ent.
+					bpSSNo7+Bz6f3UMM/756LVSYKGIf6FlfBK5E
+					V98AbR8Mg29IXOt9Fq5vgegm2FVvlgtgppl2
+					ewViHCEBZAuHSg== )
diff --git a/tests-extra/tests/dnssec/validate/test.py b/tests-extra/tests/dnssec/validate/test.py
index 0a1701279df64846cf4f230a14b837328a4bdb09..ecb383610885d99003e4382eedec3a2fb730750d 100644
--- a/tests-extra/tests/dnssec/validate/test.py
+++ b/tests-extra/tests/dnssec/validate/test.py
@@ -16,7 +16,8 @@ zones_nok = t.zone("missing.nsec.", storage=".") + t.zone("bitmap.nsec.", storag
             t.zone("chain.nsec.", storage=".") + t.zone("rrsig.a.", storage=".") + \
             t.zone("rrsig.nsec.", storage=".") + t.zone("redundant.invalid.rrsig.", storage=".")
 zones_nok3 = t.zone("missing.nsec3", storage=".") + t.zone("bitmap.nsec3.", storage=".") + \
-             t.zone("chain.nsec3.", storage=".") + t.zone("rrsig.nsec3", storage=".")
+             t.zone("chain.nsec3.", storage=".") + t.zone("rrsig.nsec3", storage=".") + \
+             t.zone("optout.ent.", storage=".")
 zones_unsigned = t.zone("example.com.")
 
 zones = zones_ok + zones_ok3 + zones_nok + zones_nok3