diff --git a/docs/ensnode.io/astro.config.mjs b/docs/ensnode.io/astro.config.mjs
index 25202aaf1..9ed94d704 100644
--- a/docs/ensnode.io/astro.config.mjs
+++ b/docs/ensnode.io/astro.config.mjs
@@ -70,6 +70,11 @@ export default defineConfig({
"/docs/integrate/ens-subgraph/examples/with-ensjs",
"/docs/reference/subgraph-legacy/with-viem": "/docs/integrate/ens-subgraph/examples/with-viem",
"/docs/reference/subgraph-legacy/subgraph-dependents": "/docs/integrate/ens-subgraph",
+ "/docs/services/ensdb/usage": "/docs/services/ensdb/integrations",
+ "/docs/services/ensdb/usage/sdk": "/docs/integrate/unigraph/examples",
+ "/docs/services/ensdb/usage/sql": "/docs/integrate/unigraph/examples",
+ "/docs/services/ensdb/integrations/ensnode": "/docs/services/ensdb/reference-implementation",
+ "/docs/services/ensdb/integrations/future-possibilities": "/docs/services/ensdb/integrations",
"/ensadmin": "/docs/services/ensadmin",
"/ensapi": "/docs/services/ensapi",
"/ensdb": "/docs/services/ensdb",
diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts
index 7e20f42bb..4a418ba4f 100644
--- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts
+++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/integrate.ts
@@ -218,6 +218,18 @@ export const integrateSidebarTopic = {
label: "ENSDb (SQL)",
link: "/docs/integrate/integration-options/ensdb",
},
+ {
+ label: "ENSDb Writers (Indexers)",
+ link: "/docs/integrate/integration-options/ensdb-writers",
+ },
+ {
+ label: "ENSDb Readers (Custom APIs)",
+ link: "/docs/integrate/integration-options/ensdb-readers",
+ },
+ {
+ label: "ENSNode Plugins (data models)",
+ link: "/docs/integrate/integration-options/ensnode-plugins",
+ },
{
label: "enscli (CLI)",
link: "/docs/integrate/integration-options/enscli",
@@ -227,7 +239,7 @@ export const integrateSidebarTopic = {
link: "/docs/integrate/integration-options/ensskills",
},
{
- label: "ensdb-cli (ENSDb Snapshots)",
+ label: "ensdb-cli (Snapshots)",
link: "/docs/integrate/integration-options/ensdb-cli",
},
{
diff --git a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts
index 36e0861be..6b53d656d 100644
--- a/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts
+++ b/docs/ensnode.io/config/integrations/starlight/sidebar-topics/services.ts
@@ -46,28 +46,11 @@ export const servicesSidebarTopic = {
{ label: "Database Schemas", link: "/docs/services/ensdb/concepts/database-schemas" },
],
},
+ { label: "Integrations", link: "/docs/services/ensdb/integrations" },
+
{
- label: "Usage",
- collapsed: true,
- items: [
- { label: "Overview", link: "/docs/services/ensdb/usage" },
- { label: "ENSDb SDK", link: "/docs/services/ensdb/usage/sdk" },
- { label: "ENSDb SQL", link: "/docs/services/ensdb/usage/sql" },
- ],
- },
- {
- label: "Integrations",
- collapsed: true,
- items: [
- {
- label: "ENSNode Reference Implementation",
- link: "/docs/services/ensdb/integrations/ensnode",
- },
- {
- label: "Future Possibilities",
- link: "/docs/services/ensdb/integrations/future-possibilities",
- },
- ],
+ label: "Reference Implementation",
+ link: "/docs/services/ensdb/reference-implementation",
},
],
},
@@ -91,7 +74,7 @@ export const servicesSidebarTopic = {
items: [
{ label: "Overview", link: "/docs/services/ensindexer/contributing" },
{
- label: "Creating a Plugin",
+ label: "ENSNode Plugins",
link: "/docs/services/ensindexer/contributing/creating-a-plugin",
},
],
diff --git a/docs/ensnode.io/mindmap.md b/docs/ensnode.io/mindmap.md
deleted file mode 100644
index 7f5cba38e..000000000
--- a/docs/ensnode.io/mindmap.md
+++ /dev/null
@@ -1,80 +0,0 @@
-```mermaid
-mindmap
- root((ENSDb))
- Vision
- Bi-directional ENS integration
- Writers provide data about ENS
- ENSIndexer indexes onchain data for ENS
- Readers query data about ENS
- ENSAwards queries ENS referrals to build dashboards
- ENSApi queries data about resolver records to enable Protocol Acceleration
-
- Foundations
- ENSDb instance
- Database Schema
- Ponder Schema
- Exactly one per ENSDb instance
- Schema Lifecycle managed by Ponder runtime
- Shared
- Among apps writing to the ENSDb instances
- ENSIndexer instances
- Among apps reading from the ENSDb instance
- ENSApi instances
- ENSNode Schema
- Exactly one per ENSDb instance
- Schema Lifecycle managed by ENSIndexer runtime
- Shared
- Among apps writing to the ENSDb instances
- ENSIndexer instances
- Among apps reading from the ENSDb instance
- ENSApi instances
- ENSIndexer Schema
- At least one per ENSDb instance
- Schema Lifecycle managed by Ponder runtime
- Isolated writer
- A single ENSIndexer can write data
- Shared readers
- Any number of readers can read data
-
- Operations
- Infrastructure
- Database Server
- Serves at least one ENSDb instance
- Writers
- ENSIndexer instance
- Writes into the ENSDb instance
- Cached RPC requests
- Ponder Schema
- Indexed ENS onchain data
- ENSIndexer Schema
- ENSNode Metadata
- ENSNode Schema
- Readers
- ENSApi instance
- Reads from the ENSDb instance
- Indexed ENS onchain data
- ENSNode Metadata
- Provides powerful APIs for querying data about ENS
- Possible future ENS primitives
- Event notifications
- Cache invalidations
- Advanced Dashboards
-
- Tools
- Snapshot tool
- Capabilities
- Takes a snapshot of a selected ENSDb instance
- Restores the ENSDb instance from the snapshot
- Goals
- Cut the cost of RPC requests
- Cut the time needed to complete indexing from scratch
-
- Integrations
- TypeScript
- ENSDb SDK
- ENSDb Reader
- Drizzle client
- ENSDb Writer
- Any tech-stack
- PostgreSQL client
-```
diff --git a/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro b/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro
index 3ee233a85..d16f620ed 100644
--- a/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro
+++ b/docs/ensnode.io/src/components/molecules/EnsDbReaderIntro.astro
@@ -3,9 +3,9 @@ import { Aside } from "@astrojs/starlight/components";
---
diff --git a/docs/ensnode.io/src/components/molecules/EnsDbWriterSchemaIntro.astro b/docs/ensnode.io/src/components/molecules/EnsDbWriterSchemaIntro.astro
new file mode 100644
index 000000000..857bfecd6
--- /dev/null
+++ b/docs/ensnode.io/src/components/molecules/EnsDbWriterSchemaIntro.astro
@@ -0,0 +1,27 @@
+---
+import { Aside } from "@astrojs/starlight/components";
+
+const { ensDbWriterSchemaName = "ensindexer_0" } = Astro.props;
+---
+
+
diff --git a/docs/ensnode.io/src/components/molecules/EnsIndexerSchemaIntro.astro b/docs/ensnode.io/src/components/molecules/EnsIndexerSchemaIntro.astro
deleted file mode 100644
index b0be43888..000000000
--- a/docs/ensnode.io/src/components/molecules/EnsIndexerSchemaIntro.astro
+++ /dev/null
@@ -1,22 +0,0 @@
----
-import { Aside } from "@astrojs/starlight/components";
-
-const { ensIndexerSchemaName = "ensindexer_0" } = Astro.props;
----
-
-
diff --git a/docs/ensnode.io/src/components/molecules/EnsNodeSchemaIntro.astro b/docs/ensnode.io/src/components/molecules/EnsNodeSchemaIntro.astro
index 25868b484..b25eab47e 100644
--- a/docs/ensnode.io/src/components/molecules/EnsNodeSchemaIntro.astro
+++ b/docs/ensnode.io/src/components/molecules/EnsNodeSchemaIntro.astro
@@ -7,8 +7,8 @@ const ensNodeSchemaName = "ensnode";
diff --git a/docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx b/docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx
index 1efd4cdef..9fcb53f84 100644
--- a/docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/hosted-instances.mdx
@@ -10,6 +10,8 @@ import HostedEnsNodeInstance from "@components/molecules/HostedEnsNodeInstance.a
import HostedInstanceSdkVersionWarning from "@components/molecules/HostedInstanceSdkVersionWarning.astro";
import EnsSubgraphCorrectnessPostEnsV2Launch from "@components/molecules/EnsSubgraphCorrectnessPostEnsV2Launch.astro";
+export const pluginLink = (pluginName) => `${pluginName}`;
+
export const subgraphCompatibilityApiLevel = `API-level Subgraph Compatibility. This ENSNode instance has a fully backwards compatible ENS Subgraph GraphQL API. However, additional plugins have been activated which index a superset of data into the subgraph data model in ENSDb. This superset of indexed data means that the data returned for some ENS Subgraph API queries may be different.`;
export const subgraphCompatibilityFull = `Full Subgraph Compatibility. This ENSNode instance has a fully backwards compatible ENS Subgraph GraphQL API at both the API-level and the data-level. We have exhaustively tested and verified that every data record returned by this ENSNode instance's ENS Subgraph API is byte-for-byte identical with The Graph's ENS Subgraph API.`;
export const omnigraphForEnsV1 = `Activated. Demonstrates the ENS Omnigraph's ability to support ENSv1 only before ENSv2 launches and both ENSv1 and ENSv2 are concurrently active. Until ENSv2 launches on this namespace, only ENSv1 domains will be available. As soon as ENSv2 launches on this namespace both ENSv1 and ENSv2 domains will be available.`;
@@ -50,7 +52,7 @@ More details about ENS namespaces can be found inside [ENSNode's datasources pac
### ENSNode Plugins
-Each ENSNode instance is also configured for a specific set of activated **ENSNode plugins**.
+Each ENSNode instance is also configured for a specific set of activated [ENSNode plugins](/docs/integrate/integration-options/ensnode-plugins).
The activated plugins determine the specific indexed data model and data records ENSIndexer will produce in ENSDb and therefore which APIs and data records ENSApi will make available to query.
@@ -69,7 +71,7 @@ The `sepolia-v2` namespace is undergoing active development by the ENS Labs team
connectWithENSAdminURL="https://admin.ensnode.io/connection?connection=https%3A%2F%2Fapi.v2-sepolia.ensnode.io"
namespace="sepolia-v2"
ensVersions="ENSv1 + ENSv2 (concurrently activated together)"
- plugins="unigraph, protocol-acceleration, subgraph"
+ plugins={`${pluginLink("unigraph")}, ${pluginLink("protocol-acceleration")}, ${pluginLink("subgraph")}`}
>
@@ -99,7 +101,7 @@ These ENSNode instances do not constrain themselves to exclusively activating th
connectWithENSAdminURL="https://admin.ensnode.io/connection?connection=https%3A%2F%2Fapi.alpha.ensnode.io"
namespace="mainnet"
ensVersions="ENSv1 only (not also ENSv2 yet)"
- plugins="unigraph, protocol-acceleration, subgraph, basenames, lineanames, threedns, registrars, tokenscope"
+ plugins={`${pluginLink("unigraph")}, ${pluginLink("protocol-acceleration")}, ${pluginLink("subgraph")}, ${pluginLink("basenames")}, ${pluginLink("lineanames")}, ${pluginLink("threedns")}, ${pluginLink("registrars")}, ${pluginLink("tokenscope")}`}
>
@@ -121,7 +123,7 @@ These ENSNode instances do not constrain themselves to exclusively activating th
connectWithENSAdminURL="https://admin.ensnode.io/connection?connection=https%3A%2F%2Fapi.alpha-sepolia.ensnode.io"
namespace="sepolia"
ensVersions="ENSv1 only (not also ENSv2 yet)"
- plugins="unigraph, protocol-acceleration, subgraph, basenames, lineanames, registrars"
+ plugins={`${pluginLink("unigraph")}, ${pluginLink("protocol-acceleration")}, ${pluginLink("subgraph")}, ${pluginLink("basenames")}, ${pluginLink("lineanames")}, ${pluginLink("registrars")}`}
>
@@ -147,7 +149,7 @@ These ENSNode instances focus on maximizing backwards compatibility with the ENS
connectWithENSAdminURL="https://admin.ensnode.io/connection?connection=https%3A%2F%2Fapi.mainnet.ensnode.io"
namespace="mainnet"
ensVersions="ENSv1 only (not also ENSv2 yet)"
- plugins="subgraph"
+ plugins={`${pluginLink("subgraph")}`}
>
@@ -169,7 +171,7 @@ These ENSNode instances focus on maximizing backwards compatibility with the ENS
connectWithENSAdminURL="https://admin.ensnode.io/connection?connection=https%3A%2F%2Fapi.sepolia.ensnode.io"
namespace="sepolia"
ensVersions="ENSv1 only (not also ENSv2 yet)"
- plugins="subgraph"
+ plugins={`${pluginLink("subgraph")}`}
>
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx
index 504f8b0b9..f6b7ad883 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/index.mdx
@@ -155,6 +155,9 @@ The ENS Omnigraph API is a GraphQL API following the Relay specification, so you
Beyond [`enssdk`](/docs/integrate/integration-options/enssdk), [`enskit`](/docs/integrate/integration-options/enskit), and the [Omnigraph GraphQL API](/docs/integrate/integration-options/omnigraph-graphql-api), ENSNode exposes a deeper set of integration surfaces for advanced use cases:
- **[ENSDb (SQL)](/docs/integrate/integration-options/ensdb)** — query the indexed ENSv1 and ENSv2 datasets directly via SQL for custom analytics or your own service layer, from any language with a Postgres driver.
+- **[ENSDb Writers (Indexers)](/docs/integrate/integration-options/ensdb-writers)** — build your own ENSDb Writer to index ENS data into your own ENSDb instance.
+- **[ENSDb Readers](/docs/integrate/integration-options/ensdb-readers)** — build your own ENSDb Reader to query your own ENSDb instance through any interface of your choice.
+- **[ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins)** — define how onchain data should be indexed into ENSDb.
- **[enscli (CLI)](/docs/integrate/integration-options/enscli)** — resolve names, look up records, and run ad-hoc Omnigraph queries from the terminal — built for humans and AI agents alike.
- **[ensskills (AI agents)](/docs/integrate/integration-options/ensskills)** — a curated set of skills that gives AI coding agents a well-defined contract for working with ENS.
- **[ensdb-cli (ENSDb Snapshots)](/docs/integrate/integration-options/ensdb-cli)** — bootstrap a fresh ENSDb in minutes from portable, versioned snapshots instead of waiting days on a full historical backfill.
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb-readers.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb-readers.mdx
new file mode 100644
index 000000000..5d7216b3a
--- /dev/null
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb-readers.mdx
@@ -0,0 +1,54 @@
+---
+title: ENSDb Readers (Custom APIs)
+description: How to build custom APIs and other services on top of ENSDb, using the ENSDb Reader standard.
+---
+
+import { LinkCard } from "@astrojs/starlight/components";
+
+An [ENSDb Reader](/docs/services/ensdb/concepts/glossary#ensdb-reader) is any service that interacts with ENSDb to read ENS data. This can be anything from a custom GraphQL or REST API, to a data analytics pipeline, to a command-line interface, to a dashboard, and more.
+
+:::tip[Build your own ENSDb Reader]
+You can build your own ENSDb Reader in any language, using any framework, as long as you follow the [ENSDb Standard](/docs/services/ensdb/concepts/glossary#ensdb-standard). The ENSDb Standard defines rules and constraints for how an ENSDb Reader should read data from an ENSDb instance in a way that maintains the integrity of the data and supports interoperability with any ENSDb Writer.
+:::
+
+## Current ENSDb Readers
+
+### ENSApi
+
+ENSApi is a reference implementation of an [ENSDb Reader](/docs/services/ensdb/concepts/glossary#ensdb-reader) that includes the following APIs:
+
+- The new [ENS Omnigraph GraphQL API](/docs/integrate/integration-options/omnigraph-graphql-api) that's built on top of [ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins) such as `unigraph` and `protocol-acceleration`.
+- A backwards-compatible [ENS Subgraph GraphQL API](/docs/integrate/ens-subgraph) that's built on top of [ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins) such as `subgraph`, `basenames`, `lineanames`, and `threedns`.
+- APIs for various queries related to the metadata stored in ENSDb, such as the indexing status from the [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) and [metadata](/docs/services/ensdb/concepts/glossary#indexing-metadata-context) about the overall [ENSNode stack of services](/docs/services) active in the ENSNode instance.
+
+
+
+### New ENSDb Readers Under Development
+
+Multiple new [ENSDb Reader](/docs/services/ensdb/concepts/glossary#ensdb-reader) services are planned by the NameHash team. Find out more about each of them below.
+
+
+
+
+
+
+
+:::note[Build your own ENSDb Reader]
+Creating your own ENSDb Reader service enables you to build your own completely custom APIs and data pipeline services. See related inspiration on the [ENSDb integration options page](/docs/integrate/integration-options/ensdb). Use any programming language or framework you wish! If you'd like any help or guidance, feel welcome to reach out to the NameHash team on [Telegram](https://t.me/ensnode).
+:::
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb-writers.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb-writers.mdx
new file mode 100644
index 000000000..9b079a2fe
--- /dev/null
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb-writers.mdx
@@ -0,0 +1,44 @@
+---
+title: ENSDb Writers (Indexers)
+description: How to build your own custom indexer implementation for ENSDb, using the ENSDb Writer specification.
+---
+
+import { LinkCard } from "@astrojs/starlight/components";
+
+An [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) is the implementation of an indexing service that implements one or more standards-compliant [ENSNode plugins](/docs/integrate/integration-options/ensnode-plugins) and implements a standards-compliant [ENSDb Metadata Writer](/docs/services/ensdb/concepts/glossary#ensdb-metadata-writer) that stores [metadata](/docs/services/ensdb/concepts/glossary#indexing-metadata-context) about the [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer).
+
+:::tip[Build your own ENSDb Writer]
+You can build your own ENSDb Writer in any language, using any indexing framework, as long as you follow the [ENSDb Standard](/docs/services/ensdb/concepts/glossary#ensdb-standard). The ENSDb Standard defines rules and constraints for how an ENSDb Writer should write data into an ENSDb instance in a way that maintains the integrity of the data and supports interoperability with any ENSDb Reader.
+
+Your ENSDb Writer must include:
+
+- The _implementation_ of 1 or more standards-compliant [ENSNode plugins](/docs/integrate/integration-options/ensnode-plugins).
+- The _implementation_ of an [ENSDb Metadata Writer](/docs/services/ensdb/concepts/glossary#ensdb-metadata-writer) that stores [metadata](/docs/services/ensdb/concepts/glossary#indexing-metadata-context) about the [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) overall, including which [ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins) it has activated, what the status of indexing is across each indexed chain, etc.
+
+:::
+
+## Current ENSDb Writers
+
+### ENSIndexer
+
+[ENSIndexer](/docs/services/ensindexer) is a reference implementation of an [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) built by the NameHash team. It is a multi-chain ENS indexer built on top of [Ponder](https://ponder.sh/) that implements many ENSNode Plugins.
+
+
+
+## New ENSDb Writers Under Development or Discussions
+
+### Envio
+
+The [Envio](https://envio.dev/) team is actively collaborating with NameHash Labs to build another standards-compliant [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) that uses Envio as the indexing engine. Their initial ENSNode plugin under development is `subgraph`, with plans to support `unigraph` after that.
+
+### Amp (Edge & Node)
+
+[Edge & Node](https://www.edgeandnode.com) has discussions scheduled with the NameHash Labs team to investigate the use of their new [Amp](https://www.edgeandnode.com/articles/stream-live-chain-data-into-your-analytics-stack-with-amp) platform to implement an ENSDb Writer.
+
+### Build Your Own
+
+You can build your own ENSDb Writer in any language, using any indexing framework, as long as you follow the [ENSDb Standard](/docs/services/ensdb/concepts/glossary#ensdb-standard). Join us on [Telegram](https://t.me/ensnode) for any questions and support.
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb.mdx
index 163a6adfb..2a4aad73d 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/ensdb.mdx
@@ -9,7 +9,9 @@ import EnsDbUseCases from "@components/molecules/EnsDbUseCases.astro";
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.
+The bi-directional [ENSDb integration standard](/docs/services/ensdb/concepts/glossary#ensdb-standard) enables any decoupled [ENSDb Writer](/docs/integrate/integration-options/ensdb-writers) and [ENSDb Reader](/docs/integrate/integration-options/ensdb-readers) 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.
+
+The ENSDb standard also defines _the abstract specification_ for how ENSDb Writers store their [metadata](/docs/services/ensdb/concepts/glossary#indexing-metadata-context) in an [ENSDb instance](/docs/services/ensdb/concepts/glossary#ensdb-instance).
:::tip[Coming soon: ensdb-cli & ENSDb snapshots]
We're building [**`ensdb-cli` & ENSDb snapshots**](/docs/integrate/integration-options/ensdb-cli) so you can pull down a fresh ENSDb in minutes instead of paying for a full historical RPC backfill among many other benefits.
@@ -21,49 +23,15 @@ We're building [**`ensdb-cli` & ENSDb snapshots**](/docs/integrate/integration-o
-### 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`.
-
-```typescript title="example.ts"
-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"));
-```
-
-```sql title="example.sql"
-SELECT * FROM ensindexer_0.domains
-WHERE canonical_name = 'vitalik.eth';
-```
-
-### Example: count an address's Domains by type (ENSv1 vs ENSv2)
-
-```typescript title="example.ts"
-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);
-```
+## Examples
-```sql title="example.sql"
-SELECT type, count(*) FROM ensindexer_0.domains
-WHERE owner_id = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
-GROUP BY type;
-```
+
-### Learn more
+## Learn more
-
-
-
-
+
+
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/index.mdx
index 3b3aaeb69..a77f435a0 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/integration-options/index.mdx
@@ -45,7 +45,34 @@ For special use cases that go beyond what the ENS Omnigraph exposes, query the l
href="/docs/integrate/integration-options/ensdb"
/>
-## 5. enscli
+## 5. ENSDb Writers
+
+Build your own indexer for ENSDb by implementing the [ENSNode Plugin](/docs/integrate/integration-options/ensnode-plugins) specifications you're interested in indexing. ENSDb Writers index onchain data and write it into an ENSDb instance according to the standards set by relevant ENSNode Plugins.
+
+
+
+## 6. ENSDb Readers
+
+Build custom APIs or other specialized services on top of ENSDb. ENSDb Readers read indexed ENS data from an ENSDb instance and serve it through any API surface (GraphQL, REST, gRPC, webhooks, etc.) or pipe it into specialized data processing pipelines through the PostgreSQL write-ahead-log.
+
+
+
+## 7. ENSNode Plugins
+
+ENSNode Plugins are abstract specifications that define indexed data models relevant to ENS. They are a key architectural piece that enables complete decoupling between ENSDb Writers and ENSDb Readers.
+
+
+
+## 8. enscli
`enscli` is a CLI that wraps `enssdk` to bring the ENS Omnigraph to the terminal. Designed for developers exploring or validating integrations, operators wiring ENS lookups into shell pipelines, and AI coding agents driving `ensskills`.
@@ -54,7 +81,7 @@ For special use cases that go beyond what the ENS Omnigraph exposes, query the l
href="/docs/integrate/integration-options/enscli"
/>
-## 6. ensskills
+## 9. ensskills
`ensskills` is a collection of curated skill bundles that give AI coding agents a well-defined contract for working with ENS — powering conversational ENS lookups and streamlining integration code written with `enskit`, `enssdk`, or the raw Omnigraph API.
@@ -63,7 +90,7 @@ For special use cases that go beyond what the ENS Omnigraph exposes, query the l
href="/docs/integrate/integration-options/ensskills"
/>
-## 7. ensdb-cli & ENSDb snapshots
+## 10. ensdb-cli & ENSDb snapshots
`ensdb-cli` is the operator-facing tool for ENSDb snapshots — portable, versioned packages of an ENSDb instance. Pull one down, restore it into Postgres, and start querying ENS in minutes instead of waiting days to complete a full historical indexing backfill from scratch.
@@ -72,7 +99,7 @@ For special use cases that go beyond what the ENS Omnigraph exposes, query the l
href="/docs/integrate/integration-options/ensdb-cli"
/>
-## 8. ENSEngine
+## 11. ENSEngine
ENSEngine watches your ENSDb for changes in real time and delivers ENS-aware events — including webhooks — to any sink you configure. Stop polling and start reacting to ENS state changes.
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/concepts.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/concepts.mdx
index 9aca48328..f9a17f5b3 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/concepts.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/omnigraph/concepts.mdx
@@ -82,7 +82,7 @@ query Namegraph {
The **Unigraph** is the entire collection of these disjoint ENSv2 Namegraphs and multiple ENSv1 Nametables, combined together into a single unified data model using ENS Resolution semantics. Navigating the Unigraph from `"eth"` down to `"vitalik.eth"` and beyond looks identical regardless of whether the underlying entities are ENSv1 or ENSv2.
-The [`unigraph` plugin](/docs/services/ensindexer) in ENSIndexer is what builds this unified model. The Unigraph constructs two Namegraphs, one rooted at the ENSv1 Root Registry and another rooted at the ENSv2 Root Registry. It's also where multichain coverage lives: Basenames (`.base.eth`), Lineanames (`.linea.eth`), and 3DNS names (`.box`) are all stitched into the ENSv1 Namegraph.
+The `unigraph` [ENSNode plugin](/docs/integrate/integration-options/ensnode-plugins), implemented in [ENSIndexer](/docs/services/ensindexer), is what builds this unified model. The Unigraph constructs two Namegraphs, one rooted at the ENSv1 Root Registry and another rooted at the ENSv2 Root Registry. It also includes special support for unifying multiple ENSv1 Nametables across multiple chains into the unigraph, including: Basenames (`.base.eth`), Lineanames (`.linea.eth`), and 3DNS names (`.box`).
```mermaid
flowchart TD
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx
index 801fbe831..c19be523a 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/account-domains.mdx
@@ -7,7 +7,7 @@ sidebar:
import { Tabs, TabItem } from "@astrojs/starlight/components";
import ResultDetails from "@components/molecules/ResultDetails.astro";
-import EnsIndexerSchemaIntro from "@components/molecules/EnsIndexerSchemaIntro.astro";
+import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro";
import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro";
export const resultJson = [
@@ -29,7 +29,7 @@ Count the Domains owned by an address, grouped by Domain `type` (`ENSv1Domain` v
-
+
```sql
SELECT type, count(*) FROM ensindexer_0.domains
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx
index 67a4834c8..92395a9ac 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/domain-by-name.mdx
@@ -7,7 +7,7 @@ sidebar:
import { Tabs, TabItem } from "@astrojs/starlight/components";
import ResultDetails from "@components/molecules/ResultDetails.astro";
-import EnsIndexerSchemaIntro from "@components/molecules/EnsIndexerSchemaIntro.astro";
+import EnsDbWriterSchemaIntro from "@components/molecules/EnsDbWriterSchemaIntro.astro";
import EnsDbReaderIntro from "@components/molecules/EnsDbReaderIntro.astro";
export const unigraphSqlResultJson = [
@@ -78,7 +78,7 @@ Canonical fields are populated on every Domain reachable from the canonical root
-
+
```sql
SELECT * FROM ensindexer_0.domains
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/index.mdx
index 6e4b40758..c5227cd69 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/index.mdx
@@ -17,7 +17,7 @@ Performing SQL queries on the ENS Unigraph requires that you have the `unigraph`
## Connect
-The Unigraph lives in [ENSDb](/docs/services/ensdb), a PostgreSQL database. Each ENSIndexer instance writes to its own **ENSIndexer Schema** (e.g. `ensindexer_0`); shared operational metadata lives in the `ensnode` schema.
+The Unigraph lives in [ENSDb](/docs/services/ensdb), a PostgreSQL database. Each [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) instance writes to its own **ENSDb Writer Schema** (e.g. `ensindexer_0`). Each instance of [ENSDb Metadata Writer](/docs/services/ensdb/concepts/glossary#ensdb-metadata-writer) writes to a shared operational [metadata table](/docs/services/ensdb/concepts/glossary#ensnode-metadata-table) in the [`ensnode` schema](/docs/services/ensdb/concepts/glossary#ensnode-schema).
@@ -25,7 +25,7 @@ The Unigraph lives in [ENSDb](/docs/services/ensdb), a PostgreSQL database. Each
psql postgresql://user:password@host:5432/ensdb_devnet
```
-Discover the available ENSIndexer Schemas:
+Discover the available ENSDb Writer Schemas:
```sql
SELECT DISTINCT ens_indexer_schema_name
@@ -39,13 +39,13 @@ npm install @ensnode/ensdb-sdk
```
:::note[ENSDb Reader]
-The `EnsDbReader` object enables you to build custom queries against the Unigraph data model in ENSDb. Use the `ensDb` field to build queries with the Drizzle ORM, and the `ensIndexerSchema` field to reference database objects (i.e. the Unigraph tables) within the [ENSIndexer Schema](/docs/services/ensdb/concepts/glossary#ensindexer-schema) in a type-safe way.
+The `EnsDbReader` object enables you to build custom queries against the Unigraph data model in ENSDb. Use the `ensDb` field to build queries with the Drizzle ORM, and the `ensIndexerSchema` field to reference database objects (i.e. the Unigraph tables) within the [ENSDb Writer Schema](/docs/services/ensdb/concepts/glossary#ensdb-writer-schema) in a type-safe way.
:::
```typescript
import { EnsDbReader } from "@ensnode/ensdb-sdk";
-// Connect by providing a connection string and the ENSIndexer Schema Name to query
+// Connect by providing a connection string and the ENSDb Writer Schema Name to query
const ensDbReader = new EnsDbReader(ensDbConnectionString, ensIndexerSchemaName);
const { ensDb, ensIndexerSchema } = ensDbReader;
```
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx
index 085603ad4..5e0121329 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/examples/indexing-status.mdx
@@ -129,7 +129,7 @@ Read the indexing status snapshot for an ENSIndexer instance from the shared `en
```sql
--- Indexing status snapshot for the `ensindexer_0` ENSIndexer Schema
+-- Indexing status snapshot for the `ensindexer_0` ENSDb Writer Schema
SELECT value -> 'indexingStatus' as indexing_status_snapshot
FROM "ensnode"."metadata"
WHERE ens_indexer_schema_name = 'ensindexer_0'
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/index.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/index.mdx
index 2c946a227..3fe93d120 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/index.mdx
@@ -32,7 +32,9 @@ The Unigraph models both protocol versions with the **same polymorphic entities*
## The Canonical Nametree
+:::note[The Canonical Nametree]
The **Canonical Nametree** is the set of all Domains that have an inferrable **Canonical Name** — materialized from the namegraph. For every Domain in it, the canonical fields are populated — `canonical_name`, `canonical_path`, `canonical_node`, and `canonical_depth` — across both ENSv1 and ENSv2. That means you can look a name up by `canonical_name = 'vitalik.eth'`, order by `canonical_depth`, or walk a name's path **without branching on protocol version** and without traversing the namegraph yourself.
+:::
Multichain coverage is part of the same model: Basenames (`.base.eth`), Lineanames (`.linea.eth`), and 3DNS names (`.box`) are materialized into the same Unigraph as mainnet `.eth`, so a single query spans every indexable name.
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/schema-reference.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/schema-reference.mdx
index c709f900f..1508fbacd 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/schema-reference.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/unigraph/schema-reference.mdx
@@ -7,14 +7,14 @@ sidebar:
import { Aside } from "@astrojs/starlight/components";
-This is the canonical reference for the **Unigraph schema** — the unified, polymorphic data model that the [`unigraph` plugin](/docs/services/ensindexer) materializes into [ENSDb](/docs/services/ensdb). It models ENSv1 and ENSv2 with shared, polymorphic entities (Domains, Registries, Registrations, Renewals, Resolvers), so the same query shape works across both protocol versions.
+This is the canonical reference for the **Unigraph schema** — the unified, polymorphic data model that the `unigraph` [ENSNode plugin](/docs/integrate/integration-options/ensnode-plugins) (implemented in [ENSIndexer](/docs/services/ensindexer)) materializes into [ENSDb](/docs/services/ensdb). It models ENSv1 and ENSv2 with shared, polymorphic entities (Domains, Registries, Registrations, Renewals, Resolvers), so the same query shape works across both protocol versions.
-Each ENSIndexer instance owns a dedicated database schema (e.g. `ensindexer_0`) holding all of its indexed Unigraph data, fully isolated from other instances.
+Each [ENSIndexer instance](/docs/services/ensdb/concepts/glossary#ensindexer-instance) owns a dedicated [ENSDb Writer Schema](/docs/services/ensdb/concepts/glossary#ensdb-writer-schema) (e.g. `ensindexer_0`) holding all of its indexed Unigraph data, fully isolated from other instances.
diff --git a/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode/ensv2-readiness.mdx b/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode/ensv2-readiness.mdx
index 82f38dd0d..a4e58f882 100644
--- a/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode/ensv2-readiness.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/integrate/why-ensnode/ensv2-readiness.mdx
@@ -22,7 +22,7 @@ Full access to ENS data formerly required two separate data-fetching strategies
## How ENSNode solves this
-**The Unigraph Data Model** — [ENSIndexer](/docs/services/ensindexer)'s `unigraph` plugin builds a single, **unified** indexed data model in [ENSDb](/docs/services/ensdb) that combines all of ENSv1 — mainnet `.eth`, Basenames on Base, Lineanames on Linea, 3DNS on Optimism — together with ENSv2. One data model, every chain, both protocol versions.
+**The Unigraph Data Model** — The `unigraph` [ENSNode plugin](/docs/integrate/integration-options/ensnode-plugins), implemented in [ENSIndexer](/docs/services/ensindexer), builds a single, **unified** indexed data model in [ENSDb](/docs/services/ensdb) that combines all of ENSv1 — mainnet `.eth`, Basenames on Base, Lineanames on Linea, 3DNS on Optimism — together with ENSv2. One data model, every chain, both protocol versions.
**The Omnigraph API** — The [ENS Omnigraph API](/docs/integrate/omnigraph), delivered by [ENSApi](/docs/services/ensapi), is a fully typed GraphQL API on top of that Unigraph data model. It handles the ENS protocol's many implementation details for you, so you can focus on building your app instead of wiring up the protocol's internals.
diff --git a/docs/ensnode.io/src/content/docs/docs/reference/contributing/releases.mdx b/docs/ensnode.io/src/content/docs/docs/reference/contributing/releases.mdx
index cc5228969..10a39aacc 100644
--- a/docs/ensnode.io/src/content/docs/docs/reference/contributing/releases.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/reference/contributing/releases.mdx
@@ -115,7 +115,7 @@ In particular, when deploying ENSNode to production environments, using the `lat
:::
:::caution
-Each ENSIndexer version update is likely to produce an updated [Ponder Build Id](https://ponder.sh/docs/api-reference/ponder/database). When updating your ENSIndexer version, you should expect to update the `ENSINDEXER_SCHEMA_NAME` environment variable to point to a new ENSIndexer Schema in ENSDb for a complete reindexing with the new Ponder Build Id. A complete reindexing may take over 24 hours depending on your configuration. ENSNode version updates require special coordination and should not be assumed to be a simple version bump.
+Each ENSIndexer version update is likely to produce an updated [Ponder Build Id](https://ponder.sh/docs/api-reference/ponder/database). When updating your ENSIndexer version, you should expect to update the `ENSINDEXER_SCHEMA_NAME` environment variable to point to a new ENSDb Writer Schema in ENSDb for a complete reindexing with the new Ponder Build Id. A complete reindexing may take over 24 hours depending on your configuration. ENSNode version updates require special coordination and should not be assumed to be a simple version bump.
:::
### Snapshot Releases
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/database-schemas.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/database-schemas.mdx
index b8c660cbb..96b11670c 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/database-schemas.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/database-schemas.mdx
@@ -4,48 +4,48 @@ description: Detailed explanation of all database schemas that make up ENSDb.
sidebar:
label: Database Schemas
order: 4
-keywords: [ensdb, database schemas, ponder schema, ensnode schema, ensindexer schema]
+keywords: [ensdb, database schemas, ponder schema, ensnode schema, ensdb writer schema]
---
-This page explains the different database schemas in ENSDb, including the ENSNode Schema, and the modular ENSIndexer Schema.
+This page explains the different database schemas in ENSDb, including the ENSNode Schema, and the modular ENSDb Writer Schema.
## Overview of ENSDb Schemas
-ENSDb instance can have two distinct kinds of database schemas: a single shared **ENSNode Schema** for operational metadata, and one **ENSIndexer Schema** per running ENSIndexer instance for all indexed ENS data. View Interactive Diagram of ENSDb Schemas.
+An ENSDb instance can have two distinct kinds of database schemas: a single shared **ENSNode Schema** for operational metadata, and one **ENSDb Writer Schema** per running ENSDb Writer instance for all indexed ENS data. View Interactive Diagram of ENSDb Schemas.
## ENSNode Schema
The `ensnode` database schema contains shared operational metadata, called ENSNode Metadata, for the entire ENSDb database.
:::note[Multi-tenancy]
-ENSDb supports multiple ENSIndexer instances coexisting in the same database, each with its own isolated database schema. The ENSNode `metadata` table is the central registry that tracks all of them. Each instance identifies itself by writing rows scoped to its own database schema name via the `ens_indexer_schema_name` column.
+ENSDb supports multiple ENSDb Writer instances coexisting in the same database, each with its own isolated database schema. The ENSNode `metadata` table is the central registry that tracks all of them. Each instance identifies itself by writing rows scoped to its own database schema name via the `ens_indexer_schema_name` column.
:::
### ENSNode Metadata
Possible key-value pairs are defined by the `EnsNodeMetadata` union type. As of now, it includes: `EnsNodeMetadataIndexingMetadataContext`.
-| Column | Type | Nullable | Description |
-| ------------------------- | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `ens_indexer_schema_name` | `text` | no | References the name of the ENSIndexer Schema that the metadata record belongs to. This allows multi-tenancy where multiple ENSIndexer instances can write to the same ENSNode Metadata table. |
-| `key` | `text` | no | Allowed keys: `indexing_metadata_context`. |
-| `value` | `jsonb` | no | Guaranteed to be a serialized representation of a JSON object. |
+| Column | Type | Nullable | Description |
+| ------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `ens_indexer_schema_name` | `text` | no | References the name of the ENSDb Writer Schema that the metadata record belongs to. This allows multi-tenancy where multiple ENSDb Writer instances can write to the same ENSNode Metadata table. |
+| `key` | `text` | no | Allowed keys: `indexing_metadata_context`. |
+| `value` | `jsonb` | no | Guaranteed to be a serialized representation of a JSON object. |
-**Primary key:** `(ens_indexer_schema_name, key)` — ensures that there is only one record for each key per ENSIndexer instance.
+**Primary key:** `(ens_indexer_schema_name, key)` — ensures that there is only one record for each key per ENSDb Writer instance.
#### Known keys
-| Key | TypeScript type | Description |
-| --------------------------- | ------------------------------------ | ------------------------------------------------------------------ |
-| `indexing_metadata_context` | `IndexingMetadataContextInitialized` | Stores indexing status and stack info for the ENSIndexer instance. |
+| Key | TypeScript type | Description |
+| --------------------------- | ------------------------------------ | -------------------------------------------------------------------- |
+| `indexing_metadata_context` | `IndexingMetadataContextInitialized` | Stores indexing status and stack info for the ENSDb Writer instance. |
---
-## ENSIndexer Schema
+## ENSDb Writer Schema
-Each ENSIndexer instance owns a dedicated database schema in ENSDb. All indexed ENS data for that instance lives within it, fully isolated from other instances. On startup, an ENSIndexer instance registers itself in `ensnode.metadata` using its database schema name as `ens_indexer_schema_name`.
+Each ENSDb Writer instance owns a dedicated database schema in ENSDb. All indexed ENS data for that instance lives within it, fully isolated from other instances.
-The ENSIndexer Schema is modular, composed of multiple logical database sub-schemas, each implemented for specific requirements by a separate Ponder plugin.
+The ENSDb Writer Schema is modular and can be composed of multiple logical database sub-schemas. Each sub-schema is implemented for the exact requirements determined by a specific implementation of an [ENSNode Plugin](/docs/services/ensdb/concepts/glossary#ensnode-plugin).
---
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/glossary.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/glossary.mdx
index ab5beb754..78d9f4fd4 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/glossary.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/glossary.mdx
@@ -46,18 +46,26 @@ Objects contained within a [database schema](#database-schema), including:
An open standard for bi-directional ENS integration. The ENSDb Standard defines:
- Schema designs for storing ENS data in a [PostgreSQL database](#postgresql-database)
-- Rules and constraints for [ENSDb Writers](#ensdb-writer) and [ENSDb Readers](#ensdb-reader)
+- Rules and constraints for [ENSDb Writers](#ensdb-writer), [ENSDb Metadata Writers](#ensdb-metadata-writer), and [ENSDb Readers](#ensdb-reader)
- A modular architecture enabling interoperability
Any [PostgreSQL database](#postgresql-database) following the ENSDb Standard is an [ENSDb instance](#ensdb-instance).
+### ENSNode Plugin
+
+An abstract specification that determines how a specific aspect of the [ENS namespace](/docs/hosted-instances#ens-namespaces) is indexed into [ENSDb](/docs/services/ensdb). A plugin defines: a name, datasources (which onchain contracts to index as a function of the ENS namespace), dependency relationships with other plugins, an indexed data model with indexes, and standards and invariants for how onchain events are translated into that indexed data model during indexing. Any [ENSDb Writer](#ensdb-writer) can have multiple plugins implementing the ENSNode Plugin standard.
+
### ENSDb Writer
-Any application that writes ENS data into an [ENSDb instance](#ensdb-instance) following the [ENSDb Standard](#ensdb-standard). For example, [ENSIndexer](#ensindexer) is a reference implementation of an ENSDb Writer. Other implementations of ENSDb Writers can be built in any language, and can use different indexing frameworks (i.e. [Ponder](https://ponder.sh/), [rindexer](https://rindexer.xyz/)), as long as they follow the ENSDb Standard.
+Any application that implements one or more standard-compliant [ENSNode Plugins](#ensnode-plugin) and also implements an [ENSDb Metadata Writer](#ensdb-metadata-writer). An ENSDb Writer is responsible for writing ENS data into an [ENSDb instance](#ensdb-instance) following the [ENSDb Standard](#ensdb-standard). For example, [ENSIndexer](#ensindexer) is a reference implementation of an ENSDb Writer. Other implementations of ENSDb Writers can be built in any language, and can use different indexing frameworks (i.e. [Ponder](https://ponder.sh/), [Envio](https://envio.dev/), [rindexer](https://rindexer.xyz/), [Amp](https://ampup.sh/) from Edge & Node, etc.), as long as they follow the ENSDb Standard.
+
+### ENSDb Metadata Writer
+
+Any application that writes metadata about an [ENSDb Writer](#ensdb-writer) into an [ENSDb instance](#ensdb-instance) following the [ENSDb Standard](#ensdb-standard). For example, [ENSIndexer](#ensindexer) is a reference implementation of an ENSDb Metadata Writer, which writes [Indexing Metadata Context](#indexing-metadata-context) records into the [ENSNode Metadata Table](#ensnode-metadata-table) for each ENSIndexer instance that has ever connected to the ENSDb instance. Other implementations of ENSDb Metadata Writers can be built in any language, as long as they follow the ENSDb Standard.
### ENSDb Reader
-Any application that reads ENS data from an [ENSDb instance](#ensdb-instance) following the [ENSDb Standard](#ensdb-standard). For example, [ENSApi](#ensapi) is a reference implementation of an ENSDb Reader. Other implementations of ENSDb Readers can be built in any language, and can serve different types of APIs (GraphQL, REST, gRPC, etc.), as long as they follow the ENSDb Standard.
+Any application that reads ENS data from an [ENSDb instance](#ensdb-instance) following the [ENSDb Standard](#ensdb-standard). It knows how to read state from ENSDb, including overall metadata from the relevant [ENSDb Writer](#ensdb-writer) instance(s) and (where relevant) data associated with the [ENSNode Plugins](#ensnode-plugin) relevant to the specific ENSDb Reader implementation. For example, [ENSApi](#ensapi) is a reference implementation of an ENSDb Reader. Other implementations of ENSDb Readers can be built in any language, as long as they follow the ENSDb Standard. Any implementation of an ENSDb Reader can support different types of interfaces (i.e. MPC, CLI, GraphQL, REST, gRPC, etc.), depending on the use case it is designed for.
## ENSDb Concepts
@@ -77,29 +85,28 @@ For ENSDb, a Drizzle ORM object that defines the structure of [database objects]
A [PostgreSQL database](#postgresql-database) that follows the [ENSDb Standard](#ensdb-standard). An ENSDb instance stores indexed ENS data and is composed of two types of database schemas:
- Exactly one [ENSNode Schema](#ensnode-schema)
-- One or more [ENSIndexer Schemas](#ensindexer-schema)
+- One or more [ENSDb Writer Schemas](#ensdb-writer-schema)
#### Multi-Tenant ENSDb instance
> This example is based on reference implementations, but the ENSDb standard is implementation-agnostic, so this is just one possible design.
-An [ENSDb instance](#ensdb-instance) is considered multi-tenant when it stores data from multiple [ENSIndexer instances](#ensindexer-instance) (tenants) in isolated [ENSIndexer Schemas](#ensindexer-schema).
+An [ENSDb instance](#ensdb-instance) is considered multi-tenant when it stores data from multiple [ENSDb Writer](#ensdb-writer) instances (tenants) in isolated ENSDb Writer Schemas.
Within a single [ENSDb instance](#ensdb-instance):
-- Each [ENSIndexer instance](#ensindexer-instance) gets its own [ENSIndexer Schema](#ensindexer-schema) — fully isolated data following the [ENSIndexer Schema Definition](#ensindexer-schema-definition) that was current when the ENSIndexer instance started.
-- All [ENSIndexer instances](#ensindexer-instance) share the [Ponder Schema](#ponder-schema), including the RPC cache.
-- Metadata of all [ENSIndexer instances](#ensindexer-instance) is tracked in the [ENSNode Schema](#ensnode-schema)
+- Each [ENSDb Writer](#ensdb-writer) instance gets its own ENSDb Writer Schema — fully isolated data following the [ENSDb Writer Schema Definition](#ensdb-writer-schema-definition) that was current when the instance started.
+- Metadata of all [ENSDb Writer](#ensdb-writer) instances is tracked in the [ENSNode Schema](#ensnode-schema)
-This enables separate indexing by multiple [ENSIndexer instances](#ensindexer-instance) with different configs. The configs may require indexing just certain chains. For example, one [ENSIndexer instance](#ensindexer-instance) is configured to index data just from the Ethereum Mainnet, while another [ENSIndexer instance](#ensindexer-instance) is configured to index data from both, Ethereum Mainnet, and Base Mainnet. Each of these [ENSIndexer instances](#ensindexer-instance) would have its own [ENSIndexer Schema](#ensindexer-schema) in the same [ENSDb instance](#ensdb-instance).
+This enables separate indexing by multiple [ENSDb Writer](#ensdb-writer) instances with different configs. The configs may require indexing just certain chains. For example, one [ENSDb Writer](#ensdb-writer) instance is configured to index data just from the Ethereum Mainnet, while another [ENSDb Writer](#ensdb-writer) instance is configured to index data from both, Ethereum Mainnet, and Base Mainnet. Each of these [ENSDb Writer](#ensdb-writer) instances would have its own ENSDb Writer Schema in the same [ENSDb instance](#ensdb-instance).
### Ponder runtime
-Ponder runtime is executed by the ENSIndexer instance. It manages fetching onchain data, and having it cached in RPC cache inside the [Ponder Schema](#ponder-schema). The Ponder runtime also performs writes to the [ENSIndexer Schema](#ensindexer-schema) owned by the ENSIndexer instance.
+Ponder runtime is executed by the ENSIndexer instance. It manages fetching onchain data, and having it cached in RPC cache inside the [Ponder Schema](#ponder-schema). The Ponder runtime also performs writes to the ENSDb Writer Schema owned by the ENSIndexer instance.
### Ponder Schema
-A [database schema](#database-schema) in the [ENSDb instance](#ensdb-instance) following the [Ponder Schema Definition](#ponder-schema-definition). It is an implementation detail of ENSIndexer. It has a fixed `ponder_sync` name, and it serves as a shared RPC cache for all [ENSIndexer instances](#ensindexer-instance) connected to the [ENSDb instance](#ensdb-instance). Its lifecycle is managed by Ponder runtime.
+A [database schema](#database-schema) in the [ENSDb instance](#ensdb-instance) following the [Ponder Schema Definition](#ponder-schema-definition). It is an implementation detail of [ENSIndexer](#ensindexer). It has a fixed `ponder_sync` name, and it serves as a shared RPC cache for all [ENSIndexer instances](#ensindexer-instance) connected to the [ENSDb instance](#ensdb-instance). Its lifecycle is managed by Ponder runtime.
The Ponder Schema enables multiple [ENSIndexer instances](#ensindexer-instance) to share RPC cache, reducing costs and improving indexing speed.
@@ -109,35 +116,35 @@ A [Schema Definition](#schema-definition) that defines the structure of the [Pon
### ENSNode Schema
-A [database schema](#database-schema) in the [ENSDb instance](#ensdb-instance) following the [ENSNode Schema Definition](#ensnode-schema-definition). It has a fixed `ensnode` name, and it serves as a registry for all [ENSIndexer instances](#ensindexer-instance) that have ever connected to the [ENSDb instance](#ensdb-instance). It also stores metadata about these [ENSIndexer instances](#ensindexer-instance).
+A [database schema](#database-schema) in the [ENSDb instance](#ensdb-instance) following the [ENSNode Schema Definition](#ensnode-schema-definition). It has a fixed `ensnode` name, and it serves as a registry for all ENSDb Writer instances that have ever connected to the [ENSDb instance](#ensdb-instance). It also stores metadata about these ENSDb Writer instances.
### ENSNode Schema Definition
A [Schema Definition](#schema-definition) that defines the structure of the [ENSNode Schema](#ensnode-schema) in the [ENSDb instance](#ensdb-instance). The ENSNode Schema Definition is part of the ENSDb standard and is maintained in the ENSDb SDK. It includes the definition of the [ENSNode Metadata Table](#ensnode-metadata-table).
-### ENSIndexer Schema
+### ENSDb Writer Schema
-A [database schema](#database-schema) within an [ENSDb instance](#ensdb-instance), used to store indexed ENS data. Each [ENSIndexer instance](#ensindexer-instance) owns exactly one ENSIndexer Schema, whose structure follows the [ENSIndexer Schema Definition](#ensindexer-schema-definition) that was current when the instance first started. The schema's name is determined at startup, when the ENSIndexer instance connects to the ENSDb instance and creates its schema using the configured [ENSIndexer Schema Name](#ensindexer-schema-name).
+A [database schema](#database-schema) within an [ENSDb instance](#ensdb-instance), used to store indexed ENS data. Each [ENSDb Writer](#ensdb-writer) instance owns exactly one ENSDb Writer Schema, whose structure follows the ENSNode Plugins implemented by the instance. The schema's name is determined at startup, when the ENSDb Writer instance connects to the ENSDb instance and creates its schema using the configured [ENSDb Writer Schema Name](#ensdb-writer-schema-name).
-#### ENSIndexer Schema Definition
+#### ENSDb Writer Schema Definition
-A [Schema Definition](#schema-definition) that defines the structure of an [ENSIndexer Schema](#ensindexer-schema). It is part of the ENSDb standard, maintained in the [ENSDb SDK](#ensdb-sdk), and specifies the core tables and columns used to store indexed ENS data.
+A [Schema Definition](#schema-definition) that defines the structure of an [ENSDb Writer Schema](#ensdb-writer-schema). It specifies the core tables and columns used to store indexed ENS data and is configured by the [ENSNode Plugins](#ensnode-plugin) implemented by the [ENSDb Writer](#ensdb-writer) instance that owns this ENSDb Writer Schema. Each time a new version of an ENSNode Plugin is released with changes to the indexed data model, the ENSDb Writer Schema Definition may be updated to reflect those changes.
-### ENSIndexer Schema Name
+### ENSDb Writer Schema Name
-The name of a specific [ENSIndexer Schema](#ensindexer-schema) in the [ENSDb instance](#ensdb-instance). This name is dynamic and determined by the [ENSIndexer instance](#ensindexer-instance) that owns the schema.
+The name of a specific ENSDb Writer Schema in the [ENSDb instance](#ensdb-instance). This name is dynamic and determined by the [ENSDb Writer](#ensdb-writer) instance that owns the schema.
-Multiple [ENSIndexer Schema Names](#ensindexer-schema-name) exist in an [ENSDb instance](#ensdb-instance) when multiple [ENSIndexer instances](#ensindexer-instance) are connected.
+Multiple ENSDb Writer Schema Names exist in an [ENSDb instance](#ensdb-instance) when multiple ENSDb Writer instances are connected.
### ENSNode Metadata Table
-A table within the [ENSNode Schema](#ensnode-schema) that tracks all [ENSIndexer instances](#ensindexer-instance) that have ever connected to the [ENSDb instance](#ensdb-instance).
+A table within the [ENSNode Schema](#ensnode-schema) that tracks all ENSDb Writer instances that have ever connected to the [ENSDb instance](#ensdb-instance).
-| Column | Type | Purpose |
-| ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------- |
-| `ens_indexer_schema_name` | `text` | References the [ENSIndexer Schema Name](#ensindexer-schema-name) of the ENSIndexer instance that manages this metadata record |
-| `key` | `text` | Type of metadata record |
-| `value` | `jsonb` | The context object (configuration, status, etc.) |
+| Column | Type | Purpose |
+| ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------- |
+| `ens_indexer_schema_name` | `text` | References the ENSDb Writer Schema Name of the [ENSDb Writer](#ensdb-writer) instance that manages this metadata record |
+| `key` | `text` | Type of metadata record |
+| `value` | `jsonb` | The context object (configuration, status, etc.) |
Primary key: (`ens_indexer_schema_name`, `key`)
@@ -147,17 +154,17 @@ The `value` column stores a JSON object which structure may evolve over time. To
The `key` column identifies the type of metadata:
-| Key | Description |
-| --------------------------- | ---------------------------------------------------------------------------------------------------------- |
-| `indexing_metadata_context` | [Indexing metadata context](#indexing-metadata-context) of the [ENSIndexer instance](#ensindexer-instance) |
+| Key | Description |
+| --------------------------- | ------------------------------------------------------------------------------------------------------ |
+| `indexing_metadata_context` | [Indexing metadata context](#indexing-metadata-context) for the [ENSDb Writer](#ensdb-writer) instance |
#### Indexing Metadata Context
-A JSON object that provides indexing metadata context. The actual context data, whose structure may evolve over time as the needs of the ENSNode stack evolve. The object may include fields such as:
+A data model that describes indexing metadata context. The actual context data structure may evolve over time as the needs of the ENSNode stack evolve. The data model may include fields such as:
- `version`: The version of the Indexing Metadata Context structure
-- `indexingStatus`: the current Indexing Status of the [ENSIndexer instance](#ensindexer-instance).
-- `stackInfo`: a group of public config objects that describe the ENSIndexer instance and its dependencies.
+- `indexingStatus`: the current Indexing Status of the [ENSDb Writer](#ensdb-writer) instance (i.e. the [Indexing Status](#indexing-status) of the ENSDb Writer instance).
+- `stackInfo`: describes the [ENSDb Writer](#ensdb-writer) instance and its config, dependencies, etc.
### ENSApi
@@ -165,43 +172,43 @@ A reference implementation of an [ENSDb Reader](#ensdb-reader) that serves Graph
### ENSApi Instance
-A running [ENSApi](#ensapi) process that serves GraphQL and REST APIs from an [ENSDb instance](#ensdb-instance).
+A running [ENSApi](#ensapi) process.
- Any [ENSApi instance](#ensapi-instance) can connect to any [ENSDb instance](#ensdb-instance)
- Multiple [ENSApi instances](#ensapi-instance) can connect to the same [ENSDb instance](#ensdb-instance) for improved availability
### ENSIndexer
-A reference implementation of an [ENSDb Writer](#ensdb-writer) that indexes onchain ENS data and writes to an [ENSDb instance](#ensdb-instance). It is built on top of [Ponder](https://ponder.sh/), a modular blockchain indexing framework.
+A reference implementation of an [ENSDb Writer](#ensdb-writer) that indexes onchain ENS data and writes to an [ENSDb instance](#ensdb-instance). It is built on top of [Ponder](https://ponder.sh/), a modular blockchain indexing framework. ENSIndexer is also an implementation of an [ENSDb Metadata Writer](#ensdb-metadata-writer). It writes metadata about itself into the [ENSNode Metadata Table](#ensnode-metadata-table) in the ENSDb instance.
### ENSIndexer Instance
-A running [ENSIndexer](#ensindexer) process that indexes onchain ENS data and writes to an [ENSIndexer Schema](#ensindexer-schema) in ENSDb.
+A running [ENSIndexer](#ensindexer) process.
-- Each [ENSIndexer instance](#ensindexer-instance) owns exactly one [ENSIndexer Schema](#ensindexer-schema)
-- Each [ENSIndexer instance](#ensindexer-instance) writes to and reads from the [Ponder Schema](#ponder-schema)
+- Each [ENSIndexer instance](#ensindexer-instance) owns exactly one [ENSDb Writer Schema](#ensdb-writer-schema)
+- Each [ENSIndexer instance](#ensindexer-instance) writes to and reads from the shared [Ponder Schema](#ponder-schema)
- Multiple [ENSIndexer instances](#ensindexer-instance) can connect to one [ENSDb instance](#ensdb-instance)
-- Each [ENSIndexer instance](#ensindexer-instance) has a row in the [ENSNode Metadata Table](#ensnode-metadata-table)
+- Each [ENSIndexer instance](#ensindexer-instance) owns exactly one row in the [ENSNode Metadata Table](#ensnode-metadata-table) and writes to it regularly via its [ENSDb Metadata Writer](#ensdb-metadata-writer) implementation.
### Indexing Status
-The status of an [ENSIndexer instance](#ensindexer-instance)'s indexing progress.
+The status of an [ENSDb Writer](#ensdb-writer) instance's indexing progress.
The Indexing Status affects database behavior:
-- During **Backfill**, [indexes](#database-objects) on the [ENSIndexer Schema](#ensindexer-schema), if any, are dropped to optimize write performance.
-- When transitioning to **Following**, [indexes](#database-objects) on the [ENSIndexer Schema](#ensindexer-schema) are created to optimize read performance.
+- During **Backfill**, [indexes](#database-objects) on the [ENSDb Writer Schema](#ensdb-writer-schema), if any, are dropped to optimize write performance.
+- When transitioning to **Following**, indexes on the ENSDb Writer Schema are created to optimize read performance.
## Schema Discovery
-The process of finding all [ENSIndexer Schemas](#ensindexer-schema) in an [ENSDb instance](#ensdb-instance) by querying the [ENSNode Metadata Table](#ensnode-metadata-table):
+The process of finding all ENSDb Writer Schemas in an [ENSDb instance](#ensdb-instance) by querying the [ENSNode Metadata Table](#ensnode-metadata-table):
```sql title="example.sql"
SELECT DISTINCT ens_indexer_schema_name
FROM ensnode.metadata;
```
-This returns all [ENSIndexer Schema Names](#ensindexer-schema-name) that have been used by [ENSIndexer instances](#ensindexer-instance) connected to this [ENSDb instance](#ensdb-instance).
+This returns all ENSDb Writer Schema Names that have been used by [ENSDb Writer](#ensdb-writer) instances ever connected to this [ENSDb instance](#ensdb-instance).
## ENSDb SDK
@@ -209,9 +216,9 @@ A TypeScript package published as [`@ensnode/ensdb-sdk`](https://www.npmjs.com/p
The ENSDb SDK includes:
-- [EnsDbReader Client](#ensdb-reader-client) — An ENSDb client implementation for querying ENSDb Metadata, and building custom queries against the [ENSDb instance](#ensdb-instance).
-- [EnsDbWriter Client](#ensdb-writer-client) — An ENSDb client implementation for writing ENSNode Metadata and executing ENSNode migrations.
-- [Schema Definitions](#schema-definition) — Drizzle schemas for [ENSIndexer Schema](#ensindexer-schema) and [ENSNode Schema](#ensnode-schema).
+- [ENSDb Reader Client](#ensdb-reader-client) — An ENSDb client implementation for querying ENSDb Metadata, and building custom queries against the [ENSDb instance](#ensdb-instance).
+- [ENSDb Writer Client](#ensdb-writer-client) — An ENSDb client implementation for writing ENSNode Metadata and executing ENSNode migrations.
+- [Schema Definitions](#schema-definition) — Drizzle schemas for ENSDb Writer Schema and [ENSNode Schema](#ensnode-schema).
### ENSDb Reader Client
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/index.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/index.mdx
index eddde096b..9fcd94854 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensdb/concepts/index.mdx
@@ -26,13 +26,14 @@ Understanding these fundamentals will help you work effectively with ENSDb, whet
## Next Steps
-After understanding these concepts:
-
-1. **[Query ENSDb with SQL](/docs/services/ensdb/usage/sql)** — Language-agnostic SQL examples
-2. **[Use the TypeScript SDK](/docs/services/ensdb/usage/sdk)** — Type-safe database access
+
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/index.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/index.mdx
index 8859fec04..169013712 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensdb/index.mdx
@@ -7,7 +7,6 @@ sidebar:
---
import { LinkCard, Aside } from "@astrojs/starlight/components";
-import EnsDbUseCases from "@components/molecules/EnsDbUseCases.astro";
## Vision
@@ -29,9 +28,12 @@ The [ENSDb standard](/docs/services/ensdb/concepts/glossary#ensdb-standard) is i
## What You Get
-### Complete ENS State
+### Indexed ENS State
-An **ENSDb instance** contains the **live onchain state of ENS**, including:
+An **ENSDb instance** contains the **live onchain state of ENS**.
+
+:::note[ENSNode plugins define indexed data]
+Depending on the [ENSNode plugins](/docs/integrate/integration-options/ensnode-plugins) activated for your [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer) instance, data indexed in ENSDb may include:
- Domains (ENSv1 and ENSv2)
- Registrations and renewals
@@ -40,6 +42,8 @@ An **ENSDb instance** contains the **live onchain state of ENS**, including:
- NFT/token data for names
- … and more!
+:::
+
### PostgreSQL Benefits
By building on a PostgreSQL database, ENSDb inherits world-class capabilities:
@@ -50,27 +54,15 @@ By building on a PostgreSQL database, ENSDb inherits world-class capabilities:
- Ecosystem — Mature tools, ORMs, dashboards, analytics platforms
- Reliability — Decades of production-proven technology
-## What You Can Build
-
-ENSDb unlocks a new universe of ENS applications:
-
-
-
## Quick Start
-
-
-## Documentation Structure
+## Learn more
## What's next
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations/future-possibilities.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations.mdx
similarity index 50%
rename from docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations/future-possibilities.mdx
rename to docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations.mdx
index 91d1cfd82..b4c08d7d1 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations/future-possibilities.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations.mdx
@@ -1,11 +1,20 @@
---
-title: Future Possibilities
-description: Explore the future possibilities and potential applications of ENSDb in various domains, including custom APIs, analytics, developer tools, event-based engines, data pipelines, and AI agents.
-sidebar:
- label: Future Possibilities
- order: 2
+title: Using ENSDb
+description: Guides for integrating and using ENSDb in your applications.
---
+import { LinkCard } from "@astrojs/starlight/components";
+
+You can interact with the ENSDb instance using the dedicated TypeScript SDK or the regular PostgreSQL interface. This section provides guides for both methods, as well as troubleshooting tips and answers to frequently asked questions.
+
+
+
+## Future possibilities
+
Use an ENSDb instance as an event source for building reactive systems that respond to ENS state changes.
With sub-second query latency and real-time updates, you can build applications that react to registration lifecycle updates, ownership transfers, resolver updates, and more.
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations/ensnode.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/reference-implementation.mdx
similarity index 88%
rename from docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations/ensnode.mdx
rename to docs/ensnode.io/src/content/docs/docs/services/ensdb/reference-implementation.mdx
index c2f44344f..545916fb0 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/integrations/ensnode.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensdb/reference-implementation.mdx
@@ -13,7 +13,7 @@ ENSNode includes initial reference implementations of the [ENSDb standard](/docs
This initial reference implementation consists of three main components:
- An [ENSDb instance](/docs/services/ensdb/concepts/glossary#ensdb-instance) — A PostgreSQL database following the ENSDb standard.
-- An [ENSIndexer instance](/docs/services/ensdb/concepts/glossary#ensindexer-instance) — A reference ENSDb Writer implementation that writes data into the ENSDb instance.
+- An [ENSIndexer instance](/docs/services/ensdb/concepts/glossary#ensindexer-instance) — A reference ENSDb Writer and ENSDb Metadata Writer implementation that writes data into the ENSDb instance.
- An [ENSApi instance](/docs/services/ensdb/concepts/glossary#ensapi-instance) — A reference ENSDb Reader implementation that serves GraphQL and REST APIs.
```mermaid
@@ -25,10 +25,10 @@ flowchart LR
subgraph PostgreSQLServer["PostgreSQL Server instance"]
ENSDb[(ENSDb instance)]
NS(ENSNode Schema)
- EIS(ENSIndexer Schema)
+ EWS(ENSDb Writer Schema)
ENSDb -->|has| NS
- ENSDb -->|has| EIS
+ ENSDb -->|has| EWS
end
end
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/index.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/index.mdx
deleted file mode 100644
index 29861b8de..000000000
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/index.mdx
+++ /dev/null
@@ -1,23 +0,0 @@
----
-title: Using ENSDb
-description: Guides for integrating and using ENSDb in your applications.
-sidebar:
- label: Overview
- order: 1
----
-
-import { LinkCard } from "@astrojs/starlight/components";
-
-You can interact with the ENSDb instance using the dedicated TypeScript SDK or the regular PostgreSQL interface. This section provides guides for both methods, as well as troubleshooting tips and answers to frequently asked questions.
-
-
-
-
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/sdk.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/sdk.mdx
deleted file mode 100644
index f6374a7d0..000000000
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/sdk.mdx
+++ /dev/null
@@ -1,58 +0,0 @@
----
-title: ENSDb SDK
-sidebar:
- label: ENSDb SDK
- order: 2
----
-
-This page provides an overview of the ENSDb SDK and how to use it in your applications.
-
-## Intro
-
-For TypeScript projects, the [ENSDb SDK](/docs/services/ensdb/concepts/glossary#ensdb-sdk) provides a convenient and efficient way to interact with your ENSDb instance.
-
-### Installation
-
-You can install the [`@ensnode/ensdb-sdk`](https://www.npmjs.com/package/@ensnode/ensdb-sdk) package from the NPM registry, using your preferred package manager:
-
-```bash
-npm install @ensnode/ensdb-sdk
-pnpm install @ensnode/ensdb-sdk
-yarn add @ensnode/ensdb-sdk
-```
-
-### Example Usage
-
-Canonical fields (`canonicalName`, `canonicalPath`, `canonicalNode`, `canonicalDepth`) are
-populated on every Domain reachable from the canonical root, across both ENSv1 and ENSv2 — query
-them uniformly without branching by `type`.
-
-```typescript title="example.ts"
-import { EnsDbReader, IndexingMetadataContextStatusCodes } from "@ensnode/ensdb-sdk";
-import { count, eq } from "drizzle-orm";
-
-// Connect to a specific ENSDb instance by providing its connection string and
-// the ENSIndexer Schema Name you want to query
-const ensDbReader = new EnsDbReader(ensDbConnectionString, ensIndexerSchemaName);
-const { ensDb, ensIndexerSchema } = ensDbReader;
-
-// Fetch a Domain by its canonical name
-const [vitalik] = await ensDb
- .select()
- .from(ensIndexerSchema.domain)
- .where(eq(ensIndexerSchema.domain.canonicalName, "vitalik.eth"));
-
-// Count an address's Domains, grouped by Domain type (ENSv1 vs ENSv2)
-const counts = await ensDb
- .select({ type: ensIndexerSchema.domain.type, count: count() })
- .from(ensIndexerSchema.domain)
- .where(eq(ensIndexerSchema.domain.ownerId, "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"))
- .groupBy(ensIndexerSchema.domain.type);
-
-// Get indexing status snapshot
-const indexingMetadataContext = await ensDbReader.getIndexingMetadataContext();
-if (indexingMetadataContext.statusCode === IndexingMetadataContextStatusCodes.Initialized) {
- const indexingStatusSnapshot = indexingMetadataContext.indexingStatus;
- // Do something with the indexing status snapshot
-}
-```
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/sql.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/sql.mdx
deleted file mode 100644
index 54bd20d7c..000000000
--- a/docs/ensnode.io/src/content/docs/docs/services/ensdb/usage/sql.mdx
+++ /dev/null
@@ -1,59 +0,0 @@
----
-title: ENSDb SQL
-sidebar:
- label: ENSDb SQL
- order: 3
----
-
-## Intro
-
-This page provides an overview of the ENSDb SQL interface and how to use it in your applications.
-
-## Example Queries
-
-### Connect with Any PostgreSQL Client
-
-Connect to an ENSDb instance (a PostgreSQL database). The examples below assume you that ENSDb instances are served from a PostgreSQL server at `host:5432` with databases named `ensdb_mainnet`, `ensdb_testnet`, and `ensdb_devnet`:
-
-```bash
-# Production environment (mainnet data)
-psql postgresql://user:password@host:5432/ensdb_mainnet
-
-# Pre-production environment (testnet data)
-psql postgresql://user:password@host:5432/ensdb_testnet
-
-# Staging / local development environment
-psql postgresql://user:password@host:5432/ensdb_devnet
-```
-
-### Discover Available Schemas
-
-Once connected to an ENSDb instance, discover its ENSIndexer Schemas:
-
-```sql title="discover-schemas.sql"
-SELECT DISTINCT ens_indexer_schema_name
-FROM ensnode.metadata;
-```
-
-### Query Data
-
-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`.
-
-```sql title="example.sql"
--- Fetch a Domain by its canonical name
-SELECT * FROM ensindexer_0.domains
-WHERE canonical_name = 'vitalik.eth';
-
--- Count an address's Domains, grouped by Domain type (ENSv1 vs ENSv2)
-SELECT type, count(*) FROM ensindexer_0.domains
-WHERE owner_id = '0xd8da6bf26964af9d7eed9e03e53415d37aa96045'
-GROUP BY type;
-
--- Get indexing status snapshot for the ENSNode Schema with the `ensindexer_0` ENSIndexer Schema Name
-SELECT value -> 'indexingStatus' FROM "ensnode"."metadata"
-WHERE ens_indexer_schema_name = 'ensindexer_0'
-AND key = 'indexing_metadata_context'
-AND value -> 'indexingStatus' -> 'omnichainSnapshot' ->> 'omnichainStatus' = 'omnichain-backfill';
-```
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensindexer/concepts/startup-sequence.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensindexer/concepts/startup-sequence.mdx
index c79847009..f3339a755 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensindexer/concepts/startup-sequence.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensindexer/concepts/startup-sequence.mdx
@@ -10,26 +10,26 @@ Below are diagrams describing the ENSIndexer startup sequence.
## Ponder app lifecycle
-Here is an overview of the ENSIndexer startup sequence. It summarizes the Ponder app lifecycle running inside an ENSIndexer instance. The example assumes that the ENSIndexer was started with the `ENSINDEXER_SCHEMA_NAME` environment variable set to `prod_0`, but the same sequence applies to any ENSIndexer Schema.
+Here is an overview of the ENSIndexer startup sequence. It summarizes the Ponder app lifecycle running inside an ENSIndexer instance. The example assumes that the ENSIndexer was started with the `ENSINDEXER_SCHEMA_NAME` environment variable (which defines the [ENSDb Writer Schema Name](/docs/services/ensdb/concepts/glossary#ensdb-writer-schema-name)) set to the `prod_0` value, but the same sequence applies to any value provided.
[](/ensindexer/startup-sequence/0-overview.png)
-## ENSIndexer schema migrations
+## ENSDb Writer Schema migrations
-When the Ponder app lifecycle reaches the step for "Execute migrations for the `prod_0` ENSIndexer Schema", Ponder will execute any pending migrations for the `prod_0` ENSIndexer Schema.
-This ensures that the ENSIndexer Schema is up to date before indexing onchain events start.
+When the Ponder app lifecycle reaches the step for "Execute migrations for the `prod_0` ENSDb Writer Schema" (previously called "Execute migrations for the `prod_0` ENSIndexer Schema"), Ponder will execute any pending migrations for the `prod_0` ENSDb Writer Schema.
+This ensures that the ENSDb Writer Schema is up to date before indexing onchain events start.
- [](/ensindexer/startup-sequence/1-ensindexer-schema-migrations.png)
## Omnichain indexing strategy
-When the Ponder app lifecycle reaches the step to "Run omnichain indexing strategy", Ponder will start writing data concurrently to the Ponder Schema (caching RPC calls) and the ENSIndexer Schema (storing indexed data). The ENSIndexer app lifecycle "injects" a special step for "Execute onchain event handlers preconditions".
+When the Ponder app lifecycle reaches the step to "Run omnichain indexing strategy", Ponder will start writing data concurrently to the Ponder Schema (caching RPC calls) and the ENSDb Writer Schema (storing indexed data). The ENSIndexer app lifecycle "injects" a special step for "Execute onchain event handlers preconditions".
[ that implements [ENSNode plugins](/docs/integrate/integration-options/ensnode-plugins). The code for each plugin inside ENSIndexer is a reference implementation of that plugin's abstract specification.
-ENSNode is extensible through ENSIndexer plugins that implement custom indexing logic and produce custom indexed data models inside ENSDb. This allows you to tailor ENSNode to your specific use case and data needs.
+For the full specification of ENSNode plugins and how they enable decoupling between [ENSDb Writers](/docs/integrate/integration-options/ensdb-writers) and [ENSDb Readers](/docs/integrate/integration-options/ensdb-readers), see the [ENSNode Plugins](/docs/integrate/integration-options/ensnode-plugins) integration guide.
-ENSIndexer will only activate the plugins you specify in the `PLUGINS` env variable, so you can choose to only activate the plugins that are relevant to your use case. The `PLUGINS` env variable accepts a comma-separated list of plugin names to be activated. For example, if you want to activate the `ensv2` and `protocol-acceleration` plugins, you can set `PLUGINS=ensv2,protocol-acceleration`.
+
-## Plugin Architecture
+## How ENSIndexer implements ENSNode plugins
-Each ENSIndexer plugin is a standalone TypeScript module that can be developed, tested, and deployed independently. The ENSIndexer Plugin can define its own indexed data models and indexing logic. It must include two main files:
+ENSNode is extensible through ENSNode Plugins. You can have your ENSIndexer implement custom indexing logic and produce custom indexed data models inside ENSDb. This allows you to tailor ENSNode to your specific use case and data needs.
-- `event-handlers.ts`: This file defines the event handlers for the plugin, which are functions that will be called when specific onchain events are indexed. The event handlers contain the logic for how to process the indexed data and store it in the relevant indexed data model inside the ENSIndexer Schema.
+ENSIndexer will only activate the ENSNode Plugins which you specify in the `PLUGINS` env variable, so you can choose to only activate the plugins that are relevant to your use case. The `PLUGINS` env variable accepts a comma-separated list of plugin names to be activated. For example, if you want to activate the `unigraph` and `protocol-acceleration` plugins, you can set `PLUGINS=unigraph,protocol-acceleration`.
+
+## Plugin implementation structure
+
+Each ENSNode Plugin implemented in ENSIndexer is a standalone TypeScript module that can be developed and tested independently, while all ENSNode Plugins are deployed together as part of the single ENSIndexer service and activated via the `PLUGINS` environment variable. The ENSNode Plugin can define its own indexed data models and indexing logic. It must include two main files:
+
+- `event-handlers.ts`: This file defines the event handlers for the plugin, which are functions that will be called when specific onchain events are indexed. The event handlers contain the logic for how to process the indexed data and store it in the relevant indexed data model inside the [ENSDb Writer Schema](/docs/services/ensdb/concepts/glossary#ensdb-writer-schema).
- `plugin.ts`: This file defines the plugin itself, including its name, description, and any configuration options, like datasources to be used for specifying onchain contracts that will be indexed.
### Event handlers
@@ -32,11 +42,3 @@ You need to import the `event-handlers.ts` file from each plugin into [`register
The `plugin.ts` file has a default export with the plugin definition object returned from `createPlugin` function. The plugin definition object includes the plugin name, datasources required for the plugin to operate, and the config for contracts to be indexed by ENSIndexer when the plugin is active.
You need to import the plugin definition object into [`apps/ensindexer/src/plugins/index.ts`](https://github.com/namehash/ensnode/tree/main/apps/ensindexer/src/plugins/index.ts) file and have it included in the `ALL_PLUGINS` array. This way, you let the ENSIndexer runtime know that the plugin is available for activation, which in turn allows you to activate the plugin by including its name in the `PLUGINS` env variable.
-
-## Existing Plugins
-
-You can find the current list of existing ENSIndexer plugins in [the ENSIndexer repository](https://github.com/namehash/ensnode/tree/main/apps/ensindexer/src/plugins).
-
-## Creating Your Own Plugin
-
-If you’re interested in building a plugin, reach out to the NameHash Labs team who is happy to provide support and additional info.
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensindexer/index.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensindexer/index.mdx
index 7e3bee2be..f89ae2242 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensindexer/index.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensindexer/index.mdx
@@ -8,7 +8,7 @@ sidebar:
import { LinkCard } from "@astrojs/starlight/components";
-ENSIndexer is a [Ponder](https://ponder.sh) app that indexes ENS contracts across multiple chains. It processes events from each relevant chain and transforms the data, storing it in your Postgres database.
+ENSIndexer is a reference implementation of an [ENSDb Writer](/docs/services/ensdb/concepts/glossary#ensdb-writer). It uses [Ponder](https://ponder.sh) for indexing ENS state from contracts across multiple chains. It processes events from each relevant chain and transforms the data, storing it in your ENSDb instance.
:::note
While ENSIndexer can be run independently in certain scenarios, it is designed to work as part of the complete ENSNode system, and we recommend following the [ENSNode Contribution Guide](/docs/reference/contributing) if you'd like to run ENSIndexer locally, or the [ENSNode Deployment Guide](/docs/self-host) if you'd like to run ENSIndexer in the cloud.
diff --git a/docs/ensnode.io/src/content/docs/docs/services/ensindexer/usage/management.mdx b/docs/ensnode.io/src/content/docs/docs/services/ensindexer/usage/management.mdx
index 3f8c2a0f7..a45d8f1c2 100644
--- a/docs/ensnode.io/src/content/docs/docs/services/ensindexer/usage/management.mdx
+++ b/docs/ensnode.io/src/content/docs/docs/services/ensindexer/usage/management.mdx
@@ -7,21 +7,21 @@ sidebar:
## Database operations
-Each instance of ENSIndexer maintains its own ENSIndexer Schema instance in ENSDb. The same ENSIndexer instance will always use the same ENSIndexer Schema, even after restarts. However, if you need to update an ENSIndexer config, or deploy a new version of ENSIndexer, you will have to update the `ENSINDEXER_SCHEMA_NAME` env variable to point to a new schema, as otherwise, the ENSIndexer instance will detect that the ENSIndexer Schema was already owned by an ENSIndexer instance with different config / indexing logic and will refuse to start. These measures are taken to protect the state invariants indexing event handlers expect and require.
+Each instance of ENSIndexer maintains its own ENSDb Writer Schema instance in ENSDb. The same ENSIndexer instance will always use the same ENSDb Writer Schema, even after restarts. However, if you need to update an ENSIndexer config, or deploy a new version of ENSIndexer, you will have to update the `ENSINDEXER_SCHEMA_NAME` env variable to point to a new schema, as otherwise, the ENSIndexer instance will detect that the ENSDb Writer Schema was already owned by an ENSIndexer instance with different config / indexing logic and will refuse to start. These measures are taken to protect the state invariants indexing event handlers expect and require.
-### ENSIndexer Schema lifecycle
+### ENSDb Writer Schema lifecycle
- Let's say you're currently running ENSNode version X that's indexing into `ENSINDEXER_SCHEMA_NAME=myschema_X`
- Now, when you upgrade to ENSNode version Y, if you try to continue using `ENSINDEXER_SCHEMA_NAME=myschema_X` then ENSIndexer will immediately terminate with an error because indexing logic or config will be different.
- Therefore, you must update the `ENSINDEXER_SCHEMA_NAME` to `myschema_Y`, which will:
- Build a completely new index from scratch into `myschema_Y` which may grow to become 100+ GB depending on how ENSIndexer is configured.
- Still retain all the data in `myschema_X` which could also be 100+ GB...
-- Now imagine you repeat this process across multiple updates to your `ENSINDEXER_SCHEMA_NAME`, you might have hundreds and hundreds of GB of ENSIndexer Schema instances no longer in use that are just taking up disk space in ENSDb instance until you completely run out of disk space.
-- The solution is that you need to manually delete all the old ENSIndexer Schema instances in your ENSDb instance you no longer use.
+- Now imagine you repeat this process across multiple updates to your `ENSINDEXER_SCHEMA_NAME`, you might have hundreds and hundreds of GB of ENSDb Writer Schema instances no longer in use that are just taking up disk space in ENSDb instance until you completely run out of disk space.
+- The solution is that you need to manually delete all the old ENSDb Writer Schema instances in your ENSDb instance you no longer use.
-### Dropping orphaned ENSIndexer Schemas
+### Dropping orphaned ENSDb Writer Schemas
-If your ENSDb instance has orphaned ENSIndexer Schemas that you no longer use, you can drop them with a SQL command like the following:
+If your ENSDb instance has orphaned ENSDb Writer Schemas that you no longer use, you can drop them with a SQL command like the following:
:::danger[`DROP SCHEMA ... CASCADE` is a destructive operation!]
Once executed, this operation is irreversible. Double-check your database connection and schema name before running this in production.