Domain Intelligence Platform architecture overview

Distributed crawler, screenshot archive & availability checker for ~540M domains across 1,000+ TLDs · fleet.html · research

What it is

A continuously-running pipeline that observes every new domain registered worldwide (via Certificate Transparency), captures a screenshot, performs WHOIS + DNS enrichment, archives everything to cloud object storage, and exposes the resulting dataset through fifteen specialised search/analytics frontends.

Core capabilities

Scale

540M
domains tracked
~1,057
gTLDs (CZDS)
316M
SLDs in bloom set
28+
VPS workers
~5M
WHOIS rows / hour
~1M
DNS rows / hour
~75K
screenshots / day
15
public dom.to sites

PostgreSQL 18 with the canonical table v3.domains (BIGSERIAL row_id, ~539M rows, fillfactor=50, pg_repacked). Snapshot blobs live in Backblaze B2 behind cdn.backup.im.

Architecture (high level)

                       ┌────────────────────┐
                       │ Certstream firehose│  (CT logs, .com/.in/.io/...)
                       └──────────┬─────────┘
                                  │
                  ┌───────────────┴───────────────┐
                  │ HUB · server25.js · :3000     │   23.137.104.135
                  │ • REST API (200+ endpoints)   │   ├─ Redis 6379  (queues, KV)
                  │ • UI: 30+ HTML dashboards     │   ├─ Bull queues  (legacy)
                  │ • baseline cursor coordinator │   └─ B2 uploader  (cdn.backup.im)
                  └───────────────┬───────────────┘
                                  │       Tailscale mesh (100.x.x.x)
            ┌─────────────────────┼─────────────────────┐
            │                     │                     │
            ▼                     ▼                     ▼
   ┌────────────────┐   ┌────────────────┐    ┌────────────────┐
   │ Fleet workers  │   │ NATS broker    │    │ PostgreSQL v3  │
   │ (Go binary,    │──→│ JetStream      │←───│ database.dom.to│
   │  28+ VPSes)    │   │ RESULTS_PIPELINE    │ partitioned    │
   │ ss/whois/dns   │   │ + KV streams   │    │ FDW shims      │
   │ + "all" lane   │   └────────┬───────┘    └────────────────┘
   └────────────────┘            │                     ▲
                                 ▼                     │
                          ┌──────────────┐             │
                          │ pipeline-svc │─────────────┘
                          │ (Go writer)  │  apply: WHOIS / DNS / SS
                          └──────────────┘
  

All inter-host traffic flows over a Tailscale mesh, so VPSes from any provider can join the fleet in minutes. The hub is the source of truth for configuration; everything else is replaceable.

Data pipeline (one domain end-to-end)

  1. CT log entry         certstream → ct_log_monitor_pg.js
  2. Bucket + dedupe      Redis: ss:active / ss:passive / whois:passive / dns:passive
  3. Worker pull          fleet-worker (Redis BLPOP) or baseline cursor claim
  4. Render               rod-pool Chrome → JPEG @ 375×667 + 1440×900
  5. Enrich               whois (TCP 43 / RDAP) → ParsedWhois
                          zdns (A/AAAA/MX/NS/TXT/SPF/DKIM/CAA/...)
  6. Emit                 NATS publish → RESULTS_PIPELINE stream
  7. Apply                pipeline-svc → bulk UPDATE v3.domains + insert v3.screenshots
  8. Archive blob         B2 upload (a-z sharded) + thumbnail
  9. CDN serve            cdn.backup.im
  

Workloads currently running

ssscreenshot capture, sinkhole-filtered, NSFW-blurred
whoisTLD-aware parsers; allowlist of ~25 registries
dnszdns MULTIPLE mode, batched 100-400 domains
allv0.25 unified lane: whois+dns then OR-gated SS, walks backwards from MAX(row_id)

Work distribution: cursor-as-counter

Workers don't lock or "claim" anything. The cursor is just a monotonic counter.

-- Shape of the row in v3.baseline_cursor (one per workload)
workload    text        -- ss / whois / dns / all
next_row_id bigint      -- the counter
direction   text        -- forward (0→max) or backward (max→0)
range_size  int         -- how many rows per claim

