Examples & Recipes

Real-world use cases with copy-pasteable code examples for ResolveDB.

Try It Live

Experiment with real DNS queries before diving into the examples:

Live DNS Query
Try:
Query breakdown:
operation:getresource:weathernamespace:publicversion:v1

Configuration Storage

Store application configuration accessible via DNS. Perfect for feature flags, environment settings, and dynamic configuration.

Feature Flags

Store feature flags that can be queried from any client without an SDK.

DNS Query:

dig get.features.myapp.v1.resolvedb.net TXT +short

Expected Response:

v=rdb1;s=ok;t=data;f=json;ttl=300;d={"dark_mode":true,"beta_users":false,"max_uploads":10}

JavaScript:

const dns = require('dns').promises;

async function getFeatureFlags() {
  const records = await dns.resolveTxt('get.features.myapp.v1.resolvedb.net');
  const response = records[0].join('');
  const data = response.match(/d=(.+)$/)?.[1];
  return JSON.parse(data);
}

// Usage
const flags = await getFeatureFlags();
if (flags.dark_mode) {
  enableDarkMode();
}

Python:

import dns.resolver
import json
import re

def get_feature_flags():
    answers = dns.resolver.resolve('get.features.myapp.v1.resolvedb.net', 'TXT')
    response = str(answers[0]).strip('"')
    match = re.search(r'd=(.+)$', response)
    if match:
        return json.loads(match.group(1))
    return {}

# Usage
flags = get_feature_flags()
if flags.get('dark_mode'):
    enable_dark_mode()

Environment Configuration

Different configurations per environment using namespaced queries.

# Production config
dig get.config.myapp-prod.v1.resolvedb.net TXT +short

# Staging config
dig get.config.myapp-staging.v1.resolvedb.net TXT +short

# Development config
dig get.config.myapp-dev.v1.resolvedb.net TXT +short

Public Data APIs

Access public data sources via DNS queries. Data is cached at the DNS layer for ultra-fast global access.

Weather Data

Query current weather by providing an explicit city name or coordinates.

Privacy by Design: Location must be explicitly provided in the query. The server never infers location from the client's IP address.

DNS Query:

# By city name (explicit parameter)
dig get.city-newyork.weather.public.v1.resolvedb.net TXT +short

# By coordinates (explicit parameters)
# Format: lat-<lat>.lon-<lon> where decimals use 'd' separator
dig get.lat-40d7128.lon--74d0060.weather.public.v1.resolvedb.net TXT +short

# Or use Base64 encoded JSON for coordinates
# {"lat":40.7128,"lon":-74.0060}
dig get.b64-eyJsYXQiOjQwLjcxMjgsImxvbiI6LTc0LjAwNjB9.weather.public.v1.resolvedb.net TXT +short

Expected Response:

v=rdb1;s=ok;t=data;f=json;ttl=300;d={"city":"New York","temp":72,"unit":"F","conditions":"Partly Cloudy"}

curl + jq:

# Using DNS-over-HTTPS for JSON output
curl -s "https://dns.google/resolve?name=get.city-newyork.weather.public.v1.resolvedb.net&type=TXT" \
  | jq -r '.Answer[0].data' \
  | sed 's/.*d=//' \
  | jq .

JavaScript:

async function getWeather(city) {
  const dns = require('dns').promises;
  // Explicit city parameter in query
  const query = `get.city-${city.toLowerCase()}.weather.public.v1.resolvedb.net`;
  const records = await dns.resolveTxt(query);
  const response = records[0].join('');
  const data = response.match(/d=(.+)$/)?.[1];
  return JSON.parse(data);
}

const weather = await getWeather('newyork');
console.log(`${weather.city}: ${weather.temp}${weather.unit}`);
// Output: New York: 72F

Stock Prices

Real-time stock quotes with short TTL for frequently updating data.

DNS Query:

dig get.aapl.stocks.public.v1.resolvedb.net TXT +short
dig get.googl.stocks.public.v1.resolvedb.net TXT +short

Expected Response:

v=rdb1;s=ok;t=data;f=json;ttl=60;d={"symbol":"AAPL","price":185.92,"change":2.34,"percent":1.27}

Python:

import dns.resolver
import json
import re

