All Use Cases

Feature Flags That Cost Nothing at Scale

DNS caching means 10,000 users checking a flag = 1 origin request. Works in shell scripts, cron jobs, edge functions - anywhere DNS works.

The Problem

Feature flag services charge per monthly active user. At 100K users, you're paying thousands per year for what amounts to boolean lookups. Every SDK adds cold-start latency. Shell scripts and edge functions can't easily use traditional flag services. And when you need to kill a feature fast, you're waiting for SDK polling intervals.

The Solution

ResolveDB serves feature flags as DNS TXT records. Simple flags work with just `dig` - no SDK required. For user targeting, the Cohort Token Pattern (CTP) encrypts user context into an opaque token; the server evaluates targeting rules and returns only the results. DNS caching means your flag service handles 1 request per TTL, not 1 per user.

Key Benefits

  • 10,000 users = 1 origin request per TTL (DNS caching multiplier)
  • Zero cold start - DNS resolution is in every language stdlib
  • Works everywhere: bash, cron, edge functions, any language
  • Fixed cost - no per-seat pricing that scales with users

Use Cases

Kill Switches

Disable a broken feature across all services in 30 seconds. No deployment, no SDK update, no coordination. Change the flag, wait for TTL expiry, done.

get.payments-v2.flags.myapp.v1.resolvedb.net → {"enabled":false}

Maintenance Mode

One flag checked by 50 microservices. With traditional flags, that's 50 SDK connections. With ResolveDB, it's one cached DNS response per TTL.

get.maintenance.flags.myapp.v1.resolvedb.net → {"enabled":true,"message":"Back in 10 mins"}

Shell Script & CI/CD Flags

Your deployment script needs to check if a feature is ready. No npm install, no pip install. Just dig.

if dig TXT get.deploy-v2.flags.myapp.v1.resolvedb.net +short | grep -q '"enabled":true'; then deploy_v2; fi

Edge Function Flags

Cloudflare Workers and Lambda@Edge have milliseconds to respond and no persistent state. DNS-over-HTTPS completes before your function cold starts.

fetch("https://dns.google/resolve?name=get.dark-mode.flags.myapp.v1.resolvedb.net&type=TXT")

Gradual Rollouts

Roll out to 10% of users, then 25%, then 50%. CTP tokens encode user tier; server evaluates rollout percentage. Cache-friendly because users in the same tier get the same response.

get.ctp-<encrypted-token>.new-checkout.flags.myapp.v1.resolvedb.net → {"enabled":true}

Security Pattern

ctp-Cohort Token Pattern (CTP)

AES-256-GCM encrypted segment bitmap for user targeting. 5-minute expiry. Server-side rule evaluation - targeting logic never exposed in queries.

Try It Live

Live DNS Query
Query breakdown:
operation:getparams:payments-v2resource:flagsnamespace:myappversion:v1

Code Examples

Terminal
# Kill switch check in deployment script
FLAG=$(dig TXT get.payments-v2.flags.acme.v1.resolvedb.net +short 2>/dev/null)
if echo "$FLAG" | grep -q '"enabled":false'; then
  echo "payments-v2 is disabled, skipping deployment"
  exit 0
fi

# Maintenance mode in cron job
if dig TXT get.maintenance.flags.acme.v1.resolvedb.net +short | grep -q '"enabled":true'; then
  echo "Maintenance mode - skipping batch job"
  exit 0
fi

# Simple flag check (any language with DNS works)
dig TXT get.dark-mode.flags.myapp.v1.resolvedb.net +short
# "v=rdb1;s=ok;f=json;ttl=60;d={\"enabled\":true}"
Python
import dns.resolver
import json

def get_flag(flag_name: str, namespace: str = "myapp") -> dict:
    """Get feature flag - no SDK required."""
    fqdn = f"get.{flag_name}.flags.{namespace}.v1.resolvedb.net"
    answers = dns.resolver.resolve(fqdn, 'TXT')
    response = str(answers[0]).strip('"')
    parts = dict(p.split('=', 1) for p in response.split(';') if '=' in p)
    return json.loads(parts.get('d', '{}'))

