go53 is a young, fast-moving authoritative DNS server written in Go — API-driven, container-native, and built so operators can see exactly what their nameserver is doing. 0.79.1 is a small release with a big warning label: it fixes two critical bugs. If you serve any TXT or SPF record longer than 255 bytes — and a single 2048-bit DKIM key already crosses that line — upgrade every node as soon as you can. Those records are currently invisible to the internet.
Here's what happened and why it matters.
The headline: long TXT/SPF records were being dropped (#52)
On the wire, a DNS TXT record isn't one string — it's a sequence of character-strings, each capped at 255 bytes. go53's query path was emitting the whole value as a single character-string. Anything longer than 255 bytes couldn't be packed, so the entire response failed to serialize and go53 answered with… nothing. No UDP reply, no TCP reply — which every resolver upstream reports as SERVFAIL.
The most common victim is a 2048-bit DKIM key, whose record is 400-plus bytes:
$ dig +short TXT may2025._domainkey.example.org
;; connection timed out; no servers could be reached # SERVFAIL upstream
1024-bit DKIM keys (under 255 bytes) worked perfectly, which is exactly why this stayed hidden — the failure only shows up once you rotate to a 2048-bit key or publish a long SPF / verification / DMARC record. The practical impact is severe: affected records simply don't resolve, so DKIM, SPF, and DMARC alignment break for those domains, and mail starts failing authentication.
The fix splits long TXT/SPF values into ≤255-byte character-strings on the serve path, using the same splitter as the zone-build and DNSSEC-signing paths — so serve output and existing RRSIGs always agree, and signatures keep validating. The split is precomputed on write, so there's no per-query cost in the common case. (The bug was a packing failure in the record itself; it had nothing to do with DNSSEC.)
Distributed mode: deletes that wouldn't die (#53)
If you run go53 as a cluster, this one bit you quietly. The HTTP layer handed the raw zone from the URL (example.org, no trailing dot) to the replication path, while storage and the Merkle tree key everything under the FQDN form (example.org., with the dot). Two things fell out of that mismatch:
- Every record add returned 500 stored record not found after add. The write actually succeeded and still replicated via anti-entropy, which masked the fault — but the API was reporting failure on every call.
- Record deletes were resurrected. The delete tombstone was keyed under the wrong zone, so Merkle anti-entropy still saw the record on peer nodes and pulled it back. Deletes never converged.
0.79.1 canonicalizes the zone to its FQDN form before any store access or event emission, so replicated upserts and delete tombstones line up with the keys already in the store. A defensive normalization in the store layer bridges a missing-or-extra trailing dot as well.
Am I affected?
- You serve any TXT or SPF record over 255 bytes — a single 2048-bit DKIM key qualifies. → #52. Upgrade now.
- You run a cluster and see 500 on record writes, or deleted records coming back a few seconds later. → #53.
Quick check, per zone:
dig +tcp TXT <selector>._domainkey.<zone> # SERVFAIL / timeout on a 2048-bit key = affected
Upgrade
There is no data migration and no config change — the on-disk format is unchanged. Upgrade the binary or image, restart, and previously-SERVFAILing records answer immediately; in a cluster, deletes finally converge.
From source
git fetch --tags && git checkout v0.79.1
go build -o go53-server ./cmd/server
Prebuilt binaries for Linux, macOS, and Windows (amd64/arm64) and container images are on the 0.79.1 release page (https://github.com/TenforwardAB/go53/releases/tag/v0.79.1). Upgrade every node — a mixed cluster still has old nodes dropping long records and resurrecting deletes.
Both fixes started life as issues (#52 (https://github.com/TenforwardAB/go53/issues/52), #53 (https://github.com/TenforwardAB/go53/issues/53)) — if you hit a rough edge, file one. Kick the tires at https://demo.go53.eu, and the project lives at https://go53.eu.