def get_stock_price(symbol):
    query = f'get.{symbol.lower()}.stocks.public.v1.resolvedb.net'
    answers = dns.resolver.resolve(query, 'TXT')
    response = str(answers[0]).strip('"')
    match = re.search(r'd=(.+)$', response)
    if match:
        return json.loads(match.group(1))
    return None

stock = get_stock_price('AAPL')
print(f"{stock['symbol']}: ${stock['price']} ({stock['change']:+.2f})")
# Output: AAPL: $185.92 (+2.34)

News Headlines

Fetch latest headlines by category.

dig get.tech.headlines.public.v1.resolvedb.net TXT +short
dig get.business.headlines.public.v1.resolvedb.net TXT +short

User Data Storage

Store and retrieve authenticated user data. Requires JWT authentication via the auth- prefix.

User Preferences

Store per-user settings that sync across devices.

Store Preferences (via API):

curl -X POST https://api.resolvedb.io/api/v1/records \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "record": {
      "key": "preferences.user123.v1",
      "data": "eyJ0aGVtZSI6ImRhcmsiLCJsYW5nIjoiZW4iLCJub3RpZnkiOnRydWV9",
      "visibility": "private"
    }
  }'

Retrieve with Authentication:

# JWT token contains user identity
dig get.auth-<jwt_token>.preferences.user123.v1.resolvedb.net TXT +short

JavaScript:

const dns = require('dns').promises;

async function getUserPreferences(userId, jwtToken) {
  const query = `get.auth-${jwtToken}.preferences.${userId}.v1.resolvedb.net`;
  const records = await dns.resolveTxt(query);
  const response = records[0].join('');

  // Check for auth errors
  if (response.includes('s=auth')) {
    throw new Error('Authentication required');
  }

  const data = response.match(/d=(.+)$/)?.[1];
  return JSON.parse(data);
}

// Usage
const prefs = await getUserPreferences('user123', myJwtToken);
console.log(prefs);
// Output: { theme: "dark", lang: "en", notify: true }

Python:

import dns.resolver
import json
import re

def get_user_preferences(user_id, jwt_token):
    query = f'get.auth-{jwt_token}.preferences.{user_id}.v1.resolvedb.net'
    answers = dns.resolver.resolve(query, 'TXT')
    response = str(answers[0]).strip('"')

    # Check for auth errors
    if 's=auth' in response:
        raise Exception('Authentication required')

    match = re.search(r'd=(.+)$', response)
    if match:
        return json.loads(match.group(1))
    return None

prefs = get_user_preferences('user123', my_jwt_token)
print(prefs)
# Output: {'theme': 'dark', 'lang': 'en', 'notify': True}

Large File Handling

DNS TXT records are limited to ~255 bytes per string and ~512 bytes per UDP response. ResolveDB handles larger data through chunking and blob URL fallback.

Chunked Data Retrieval

For data between 512 bytes and 4KB, ResolveDB returns metadata pointing to chunks.

DNS Query:

dig get.largeconfig.myapp.v1.resolvedb.net TXT +short

Chunked Response:

v=rdb1;s=partial;t=multi;chunks=3;total=1536;hash=abc123;d=chunk-0.largeconfig.myapp.v1

JavaScript - Chunk Reassembly:

const dns = require('dns').promises;

async function getLargeData(key, namespace, version) {
  const baseQuery = `get.${key}.${namespace}.${version}.resolvedb.net`;
  const records = await dns.resolveTxt(baseQuery);
  const response = records[0].join('');

  // Check if chunked
  if (response.includes('t=multi')) {
    const chunks = parseInt(response.match(/chunks=(\d+)/)?.[1] || '0');

    // Fetch all chunks in parallel
    const chunkPromises = [];
    for (let i = 0; i < chunks; i++) {
      const chunkQuery = `get.chunk-${i}.${key}.${namespace}.${version}.resolvedb.net`;
      chunkPromises.push(dns.resolveTxt(chunkQuery));
    }

    const chunkResults = await Promise.all(chunkPromises);
    const reassembled = chunkResults
      .map(r => r[0].join(''))
      .map(r => r.match(/d=(.+)$/)?.[1])
      .join('');

    return JSON.parse(reassembled);
  }

  // Small data - return directly
  const data = response.match(/d=(.+)$/)?.[1];
  return JSON.parse(data);
}

Blob URL Fallback

