Skip to content

fix: re-enable subgraph_domain.name indexes (hash + gin trigram)#1856

Merged
shrugs merged 14 commits intomainfrom
fix/name-index
Apr 20, 2026
Merged

fix: re-enable subgraph_domain.name indexes (hash + gin trigram)#1856
shrugs merged 14 commits intomainfrom
fix/name-index

Conversation

@shrugs
Copy link
Copy Markdown
Member

@shrugs shrugs commented Mar 31, 2026

Summary

  • replace the previously-disabled btree index on subgraph_domain.name with a hash index (exact-match lookups that bypass the btree 8191-byte row size limit) and a gin trigram index (gin_trgm_ops) for partial-match filters _contains, _starts_with, _ends_with.
  • install the pg_trgm extension via a new Drizzle migration (0001_enable_ext_pg_trgm.sql) that runs through migrateEnsNodeSchema() before Ponder starts up.
  • doc updates in contributing, deploy (docker, terraform), and running guides noting the pg_trgm requirement.

Why

closes the remaining work from #1819. measured on mainnet, the gin index is ~1.2 GB (~19% of heap) — within typical range for a text trigram index, not pathological.

Testing

  • pnpm -F ensindexer -F @ensnode/ensdb-sdk typecheck — clean
  • pnpm lint:ci — clean
  • pnpm test --project ensindexer --project @ensnode/ensdb-sdk — unit tests pass
  • docs site astro build — clean (69 pages)
  • integration tests pass end-to-end (setup → backfill → createIndexes).

Notes for Reviewer

  • the install lives in a Drizzle migration because migrations run with the default search_path (which includes public), so unqualified CREATE EXTENSION IF NOT EXISTS pg_trgm lands in public and Ponder's write-path connection resolves the unqualified gin_trgm_ops at index-creation time. doing this in the runtime setup hook was more fragile (see earlier commits in this PR for the search_path rabbit-hole).
  • drizzle's .op("gin_trgm_ops") gets dropped by ponder's index emitter, so the gin index is declared via a raw sql fragment (index().using("gin", sql${t.name} gin_trgm_ops)).
  • known follow-up: gin trigram indexes every name, and pathological 8KB spam names add ~500-1000× the trigrams of a normal name. measured impact on mainnet is modest (~19% of heap, ~1.2 GB). a partial index (e.g. WHERE length(name) < 2048) is a reasonable follow-up if this grows.

Checklist

  • This PR does not change runtime behavior or semantics
  • This PR is low-risk and safe to review quickly

Copilot AI review requested due to automatic review settings March 31, 2026 20:41
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 31, 2026

🦋 Changeset detected

Latest commit: dec0101

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 24 packages
Name Type
ensindexer Major
@ensnode/ensdb-sdk Major
ensapi Major
@ensnode/integration-test-env Patch
ensadmin Major
ensrainbow Major
fallback-ensapi Major
enssdk Major
enscli Major
enskit Major
ensskills Major
@ensnode/datasources Major
@ensnode/ensrainbow-sdk Major
@ensnode/ensnode-react Major
@ensnode/ensnode-sdk Major
@ensnode/ponder-sdk Major
@ensnode/ponder-subgraph Major
@ensnode/shared-configs Major
@docs/ensnode Major
@docs/ensrainbow Major
@docs/mintlify Major
@namehash/ens-referrals Major
@namehash/namehash-ui Major
@ensnode/enskit-react-example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ensnode.io Ready Ready Preview, Comment Apr 17, 2026 8:27pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Apr 17, 2026 8:27pm
ensrainbow.io Skipped Skipped Apr 17, 2026 8:27pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 31, 2026

Warning

Rate limit exceeded

@shrugs has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 5 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 8 minutes and 5 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 60f60bdc-5d34-4068-b18e-340e76993ac7

📥 Commits

Reviewing files that changed from the base of the PR and between 427ff54 and dec0101.

📒 Files selected for processing (7)
  • .changeset/hash-and-trigram-name-indexes.md
  • docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx
  • docs/ensnode.io/src/content/docs/docs/running/index.mdx
  • packages/ensdb-sdk/migrations/0001_enable_ext_pg_trgm.sql
  • packages/ensdb-sdk/migrations/meta/0001_snapshot.json
  • packages/ensdb-sdk/migrations/meta/_journal.json
  • packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts
📝 Walkthrough

Walkthrough

Replaced the disabled byName index with a new byExactName (hash) index and added a byFuzzyName GIN trigram index on subgraph_domain.name; added a changeset to reintroduce these indexes and require pg_trgm; runtime setup ensures pg_trgm is created; tests mock ENSDB execute and logger.

Changes

