diff --git a/lib/dns/adb.c b/lib/dns/adb.c
index a2800226d1..8df418d189 100644
--- a/lib/dns/adb.c
+++ b/lib/dns/adb.c
@@ -440,6 +440,7 @@ log_quota(dns_adbentry_t *entry, const char *fmt, ...) ISC_FORMAT_PRINTF(2, 3);
 #define FIND_GLUEOK(fn)		(((fn)->options & DNS_ADBFIND_GLUEOK) != 0)
 #define FIND_HAS_ADDRS(fn)	(!ISC_LIST_EMPTY((fn)->list))
 #define FIND_RETURNLAME(fn)	(((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)
+#define FIND_NOFETCH(fn)	(((fn)->options & DNS_ADBFIND_NOFETCH) != 0)
 
 /*
  * These are currently used on simple unsigned ints, so they are
@@ -3234,7 +3235,9 @@ dns_adb_createfind(dns_adb_t *adb, isc_task_t *task, isc_taskaction_t action,
 	} else {
 		have_address = false;
 	}
-	if (wanted_fetches != 0 && !(FIND_AVOIDFETCHES(find) && have_address)) {
+	if (wanted_fetches != 0 && !(FIND_AVOIDFETCHES(find) && have_address) &&
+	    !FIND_NOFETCH(find))
+	{
 		/*
 		 * We're missing at least one address family.  Either the
 		 * caller hasn't instructed us to avoid fetches, or we don't
diff --git a/lib/dns/include/dns/adb.h b/lib/dns/include/dns/adb.h
index 5895b5db3a..724f9b001a 100644
--- a/lib/dns/include/dns/adb.h
+++ b/lib/dns/include/dns/adb.h
@@ -205,6 +205,10 @@ struct dns_adbfind {
  *      lame for this query.
  */
 #define DNS_ADBFIND_OVERQUOTA 0x00000400
+/*%
+ *	Don't perform a fetch even if there are no address records available.
+ */
+#define DNS_ADBFIND_NOFETCH 0x00000800
 
 /*%
  * The answers to queries come back as a list of these.
diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c
index 645a3e12cb..7252b17dfa 100644
--- a/lib/dns/resolver.c
+++ b/lib/dns/resolver.c
@@ -183,6 +183,14 @@
 #define DEFAULT_MAX_QUERIES 75
 #endif /* ifndef DEFAULT_MAX_QUERIES */
 
+/*
+ * After NS_FAIL_LIMIT attempts to fetch a name server address,
+ * if the number of addresses in the NS RRset exceeds NS_RR_LIMIT,
+ * stop trying to fetch, in order to avoid wasting resources.
+ */
+#define NS_FAIL_LIMIT 4
+#define NS_RR_LIMIT   5
+
 /* Number of hash buckets for zone counters */
 #ifndef RES_DOMAIN_BUCKETS
 #define RES_DOMAIN_BUCKETS 523
@@ -3465,7 +3473,7 @@ sort_finds(dns_adbfindlist_t *findlist, unsigned int bias) {
 static void
 findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
 	 unsigned int options, unsigned int flags, isc_stdtime_t now,
-	 bool *overquota, bool *need_alternate) {
+	 bool *overquota, bool *need_alternate, unsigned int *no_addresses) {
 	dns_adbaddrinfo_t *ai;
 	dns_adbfind_t *find;
 	dns_resolver_t *res;
@@ -3562,6 +3570,9 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
 			{
 				*need_alternate = true;
 			}
+			if (no_addresses != NULL) {
+				(*no_addresses)++;
+			}
 		} else {
 			if ((find->options & DNS_ADBFIND_OVERQUOTA) != 0) {
 				if (overquota != NULL) {
@@ -3616,6 +3627,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
 	dns_rdata_ns_t ns;
 	bool need_alternate = false;
 	bool all_spilled = true;
+	unsigned int no_addresses = 0;
 
 	FCTXTRACE5("getaddresses", "fctx->depth=", fctx->depth);
 
@@ -3792,8 +3804,13 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
 			continue;
 		}
 
+		if (no_addresses > NS_FAIL_LIMIT &&
+		    dns_rdataset_count(&fctx->nameservers) > NS_RR_LIMIT)
+		{
+			stdoptions |= DNS_ADBFIND_NOFETCH;
+		}
 		findname(fctx, &ns.name, 0, stdoptions, 0, now, &overquota,
-			 &need_alternate);
+			 &need_alternate, &no_addresses);
 
 		if (!overquota) {
 			all_spilled = false;
@@ -3818,7 +3835,7 @@ fctx_getaddresses(fetchctx_t *fctx, bool badcache) {
 			if (!a->isaddress) {
 				findname(fctx, &a->_u._n.name, a->_u._n.port,
 					 stdoptions, FCTX_ADDRINFO_FORWARDER,
-					 now, NULL, NULL);
+					 now, NULL, NULL, NULL);
 				continue;
 			}
 			if (isc_sockaddr_pf(&a->_u.addr) != family) {
@@ -4264,16 +4264,14 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
 		return;
 	}
 
-	if (dns_name_countlabels(&fctx->domain) > 2) {
-		result = isc_counter_increment(fctx->qc);
-		if (result != ISC_R_SUCCESS) {
-			isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
-				      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
-				      "exceeded max queries resolving '%s'",
-				      fctx->info);
-			fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
-			return;
-		}
+	result = isc_counter_increment(fctx->qc);
+	if (result != ISC_R_SUCCESS) {
+		isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+			      DNS_LOGMODULE_RESOLVER, ISC_LOG_DEBUG(3),
+			      "exceeded max queries resolving '%s'",
+			      fctx->info);
+		fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+		return;
 	}
 
 	fctx_increference(fctx);