For data larger than 4KB, ResolveDB returns a redirect to a CDN-hosted blob.

DNS Query:

dig get.largefile.myapp.v1.resolvedb.net TXT +short

Redirect Response:

v=rdb1;s=redirect;t=url;ttl=3600;d=https://cdn.resolvedb.cloud/blob/abc123def456

JavaScript - Handle Redirect:

const dns = require('dns').promises;

async function getData(key, namespace, version) {
  const query = `get.${key}.${namespace}.${version}.resolvedb.net`;
  const records = await dns.resolveTxt(query);
  const response = records[0].join('');

  // Check for redirect
  if (response.includes('s=redirect')) {
    const url = response.match(/d=(.+)$/)?.[1];
    // Fetch from CDN
    const blobData = await fetch(url).then(r => r.json());
    return blobData;
  }

  // Direct data
  const data = response.match(/d=(.+)$/)?.[1];
  return JSON.parse(data);
}

Python:

import dns.resolver
import json
import re
import requests

def get_data(key, namespace, version):
    query = f'get.{key}.{namespace}.{version}.resolvedb.net'
    answers = dns.resolver.resolve(query, 'TXT')
    response = str(answers[0]).strip('"')

    # Check for redirect
    if 's=redirect' in response:
        match = re.search(r'd=(.+)$', response)
        if match:
            url = match.group(1)
            return requests.get(url).json()

    # Direct data
    match = re.search(r'd=(.+)$', response)
    if match:
        return json.loads(match.group(1))
    return None

Encrypted Secrets

Store sensitive data with client-side encryption. ResolveDB never sees the plaintext.

AES-256-GCM Encryption

Encrypt data before storing, decrypt after retrieval.

Store Encrypted Secret (via API):

# Client-side: encrypt data before sending
# encrypted = AES-256-GCM(plaintext, key)
# encoded = base64(nonce + ciphertext + tag)

curl -X POST https://api.resolvedb.io/api/v1/records \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "record": {
      "key": "secrets.db-password.prod.v1",
      "data": "<base64_encrypted_data>",
      "encrypted": true
    }
  }'

JavaScript - Encrypt & Store:

const crypto = require('crypto');

// Encryption key (store securely, e.g., in environment or KMS)
const ENCRYPTION_KEY = Buffer.from(process.env.RESOLVEDB_ENCRYPTION_KEY, 'hex');

function encrypt(plaintext) {
  const iv = crypto.randomBytes(12);
  const cipher = crypto.createCipheriv('aes-256-gcm', ENCRYPTION_KEY, iv);

  let encrypted = cipher.update(plaintext, 'utf8');
  encrypted = Buffer.concat([encrypted, cipher.final()]);

  const tag = cipher.getAuthTag();

  // Combine: iv (12) + encrypted + tag (16)
  return Buffer.concat([iv, encrypted, tag]).toString('base64');
}

function decrypt(encryptedBase64) {
  const data = Buffer.from(encryptedBase64, 'base64');

  const iv = data.subarray(0, 12);
  const tag = data.subarray(-16);
  const ciphertext = data.subarray(12, -16);

  const decipher = crypto.createDecipheriv('aes-256-gcm', ENCRYPTION_KEY, iv);
  decipher.setAuthTag(tag);

  let decrypted = decipher.update(ciphertext);
  decrypted = Buffer.concat([decrypted, decipher.final()]);

  return decrypted.toString('utf8');
}

// Store secret
const secret = 'my-database-password';
const encrypted = encrypt(secret);
// Send 'encrypted' to ResolveDB API

// Retrieve and decrypt
const response = await getFromResolveDB('secrets.db-password.prod.v1');
const plaintext = decrypt(response);

Python:

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
import base64

# Encryption key (32 bytes for AES-256)
ENCRYPTION_KEY = bytes.fromhex(os.environ['RESOLVEDB_ENCRYPTION_KEY'])

def encrypt(plaintext: str) -> str:
    aesgcm = AESGCM(ENCRYPTION_KEY)
    nonce = os.urandom(12)
    ciphertext = aesgcm.encrypt(nonce, plaintext.encode(), None)
    # Combine nonce + ciphertext (includes tag)
    return base64.b64encode(nonce + ciphertext).decode()

