Skip to main content

On This Page

How Sliplane Built a Custom DNS Server in Go to Solve Propagation Latency

3 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

How We Built Our Own DNS Server

Jonas Scholz and the Sliplane team replaced their managed DNS provider with a custom Go-based server to bypass a 10,000-record limit. This system dropped record propagation times from 90 minutes to just a few seconds.

Why This Matters

In high-growth PaaS environments, managed DNS providers often impose rigid record caps or suffer from significant API-to-nameserver propagation delays that disrupt user experience. By adopting the hidden primary pattern and utilizing standard protocols like AXFR and IXFR, engineers can achieve infrastructure independence and sub-second scaling without the overhead of ‘contact sales’ pricing models.

This architecture proves that standard database features like Postgres LISTEN/NOTIFY can effectively replace complex message queues for low-volume infrastructure events. It highlights the technical reality that standard RFC-compliant protocols allow for building highly specialized, internal tools that outperform generic managed services at scale.

Key Insights

  • Sliplane reached a 10,000-record hard cap on Hetzner DNS, which would have been exceeded within weeks due to linear growth per service (2026).
  • Managed DNS API propagation can take up to 90 minutes, creating a ‘broken’ experience for users deploying new services in a PaaS environment.
  • The hidden primary pattern uses a private authoritative server to push zone data to public secondaries, avoiding the need for anycast or redundant global deployments.
  • Postgres functions as a lightweight event bus using pg_notify(‘dns_zone_changed’, ”), handling zone change volumes that occur a few times per minute.
  • Implementing IXFR (RFC 1995) is essential because some secondary providers, like Hetzner Robot, do not always fall back cleanly to full AXFR transfers.
  • The sliplane-dns server uses the miekg/dns Go library to build zones and serve them via TCP-based AXFR transfers.

Working Examples

A minimal Go DNS server implementation that serves a hardcoded zone for example.com via AXFR.

package main
import (
"context"
"log"
"net/netip"
"codeberg.org/miekg/dns"
"codeberg.org/miekg/dns/rdata"
)
func main() {
soa := &dns.SOA{
Hdr: dns.Header{Name: "example.com.", TTL: 3600, Class: dns.ClassINET},
SOA: rdata.SOA{Ns: "ns1.example.com.", Mbox: "admin.example.com.", Serial: 1},
}
records := []dns.RR{
soa,
&dns.A{
Hdr: dns.Header{Name: "app.example.com.", TTL: 300, Class: dns.ClassINET},
A: rdata.A{Addr: netip.MustParseAddr("1.2.3.4")},
},
soa,
}
mux := dns.NewServeMux()
mux.HandleFunc("example.com.", func(_ context.Context, w dns.ResponseWriter, r *dns.Msg) {
r.Unpack()
w.Hijack()
env := make(chan *dns.Envelope, len(records))
for _, rr := range records {
env <- &dns.Envelope{Answer: []dns.RR{rr}}
}
close(env)
dns.NewClient().TransferOut(w, r, env)
w.Close()
})
srv := dns.NewServer()
srv.Addr = ":5553"
srv.Net = "tcp"
srv.Handler = mux
log.Fatal(srv.ListenAndServe())
}

Practical Applications

  • Use Case: PaaS platforms requiring a managed subdomain for every user service can use hidden primaries to maintain thousands of A/AAAA records without per-record provider fees.
  • Pitfall: Failing to implement IXFR (Incremental Zone Transfer) can lead to stale records if the secondary nameserver does not reliably fall back to AXFR.
  • Use Case: Organizations with strict data residency requirements (e.g., EU-only) can use this pattern to keep primary records on internal infrastructure while using regional secondaries.
  • Pitfall: Migrating nameservers requires a Saturday night cutover window due to NS record caching; cached old records will return stale data until the TTL expires.

References:

Continue reading

Next article

Actools: A CLI-Driven Drupal 11 Installer with Automated Security Auditing

Related Content