All Use Cases

Private Feature Configuration over DNS

Read small configuration values through an encrypted DNS transport with a namespace-scoped query token.

The Problem

Applications often need a small configuration document without adding another proprietary client protocol.

The Solution

Store a value of up to 2,586 decoded bytes through the REST API, mint an opaque namespace query token, and read the record over DoH or DoT. Private answers use DNS RR TTL 0 even when the TXT envelope retains a nonzero configured ttl hint.

Key Benefits

  • Standard DNS and HTTPS transports
  • Opaque token bound to one namespace
  • Uniform REFUSED response for authorization failures
  • REST API remains the system of record for writes

Use Cases

Runtime configuration

Distribute a small JSON document to clients that can make DNS queries.

get.auth-rdbq<52>.config.your-namespace.v1.resolvedb.net

Read-only demonstration

Use the operator-managed Hooli fixtures to test parsing without a token.

get.dark-mode.flags.hooli.v1.resolvedb.net

Security Pattern

auth-rdbqNamespace Query Token

Opaque bearer token returned once, stored as a digest, and authorized for one private namespace.

Try It Live

Live DNS Query
dig TXT
Query breakdown:
operation:getparams:auth-rdbq<52>resource:confignamespace:your-namespaceversion:v1

Code Examples

Terminal
# Query a private hosted record over DoT.
export RDBQ='rdbq...'
kdig +tls-ca +tls-hostname=dot.resolvedb.io @dot.resolvedb.io \
  TXT "get.auth-${RDBQ}.config.your-namespace.v1.resolvedb.net"
Python
import base64
import json
import os
import dns.message
import dns.query

token = os.environ["RDBQ"]
name = f"get.auth-{token}.config.your-namespace.v1.resolvedb.net"
query = dns.message.make_query(name, "TXT")
response = dns.query.https(query, "https://doh.resolvedb.io/dns-query")
record = next(iter(response.answer[0]))
txt = b"".join(record.strings).decode("utf-8")
metadata_text, payload = txt.split(";d=", 1)
metadata = dict(field.split("=", 1) for field in metadata_text.split(";"))
if metadata.get("e") == "b64":
    payload = base64.b64decode(payload).decode("utf-8")
config = json.loads(payload)
JavaScript
const token = process.env.RDBQ
const name = `get.auth-${token}.config.your-namespace.v1.resolvedb.net`
const url = `https://doh.resolvedb.io/resolve?name=${encodeURIComponent(name)}&type=TXT`
const response = await fetch(url)
const dns = await response.json()
const chunks = dns.Answer[0].data.match(/"(?:\\.|[^"\\])*"/g) ?? []
const txt = chunks.map((chunk) => JSON.parse(chunk)).join('')
const marker = ';d='
const index = txt.indexOf(marker)
const metadata = Object.fromEntries(
  txt.slice(0, index).split(';').map((field) => field.split('=', 2)),
)
let payload = txt.slice(index + marker.length)
if (metadata.e === 'b64') payload = Buffer.from(payload, 'base64').toString('utf8')
const config = JSON.parse(payload)
Go
token := os.Getenv("RDBQ")
name := fmt.Sprintf("get.auth-%s.config.your-namespace.v1.resolvedb.net", token)
endpoint := "https://doh.resolvedb.io/resolve?name=" + url.QueryEscape(name) + "&type=TXT"
response, err := http.Get(endpoint)
if err != nil { log.Fatal(err) }
defer response.Body.Close()
var dnsResponse struct { Answer []struct { Data string } }
if err := json.NewDecoder(response.Body).Decode(&dnsResponse); err != nil { log.Fatal(err) }
rr, err := dns.NewRR("example. 0 IN TXT " + dnsResponse.Answer[0].Data)
if err != nil { log.Fatal(err) }
txt := strings.Join(rr.(*dns.TXT).Txt, "")
parts := strings.SplitN(txt, ";d=", 2)
if len(parts) != 2 { log.Fatal("missing UQRP data") }
metadata := map[string]string{}
for _, field := range strings.Split(parts[0], ";") {
    pair := strings.SplitN(field, "=", 2)
    if len(pair) == 2 { metadata[pair[0]] = pair[1] }
}
payload := []byte(parts[1])
if metadata["e"] == "b64" {
    payload, err = base64.StdEncoding.DecodeString(parts[1])
    if err != nil { log.Fatal(err) }
}
var config map[string]any
if err := json.Unmarshal(payload, &config); err != nil { log.Fatal(err) }

Comparison

FeatureResolveDBAlternative
Read transportDNS, DoH, or DoTApplication-specific HTTP client
Write transportREST APIApplication-specific API
Private cachingDNS RR TTL 0Application-defined
Maximum decoded value2,586 bytesVaries

Frequently Asked Questions

Are private feature flags cached globally?

No. Every authenticated private answer has DNS RR TTL 0. The TXT envelope may still show the record's configured ttl hint; clients must not treat that hint as permission to cache.

Can I use a Rails session JWT in the query?

No. Production DNS authorization accepts only the namespace rdbq token. Customer JWTs and API keys are REST-only.

How are values updated?

Create or update records through the dashboard or REST API. Writes replicate to the DNS fleet through the transactional outbox.

Ready to get started?

Create an account and start storing data in under a minute.