def decrypt(encrypted_b64: str) -> str:
    data = base64.b64decode(encrypted_b64)
    nonce = data[:12]
    ciphertext = data[12:]

    aesgcm = AESGCM(ENCRYPTION_KEY)
    plaintext = aesgcm.decrypt(nonce, ciphertext, None)
    return plaintext.decode()

# Usage
secret = 'my-database-password'
encrypted = encrypt(secret)
# Store 'encrypted' in ResolveDB

# Later: retrieve and decrypt
plaintext = decrypt(encrypted)

Key Management Patterns

Best practices for managing encryption keys:

  • Environment-specific keys: Use different encryption keys per environment (dev, staging, prod)
  • Key rotation: Store versioned keys, include key version in encrypted data metadata
  • Key derivation: Derive per-record keys from master key using HKDF
  • Cloud KMS: Use AWS KMS, GCP KMS, or Azure Key Vault for key storage

Key Derivation Example:

const crypto = require('crypto');

function deriveKey(masterKey, recordId) {
  return crypto.hkdfSync(
    'sha256',
    masterKey,
    Buffer.from(recordId),
    Buffer.from('resolvedb-encryption'),
    32
  );
}

// Each record gets a unique derived key
const recordKey = deriveKey(masterKey, 'secrets.db-password.prod.v1');

Edge Computing / Serverless

ResolveDB is ideal for serverless environments where cold starts matter. DNS resolution happens outside your function, with data already cached at edge locations.

AWS Lambda

Fetch configuration without HTTP client initialization overhead.

JavaScript (Node.js Runtime):

const dns = require('dns').promises;

// DNS is available immediately - no HTTP client needed
exports.handler = async (event) => {
  // Resolves in ~1-5ms when cached (vs 50-200ms HTTP cold start)
  const records = await dns.resolveTxt('get.config.myapp.v1.resolvedb.net');
  const response = records[0].join('');
  const config = JSON.parse(response.match(/d=(.+)$/)?.[1]);

  // Use config
  const threshold = config.rate_limit || 100;

  return {
    statusCode: 200,
    body: JSON.stringify({ processed: true })
  };
};

Python Runtime:

import dns.resolver
import json
import re

def lambda_handler(event, context):
    # DNS resolution is fast - no connection pooling needed
    answers = dns.resolver.resolve('get.config.myapp.v1.resolvedb.net', 'TXT')
    response = str(answers[0]).strip('"')
    match = re.search(r'd=(.+)$', response)
    config = json.loads(match.group(1)) if match else {}

    # Use config
    threshold = config.get('rate_limit', 100)

    return {
        'statusCode': 200,
        'body': json.dumps({'processed': True})
    }

Cloudflare Workers

Use DNS-over-HTTPS in Workers where native DNS is not available.

