Summary
DNS queries currently rebuild dns.RR objects on every lookup from the internal storage representation. This causes unnecessary allocations, parsing, and CPU overhead on the hot query path.
Problem
For common record types such as A records, the lookup path retrieves data from the memory store, interprets map[string]interface{} / []interface{} values, parses IP addresses, allocates new dns.RR objects, and builds new slices for every query.
This work is repeated even though zone data usually changes much less frequently than it is queried.
Proposed solution
Introduce an RRset cache layer keyed by zone, owner name, and RR type.
Example shape:
type CachedRRSet struct {
Records []dns.RR
Version uint64
}
Cache key:
The write path should invalidate or rebuild affected cache entries when records are added, updated, deleted, or when DNSSEC material changes.
The read path should return pre-built []dns.RR whenever possible.
Expected benefits
- Fewer allocations per DNS query
- Lower GC pressure
- Less per-query parsing and object construction
- Higher QPS for common record types
Priority
High
Additional implementation idea
This work could be split into two phases.
Step 1: Typed record storage
Replace dynamic structures such as:
with strongly typed internal representations:
[]types.ARecord
[]types.AAAARecord
This would eliminate a significant amount of type assertions and conversion work while keeping the existing lookup model intact.
Step 2: RRset cache
Introduce a cache of fully constructed:
objects.
Cache entries should be invalidated when records are added, updated, deleted, or when DNSSEC signatures change.
This moves work from the query path to the mutation path and is expected to provide the largest performance improvement.
Summary
DNS queries currently rebuild
dns.RRobjects on every lookup from the internal storage representation. This causes unnecessary allocations, parsing, and CPU overhead on the hot query path.Problem
For common record types such as A records, the lookup path retrieves data from the memory store, interprets
map[string]interface{}/[]interface{}values, parses IP addresses, allocates newdns.RRobjects, and builds new slices for every query.This work is repeated even though zone data usually changes much less frequently than it is queried.
Proposed solution
Introduce an RRset cache layer keyed by zone, owner name, and RR type.
Example shape:
Cache key:
The write path should invalidate or rebuild affected cache entries when records are added, updated, deleted, or when DNSSEC material changes.
The read path should return pre-built
[]dns.RRwhenever possible.Expected benefits
Priority
High
Additional implementation idea
This work could be split into two phases.
Step 1: Typed record storage
Replace dynamic structures such as:
with strongly typed internal representations:
This would eliminate a significant amount of type assertions and conversion work while keeping the existing lookup model intact.
Step 2: RRset cache
Introduce a cache of fully constructed:
[]dns.RRobjects.
Cache entries should be invalidated when records are added, updated, deleted, or when DNSSEC signatures change.
This moves work from the query path to the mutation path and is expected to provide the largest performance improvement.