-- claim_next_range() in plpgsql:
SELECT * FROM v3.baseline_cursor WHERE workload=$1 FOR UPDATE;
new_start := next_row_id;
new_end   := new_start + range_size;
UPDATE v3.baseline_cursor SET next_row_id = new_end WHERE ...;
RETURN (new_start, new_end);

Properties

Fleet

Single Go binary (fleet-worker) running on every VPS as a systemd unit. Auto-updates from a release manifest with stable / beta / canary lanes.

Concurrencyauto-sized to host: SS = cores×4, DNS = cores×5, WHOIS = cores
Browser poolgo-rod, headless chromium (snap), 10 browsers per pool, JPEG q80
Result emissionNATS RESULTS_PIPELINE; HTTP /api/baseline/results fallback when NATS down
Local durabilityBadgerDB at /var/lib/fleet-worker (5GB soft, 20GB hard cap)
Control plane:15901 HTTP — /status, /worker/start, /worker/stop, /worker/dns/*
Hub-driven enableRedis key fleet:enable:HOST:WORKLOAD = true|false
Hub-driven concurrencyRedis key fleet:conc:HOST:WORKLOAD overrides YAML
Wave controllerfleet-wide pause / drain modes via Redis fleet:pause:_all

Provider mix (representative)

DeluxHost · CycloneServers · Hetzner · DigitalOcean · Berohost · Solidvps · Advin · Packets · 24fire · Greencloud · Sthosting · ProprUS · DediRock · UltraVPS — usually €1–35/year per host. All on Tailscale; provider-agnostic.

Databases & storage

v3 (canonical)PostgreSQL 18 · 100.73.213.7 · v3.domains 539M rows, partitioned by row_id
Primary (legacy)PostgreSQL · 162.250.191.144 · master_domains, sld_profiles, in_search_domains
SecondaryPostgreSQL · 100.65.217.50 · screenshots_archive (collections, screenshots metadata)
Hub Redis23.137.104.135:6379 · queue lanes, KV, dedup, fleet config
NATS JetStream100.108.236.114:4222 · RESULTS_PIPELINE + KV_fleet_config
Object storeBackblaze B2 · screenshot-archive bucket · cdn.backup.im
Bloom filters710 zone files · 316M SLDs · ~918MB total · in-RAM existence checks
CZDS zone files1,057 gTLDs · 8.2GB compressed · daily download via cron

Public sites (15× dom.to subdomains)

search.dom.tokeyword search across 540M
find.dom.tosingle-domain lookup
in.dom.to.in semantic search
check.dom.tobulk availability
ai.dom.toAI-powered search
mod.dom.tomoderation tools
short.dom.to2-4 letter availability
og.dom.toOpenGraph image gallery
io.dom.to.io domain search
xyz.dom.to.xyz search & sales
scan.dom.toURL link scanner
stats.dom.tosystem statistics
list.dom.todomainer word lists
tools.dom.tomisc utilities

All hosted on a single 512MB IPv6-only VPS (77.76.13.194), nginx-fronted, PM2-managed, ports 3001-3015.

Tech stack

Hub serverNode.js Express, ~40K lines (server25.js)
Fleet workerGo 1.22 single binary, ~30K lines, go-rod, zdns, NATS, BadgerDB
Pipeline writerGo pipeline-svc — bulk UPDATE aggregator (Apr 2026 rolled back, replacement WIP)
DatabasesPostgreSQL 18 + pg_repack + FDW + partitioning
Queue / KVRedis Bull + lists + KV · NATS JetStream for results
Object storeBackblaze B2 behind cdn.backup.im
MeshTailscale — every host is a 100.x.x.x peer, no public ports
Process mgmtPM2 (hub apps) · systemd (fleet-worker, NATS, zdns)
Reverse proxyCloudflare Tunnels → Caddy/nginx
External APIsDynadot · NameSilo · Namecheap · Name.com · OpenProvider · RDAP (via dropseer aggregator)

Evolution highlights

What's next

Generated 2026-05-06 · Dashboards: fleet.html · coverage.html · research.html