export default {
  async fetch(request, env) {
    // Workers don't have native DNS, use DoH
    const dohUrl = 'https://cloudflare-dns.com/dns-query';
    const query = 'get.config.myapp.v1.resolvedb.net';

    const response = await fetch(
      `${dohUrl}?name=${query}&type=TXT`,
      {
        headers: { 'Accept': 'application/dns-json' }
      }
    );

    const data = await response.json();
    const txtRecord = data.Answer?.[0]?.data?.replace(/"/g, '');
    const config = JSON.parse(txtRecord.match(/d=(.+)$/)?.[1]);

    return new Response(JSON.stringify({
      feature_enabled: config.feature_enabled
    }), {
      headers: { 'Content-Type': 'application/json' }
    });
  }
};

Vercel Edge Functions

Lightweight configuration for edge middleware.

import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export async function middleware(request: NextRequest) {
  // Fetch feature flags via DoH (edge has no native DNS)
  const doh = await fetch(
    'https://dns.google/resolve?name=get.flags.myapp.v1.resolvedb.net&type=TXT'
  );
  const data = await doh.json();
  const record = data.Answer?.[0]?.data?.replace(/"/g, '');
  const flags = JSON.parse(record.match(/d=(.+)$/)?.[1]);

  // A/B test based on feature flag
  if (flags.new_checkout && Math.random() < flags.new_checkout_percent) {
    return NextResponse.rewrite(new URL('/checkout-v2', request.url));
  }

  return NextResponse.next();
}

export const config = {
  matcher: '/checkout/:path*'
};

Why DNS is faster for serverless

  • No TCP/TLS handshake (UDP-based)
  • Cached at multiple layers (local, ISP, edge)
  • No connection pooling or keep-alive management
  • Available immediately in cold start (no client init)
  • Sub-millisecond when cached locally

IoT / Embedded

Minimal DNS-only clients for resource-constrained devices. No HTTP stack required, works with any device that can make DNS queries.

Device Configuration

Push configuration to IoT devices via DNS. Devices poll their config periodically using lightweight DNS queries.

DNS Query:

# Device queries its own config by device ID
dig get.config.device-abc123.iot.v1.resolvedb.net TXT +short

Expected Response:

v=rdb1;s=ok;t=data;f=json;ttl=3600;d={"sample_rate":60,"report_interval":300,"firmware":"2.1.0"}

Arduino/ESP32 (C++)

#include <WiFi.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>

WiFiUDP udp;
const char* DNS_SERVER = "8.8.8.8";
const int DNS_PORT = 53;

String dnsQuery(const char* hostname) {
  // Simplified DNS query - use a proper DNS library in production
  byte packet[512];
  int len = buildDnsQuery(packet, hostname, DNS_TYPE_TXT);

  udp.beginPacket(DNS_SERVER, DNS_PORT);
  udp.write(packet, len);
  udp.endPacket();

  int responseLen = waitForResponse(packet, 512, 1000);
  if (responseLen > 0) {
    return parseTxtRecord(packet, responseLen);
  }
  return "";
}

void updateConfig() {
  String deviceId = getDeviceId();
  String query = "get.config." + deviceId + ".iot.v1.resolvedb.net";

  String response = dnsQuery(query.c_str());

  int dataStart = response.indexOf("d=");
  if (dataStart > 0) {
    String jsonData = response.substring(dataStart + 2);

    StaticJsonDocument<256> doc;
    deserializeJson(doc, jsonData);

    int sampleRate = doc["sample_rate"] | 60;
    int reportInterval = doc["report_interval"] | 300;

    applySampleRate(sampleRate);
    applyReportInterval(reportInterval);
  }
}

void loop() {
  updateConfig();
  delay(3600000); // Check hourly (matches TTL)
}

MicroPython (ESP8266/ESP32)

import socket
import ujson
import ure

def dns_query_txt(hostname):
    """Simple TXT record query using system resolver"""
    try:
        import udns  # hypothetical lightweight DNS library
        records = udns.query(hostname, 'TXT')
        return records[0] if records else None
    except Exception as e:
        print(f"DNS error: {e}")
        return None

def get_config():
    device_id = get_device_id()
    hostname = f"get.config.{device_id}.iot.v1.resolvedb.net"

    response = dns_query_txt(hostname)
    if response:
        match = ure.search(r'd=(.+)$', response)
        if match:
            config = ujson.loads(match.group(1))
            return config
    return {}

# Main loop
while True:
    config = get_config()
    sample_rate = config.get('sample_rate', 60)
    set_sample_rate(sample_rate)

    import time
    time.sleep(config.get('ttl', 3600))

Fleet Configuration Distribution

Push updates to groups of devices simultaneously.

# Global config for all devices
dig get.config.global.iot.v1.resolvedb.net TXT +short

# Config by device type
dig get.config.sensor-v2.iot.v1.resolvedb.net TXT +short

# Config by location
dig get.config.warehouse-nyc.iot.v1.resolvedb.net TXT +short

# Individual device override
dig get.config.device-abc123.iot.v1.resolvedb.net TXT +short

Configuration Hierarchy (Device Code):

def get_merged_config():
    """Fetch config with fallback hierarchy"""
    config = {}

    # 1. Start with global defaults
    global_config = query_config('global')
    config.update(global_config)

    # 2. Apply device type overrides
    type_config = query_config(f'sensor-{DEVICE_TYPE}')
    config.update(type_config)

    # 3. Apply location overrides
    location_config = query_config(f'location-{DEVICE_LOCATION}')
    config.update(location_config)

    # 4. Apply device-specific overrides
    device_config = query_config(f'device-{DEVICE_ID}')
    config.update(device_config)

    return config

IoT Advantages

  • Minimal code footprint - DNS is a standard protocol
  • No TLS certificates needed for read-only config
  • Works behind NAT without port forwarding
  • Firewall-friendly (DNS typically allowed)
  • Low power - single UDP packet vs TCP connection