# Kill switch check
if not get_flag("payments-v2")["enabled"]:
    print("Feature disabled")
    sys.exit(0)

# With SDK for user targeting (optional)
from resolvedb import ResolveDB
db = ResolveDB(namespace="myapp", secret="your-secret")

# CTP auto-encrypts user context
flags = db.flags.get_for_user("new-checkout", user={
    "id": "user-123", "premium": True, "region": "na"
})
print(f"New checkout: {flags['enabled']}")
JavaScript
import dns from 'dns/promises';

// No SDK required - just DNS
async function getFlag(flagName: string): Promise<{enabled: boolean}> {
  const fqdn = `get.${flagName}.flags.myapp.v1.resolvedb.net`;
  const records = await dns.resolveTxt(fqdn);
  const response = records.flat().join('');
  const match = response.match(/d=(.+?)(?:;|$)/);
  return match ? JSON.parse(match[1]) : { enabled: false };
}

// Edge function (Cloudflare Workers)
async function handleRequest(request: Request) {
  // DoH - works in edge runtime
  const res = await fetch(
    'https://dns.google/resolve?name=get.maintenance.flags.myapp.v1.resolvedb.net&type=TXT'
  );
  const data = await res.json();
  if (data.Answer?.[0]?.data?.includes('"enabled":true')) {
    return new Response('Maintenance mode', { status: 503 });
  }
  // Continue with request...
}
Go
package main

import (
    "encoding/json"
    "net"
    "strings"
)

func getFlag(flagName, namespace string) (map[string]any, error) {
    fqdn := fmt.Sprintf("get.%s.flags.%s.v1.resolvedb.net", flagName, namespace)
    records, err := net.LookupTXT(fqdn)
    if err != nil { return nil, err }

    response := strings.Join(records, "")
    for _, seg := range strings.Split(response, ";") {
        if strings.HasPrefix(seg, "d=") {
            var result map[string]any
            json.Unmarshal([]byte(seg[2:]), &result)
            return result, nil
        }
    }
    return nil, nil
}

// Kill switch check
flag, _ := getFlag("payments-v2", "myapp")
if enabled, ok := flag["enabled"].(bool); !ok || !enabled {
    log.Fatal("Feature disabled")
}

Comparison

FeatureResolveDBAlternative
Cost at 100K MAU~$10/month (fixed)$1,000+/month (per-seat)
10K concurrent users1 origin request/TTL10K SDK connections
Shell script supportNative (dig)REST API workaround
Edge function supportDoH in 1 lineSDK may not work
Cold start latency0ms (DNS in stdlib)50-500ms (SDK init)
Kill switch propagation30-60s (TTL)1-5min (SDK polling)

Frequently Asked Questions

How is this different from LaunchDarkly?

ResolveDB is simpler and cheaper at scale. LaunchDarkly excels at sophisticated targeting (50+ attributes), built-in experimentation, and enterprise compliance. ResolveDB is ideal for simple on/off flags, kill switches, and environments where SDKs don't work (shell scripts, edge functions). At scale, the pricing difference is significant.

What about user targeting?

Use Cohort Token Pattern (CTP) for basic segmentation. The SDK encrypts user attributes (premium, region, tier) into a token. The server evaluates rules and returns results. For sophisticated 50-attribute rules, use a dedicated feature flag service.

What if I need to kill a feature immediately?

Update the flag via API, and it propagates globally within one TTL period (default 60 seconds). For faster propagation during incidents, use a shorter TTL (30s) or implement a local SDK cache bypass.

Can I use this without any SDK?

Absolutely. Simple flags work with just dig or any DNS library. The examples show raw DNS queries. The SDK is optional convenience for response parsing and CTP token generation.

What happens if the app_secret for CTP is compromised?

Rotate the secret immediately via API. Old tokens become invalid (can't decrypt). This is a P0 incident - treat CTP secrets like database credentials. For access control, always combine CTP with JWT authentication.

Ready to get started?

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