Cohort / File(s) Summary
Schema: name indexes
packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts
Replaced commented byName with byExactName (hash on t.name) and added byFuzzyName (GIN with gin_trgm_ops using sql opclass injection).
Changeset
.changeset/hash-and-trigram-name-indexes.md
New changeset documenting minor version bump, dual-index strategy (hash + GIN trigram) and note to ensure pg_trgm.
Runtime setup: pg_trgm
apps/ensindexer/src/lib/indexing-engines/ponder.ts
Added initialization step that runs CREATE EXTENSION IF NOT EXISTS pg_trgm via ensDbClient.ensDb.execute(...) with debug/info logging and wrapped error handling.
Tests: ENSDB & logger mocks
apps/ensindexer/src/lib/indexing-engines/ponder.test.ts
Added global logger mock and a hoisted mock for ENSDB execute via vi.mock(...); resets mock before each test and updated test description for :setup behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Ponder as Ponder setup
    participant Logger as Logger
    participant EnsDB as ensDbClient
    participant Indexer as Index creation

    Note over Ponder,Logger: initialization start
    Ponder->>Logger: debug("starting setup")
    Ponder->>EnsDB: execute("CREATE EXTENSION IF NOT EXISTS pg_trgm")
    EnsDB-->>Ponder: success / error
    alt success
        Ponder->>Logger: info("pg_trgm ensured")
        Ponder->>Indexer: proceed to create indexes (hash + gin_trgm_ops)
        Indexer-->>Ponder: indexes created
    else failure
        EnsDB-->>Logger: error
        Ponder-->>Logger: error("extension creation failed", cause)
        Ponder-->>Ponder: throw Error(cause)
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

Poem

🐰 I hopped through code with nimble paws,
Swapped b-tree dreams for hash-smart laws.
Trigrams hum when searches roam,
pg_trgm planted — indexes come home. 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: re-enabling indexes on subgraph_domain.name using both hash and GIN trigram approaches.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Description check ✅ Passed The PR description follows the template with all required sections completed: Summary (3 bullets), Why (issue reference), Testing (multiple test types), and Notes for Reviewer (implementation details).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/name-index

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Re-enables an index on subgraph_domains.name in the ENS subgraph-compatible Ponder/Drizzle schema, switching from a btree index to a hash index to avoid Postgres’ btree index-row size limit when spam/oversized names are present.

Changes:

  • Add a hash index on subgraph_domains.name (byExactName) to support exact-match lookups without hitting the btree 8191-byte limit.
  • Remove the prior commented-out/disabled byName index block.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts
@tk-o
Copy link
Copy Markdown
Member

tk-o commented Apr 1, 2026

The update looks good to me 👍 As discussed on Slack, it'd great to enable the pg_trgm extension for ENSDb within the prepareIndexingSetup function that will be added in PR #1843.

Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shrugs Hey shared a suggestion. Please feel welcome to merge when ready 🫡

Comment thread packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts
@tk-o
Copy link
Copy Markdown
Member

tk-o commented Apr 9, 2026

@shrugs feel free to have the required pg extension enabled with ENSDb migrations. It's a nice approach that ensures that the extension will be enabled just once for the single ENSDb instance.

You can create the migration file like so: pnpm -F @ensnode/ensdb-sdk drizzle-kit:generate --custom --name=enable_ext_pg_trgm and include the relevant SQL query in it:

-- This migration enables the pg_trgm extension, which is used for
-- trigram-based indexing and searching in PostgreSQL.
CREATE EXTENSION IF NOT EXISTS pg_trgm;

shrugs added 2 commits April 17, 2026 10:41
…ain.name

Use the existing `initializeIndexingSetup` hook to install the `pg_trgm`
extension before Ponder creates indexes, then re-introduce the GIN
trigram index (`gin_trgm_ops`) on `subgraph_domain.name` to back the
Subgraph GraphQL partial-match filters (`_contains`, `_starts_with`,
`_ends_with`). The hash index added previously is retained for exact
equality lookups; the trigram index covers partial matches.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 17, 2026

Greptile Summary

This PR re-enables the subgraph_domain.name indexes that were disabled in #1819, replacing the single btree index (which hit Postgres's 8191-byte row-size limit for long spam names) with a hash index for exact-match lookups and a GIN trigram index (gin_trgm_ops) for partial-match filters. A Drizzle migration (0001_enable_ext_pg_trgm.sql) is added to install the pg_trgm extension before Ponder starts, and four doc pages are updated to document the new Postgres prerequisite.

Confidence Score: 5/5

Safe to merge — changes are additive (new indexes + extension install), idempotent, and integration-tested end-to-end.

All findings are P2 or informational. The hash + GIN index combination correctly solves the btree row-size limit. The pg_trgm migration is idempotent and correctly placed in the Drizzle migrator so the extension is available before Ponder creates the GIN index. Documentation updates are consistent across all four relevant doc pages.

No files require special attention.

Important Files Changed

