Custom APIs
ENSDb (SQL)
For special use cases that go beyond what the ENS Omnigraph exposes—you can query the live onchain state of both ENSv1 and ENSv2 directly via SQL.
ENSDb is a bi-directional integration standard for any EnsDbWriter and EnsDbReader implementations to coordinate around the live unified onchain state of ENSv1 and ENSv2 in a carefully-crafted standardized data model within a PostgreSQL database. Because ENSDb builds on Postgres, you can use any language with a Postgres driver—TypeScript, Python, Rust, Go, and more.
We’re building ensdb-cli & ENSDb snapshots so you can pull down a fresh ENSDb in minutes instead of paying for a full historical RPC backfill among many other benefits.
Inspirations for what you can build with ENSDb
Section titled “Inspirations for what you can build with ENSDb”Analytics & Dashboards
CLIs & Developer Tools
Event-Based Engines
Data Pipelines
AI Agents
Example: fetch a Domain by canonical name
Section titled “Example: fetch a Domain by canonical name”Canonical fields (canonical_name, canonical_path, canonical_node, canonical_depth) are
populated on every Domain reachable from the canonical root, across both ENSv1 and ENSv2—query
them uniformly without branching by type.
import { EnsDbReader } from "@ensnode/ensdb-sdk";import { eq } from "drizzle-orm";
const ensDbReader = new EnsDbReader(ensDbConnectionString, ensIndexerSchemaName);const { ensDb, ensIndexerSchema } = ensDbReader;
const [vitalik] = await ensDb .select() .from(ensIndexerSchema.domain) .where(eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth"));SELECT * FROM ensindexer_0.domainsWHERE canonical_name = 'vitalik.eth';Example: count an address’s Domains by type (ENSv1 vs ENSv2)
Section titled “Example: count an address’s Domains by type (ENSv1 vs ENSv2)”import { count, eq } from "drizzle-orm";
const counts = await ensDb .select({ type: ensIndexerSchema.domain.type, count: count() }) .from(ensIndexerSchema.domain) .where(eq(ensIndexerSchema.domain.ownerId, "0xd8da6bf26964af9d7eed9e03e53415d37aa96045")) .groupBy(ensIndexerSchema.domain.type);SELECT type, count(*) FROM ensindexer_0.domainsWHERE owner_id = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'GROUP BY type;