Filename Overview
packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts Replaces the commented-out btree index with a hash index for exact-match and a GIN trigram index via raw sql fragment; both handle nullable names correctly.
packages/ensdb-sdk/migrations/0001_enable_ext_pg_trgm.sql Idempotent CREATE EXTENSION IF NOT EXISTS pg_trgm migration; correct approach for installing into public so gin_trgm_ops is resolvable by Ponder's write-path connection.
packages/ensdb-sdk/migrations/meta/_journal.json Journal correctly appended with idx=1 migration entry; version and breakpoints consistent with the existing entry.
packages/ensdb-sdk/migrations/meta/0001_snapshot.json Snapshot reflects only Drizzle-managed tables (ensnode.metadata); correctly unchanged since the migration only installs an extension, not new tables.
docs/ensnode.io/src/content/docs/docs/contributing/index.mdx Adds inline pg_trgm prerequisite note to the contributing prerequisites list; accurate and concise.
docs/ensnode.io/src/content/docs/docs/deploying/docker.mdx Adds a Starlight :::note block explaining the pg_trgm requirement for swapped-out Postgres images; consistent wording with other docs.
docs/ensnode.io/src/content/docs/docs/deploying/terraform.mdx Adds pg_trgm requirement note specific to Render's managed Postgres; correctly notes the extension is available by default on Render.
docs/ensnode.io/src/content/docs/docs/running/index.mdx Adds pg_trgm requirement note at the top of the running guide; wording consistent with contributing and docker docs.

Sequence Diagram

sequenceDiagram
    participant API as api/index.ts
    participant M as migrateEnsNodeSchema()
    participant DB as Postgres (ensnode schema)
    participant P as Ponder (createIndexes)

    API->>M: call (async, fire-and-forget)
    M->>DB: Drizzle migrate()<br/>(migrationsSchema: "ensnode")
    DB->>DB: CREATE EXTENSION IF NOT EXISTS pg_trgm<br/>(lands in public schema)
    DB-->>M: migration complete
    M-->>API: .then(startEnsDbWriterWorker)
    Note over P: Ponder index-creation phase
    P->>DB: CREATE INDEX USING hash (name)
    P->>DB: CREATE INDEX USING gin (name gin_trgm_ops)<br/>(resolves gin_trgm_ops from public)
    DB-->>P: indexes created
Loading

Reviews (2): Last reviewed commit: "fix: address PR review nits" | Re-trigger Greptile

Comment thread apps/ensindexer/src/lib/indexing-engines/ponder.test.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/ensindexer/src/lib/indexing-engines/ponder.ts Outdated
Comment thread packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts Outdated
Comment thread apps/ensindexer/src/lib/indexing-engines/ponder.test.ts Outdated
Comment thread .changeset/hash-and-trigram-name-indexes.md Outdated
Call out that any Postgres instance used as ENSDb must have the
`pg_trgm` extension available for installation, since ENSIndexer
runs `CREATE EXTENSION IF NOT EXISTS pg_trgm` at startup to back
the partial-name search indexes on `subgraph_domain.name`.
The idempotency and error-propagation tests for the pg_trgm install
re-exercise the shared `eventHandlerPreconditions` promise-caching
mechanism, which is already covered by the ENSRainbow onchain-path
tests. The SQL-content assertion tested an implementation detail that
a source-level review catches more cheaply. Keep the ensDb singleton
and logger mocks — they're needed for the module to load cleanly
under vitest, not for coverage.
Copilot AI review requested due to automatic review settings April 17, 2026 16:01
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 17, 2026 16:01 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 17, 2026 19:58 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 17, 2026 19:58 Inactive
Copilot AI review requested due to automatic review settings April 17, 2026 20:09
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 17, 2026 20:09 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 17, 2026 20:09 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 17, 2026 20:09 Inactive
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/ensdb-sdk/migrations/0001_enable_ext_pg_trgm.sql
Comment thread packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts Outdated
Comment thread .changeset/hash-and-trigram-name-indexes.md
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 17, 2026 20:25 Inactive
@vercel vercel Bot temporarily deployed to Preview – ensnode.io April 17, 2026 20:25 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 17, 2026 20:25 Inactive
- import `sql` from ponder instead of drizzle-orm for consistency with
  other schema files in ensdb-sdk (ensv2.schema.ts does the same)
- rephrase pg_trgm managed-provider note from "enabled by default"
  (inaccurate — pg_trgm is per-database `CREATE EXTENSION`) to
  "available for installation" to match the rest of the docs
Copilot AI review requested due to automatic review settings April 17, 2026 20:26
@vercel vercel Bot temporarily deployed to Preview – ensrainbow.io April 17, 2026 20:26 Inactive
@vercel vercel Bot temporarily deployed to Preview – admin.ensnode.io April 17, 2026 20:26 Inactive
@shrugs
Copy link
Copy Markdown
Member Author

shrugs commented Apr 17, 2026

@greptile re-review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/ensdb-sdk/src/ensindexer-abstract/subgraph.schema.ts
Copy link
Copy Markdown
Member

@tk-o tk-o left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Copy Markdown
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shrugs Looks nice! Just 1 question. Please take the lead to merge when ready 👍

// For more details, see: https://github.com/namehash/ensnode/issues/1819
// byName: index().on(t.name),
// uses a hash index because some name values exceed the btree max row size (8191 bytes)
byExactName: index().using("hash", t.name),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised no other code is updated in relation to us making the schema changes here? Ex: code in API handlers?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none! postgres planner will use the indexes without specification

@shrugs shrugs merged commit fc88ee5 into main Apr 20, 2026
23 checks passed
@shrugs shrugs deleted the fix/name-index branch April 20, 2026 15:51
@github-actions github-actions Bot mentioned this pull request Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants