Configuring ENSIndexer
ENSIndexer requires private RPC endpoints. Public (rate limited) RPC endpoints will not provide acceptable performance.
You must configure private (paid) RPC services from providers like Alchemy, QuickNode, drpc.org, or Infura or host your own RPC service that can handle high-volume requests.
Warning: Configuring ENSIndexer to use the public ENSRainbow server (https://api.ensrainbow.io) will significantly slow down indexing.
For optimal indexing performance, always colocate ENSIndexer and ENSRainbow. For example, if you are running ENSIndexer locally, you should also run a local instance of ENSRainbow and set ENSRAINBOW_URL to your local ENSRainbow server.
ENSIndexer’s behavior can be configured through environment variables. Copy .env.local.example to .env.local and configure all required values.
# The port ENSIndexer serves its API on.# Optional. If this is not set, the default value is Ponder's default of 42069.# PORT=42069
# RPC configuration# Required. When ENSIndexer starts up it verifies RPCs are defined for each of the chains# that are to be indexed based on the configured NAMESPACE and PLUGINS, along with the ENS Root Chain.## NOTE: You must configure your own private RPC endpoints.# ENSIndexer makes millions of RPC requests during operation.# Public RPC endpoints are rate limited and will not provide acceptable performance.# You must use only private (paid) RPC endpoints or your own self-hosted RPC service# that is prepared to support millions of requests (ex: 500+ requests / second)## Each configured RPC endpoint must be prepared to receive and quickly# process millions of RPC requests. High-volume RPC service options include:# - Alchemy (paid plan) - https://www.alchemy.com/# - QuickNode (paid plan) - https://www.quicknode.com# - drpc.org (paid plan) - https://drpc.org/# - Infura (paid plan) - https://infura.io/## Example RPC endpoint URL formats:# - Alchemy RPC endpoints# - https://eth-mainnet.g.alchemy.com/v2/<alchemy-api-key># - wss://eth-mainnet.g.alchemy.com/v2/<alchemy-api-key># - https://base-sepolia.g.alchemy.com/v2/<alchemy-api-key># - QuickNode RPC endpoints# - https://<quicknode-endpoint-name>.quiknode.pro/<quicknode-api-key># - wss://<quicknode-endpoint-name>.quiknode.pro/<quicknode-api-key># - https://<quicknode-endpoint-name>.base-sepolia.quiknode.pro/<quicknode-api-key># - dRPC RPC endpoints# - https://lb.drpc.live/ethereum/<drpc-api-key># - wss://lb.drpc.live/ethereum/<drpc-api-key># - https://lb.drpc.live/base-sepolia/<drpc-api-key># - Infura RPC endpoints# - https://mainnet.infura.io/v3/<infura-api-key># - wss://mainnet.infura.io/ws/v3/<infura-api-key># - https://base-sepolia.infura.io/v3/<infura-api-key>## Configuring the following environment variables enables auto-generation of# RPC endpoint URLs for each indexed chain (with limitations as noted below):# - ALCHEMY_API_KEY — ALCHEMY_API_KEY — API key for your Alchemy app, if set, Alchemy RPC URLs (HTTP & WS) will be autogenerated for chains Alchemy supports.# - QUICKNODE_API_KEY - API key for your multi-chain QuickNode endpoint.# - QUICKNODE_ENDPOINT_NAME — endpoint name of your multi-chain QuickNode endpoint.# - DRPC_API_KEY — if set, an dRPC RPC URL (HTTP) will be autogenerated for chains dRPC supports.# - RPC_URL_${chainId} — specific, per-chain RPC settings.## If both, QUICKNODE_API_KEY and QUICKNODE_ENDPOINT_NAME are specified,# a QuickNode RPC URL will be autogenerated for chains QuickNode supports.# If only one of QUICKNODE_API_KEY or QUICKNODE_ENDPOINT_NAME is set but not the other,# the configuration will be rejected with an error.# Note key constraints of QuickNode RPC endpoints:# - Only multi-chain QuickNode endpoints can be used for setting# QUICKNODE_API_KEY and QUICKNODE_ENDPOINT_NAME environment variables.# A multi-chain endpoint allows sharing the same endpoint name and API key# across all chains supported by QuickNode platform. Read more in QuickNode docs:# https://www.quicknode.com/guides/quicknode-products/how-to-use-multichain-endpoint# - QuickNode platform does not support Linea Sepolia RPC (as of 2025-12-03).# https://www.quicknode.com/docs/linea## Each RPC_URL_${chainId} environment variable, if specified, will take precedence over# all auto-generated RPC URLs for the specified chainId from Alchemy, QuickNode, or dRPC.# It must be a comma-separated list of HTTP/HTTPS RPC endpoints.# ENSIndexer provides all the resulting RPC URLs to Ponder. If multiple HTTP RPC URLs are provided to Ponder,# Ponder automatically balances requests between them (see below).
# Auto-generated RPC URLs:# ALCHEMY_API_KEY=xyz# QUICKNODE_API_KEY=your-api-key# QUICKNODE_ENDPOINT_NAME=your-endpoint-name# DRPC_API_KEY=xyz## For full control of chain-specific RPC configuration, use the RPC_URL_{chainId} environment variable.# Its value is a comma-separated list of one or more HTTP RPC URLs and at most one WebSocket RPC URL.## Example (single HTTP RPC URL):# RPC_URL_1=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY# RPC_URL_11155111=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY## Example (multiple HTTP RPC URL, single WebSocket RPC URL):# RPC_URL_1=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY,https://lb.drpc.org/ethereum/YOUR_API_KEY# RPC_URL_11155111=https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY,https://lb.drpc.org/ethereum-sepolia/YOUR_API_KEY## The RPC_URL_${chainId} value has the following invariants:# - Must always include at least one HTTP/HTTPS RPC endpoint. RPC endpoints can# fail or experience downtime. To optimize resiliency of ENSIndexer,# defining more than one HTTP/HTTPS endpoint (from more than one RPC provider)# per indexed chain is strongly encouraged.# - Can include at most one WS/WSS (websocket) RPC endpoint. A WS/WSS (websocket)# RPC endpoint per indexed chain is optional. If defined it may optimize# the time to discover new blocks. Independent of a websocket RPC endpoint# being defined, Ponder automatically polls the HTTP/HTTPS RPC endpoint for# a chain to discover new blocks at an interval.## To optimize performance, Ponder automatically adapts to the rate limits (429 errors) of each# provided HTTP/HTTPS RPC. More details at: https://ponder.sh/docs/config/chains#rpc-endpoints#
# === ENS Namespace: Mainnet ===# Ethereum Mainnet# - required if the configured namespace is mainnet# - required by plugins: subgraph, protocol-acceleration, registrars, tokenscope# RPC_URL_1=
# Optimism Mainnet# - required by plugins: threedns, protocol-acceleration, tokenscope# RPC_URL_10=
# Base Mainnet# - required by plugins: basenames, threedns, protocol-acceleration, registrars, tokenscope# RPC_URL_8453=
# Arbitrum Mainnet# - required by plugins: protocol-acceleration# RPC_URL_42161=
# Linea Mainnet# - required by plugins: lineanames, protocol-acceleration, registrars, tokenscope# RPC_URL_59144=
# Scroll Mainnet# - required by plugins: protocol-acceleration# RPC_URL_534352=
# === ENS Namespace: Sepolia ===# Ethereum Sepolia (public testnet)# - required if the configured namespace is sepolia# - required by plugins: subgraph, protocol-acceleration, registrars, tokenscope# RPC_URL_11155111=
# Base Sepolia (public testnet)# - required by plugins: basenames, protocol-acceleration, registrars, tokenscope# RPC_URL_84532=
# Linea Sepolia (public testnet)# - required by plugins: lineanames, protocol-acceleration, registrars, tokenscope# RPC_URL_59141=
# Optimism Sepolia (public testnet)# - required by plugins: protocol-acceleration, tokenscope# RPC_URL_11155420=
# Arbitrum Sepolia (public testnet)# - required by plugins: protocol-acceleration# RPC_URL_421614=
# Scroll Sepolia (public testnet)# - required by plugins: protocol-acceleration# RPC_URL_534351=
# === ENS Namespace: ens-test-env ===# ens-test-env (local testnet)# - required if the configured namespace is ens-test-env# RPC_URL_1337=
# Database configuration# Required. This is a namespace for the tables that the indexer will create to store indexed data.# It should be a string that is unique to the running indexer instance.## Keeping the database schema unique to the indexer instance is important to# 1) speed up indexing after a restart# 2) prevent data corruption from multiple indexer app instances writing state# concurrently to the same db schema## No two indexer instances can use the same database schema at the same time.## Read more about database schema rules here:# https://ponder.sh/docs/api-reference/database#database-schema-rules## Avoid using the `public` schema as we force that in the `dev` command. Using `public`# cause conflicts as you interchange between dev and start commands so use literally# anything else.DATABASE_SCHEMA=production# Required. This is the connection string for the database that the indexer will use to store data.# It should be in the format of `postgresql://<username>:<password>@<host>:<port>/<database>`DATABASE_URL=postgresql://dbuser:abcd1234@localhost:5432/my_database
# ENS Namespace Configuration# Required. Must be an ENS namespace's Identifier such as mainnet, sepolia, or ens-test-env.# (see `@ensnode/datasources` for available options).NAMESPACE=mainnet
# Plugin Configuration# Required. Identify which indexer plugins to activate (see `src/plugins` for available plugins)# This is a comma separated list of one or more available plugin names (case-sensitive).# NOTE:# - for subgraph-compatible indexing, the only valid configuration is `PLUGINS=subgraph`.# - to support Protocol Acceleration in the Resolution API, enable the protocol-acceleration plugin.PLUGINS=subgraph,basenames,lineanames,threedns,protocol-acceleration,registrars,tokenscope
# ENSRainbow service URL# Required. This is the URL of the ENSRainbow server that ENSIndexer will use to heal# unknown labels. The best indexing performance requires a colocated deployments of# ENSIndexer and ENSRainbow services to minimize latency. For example, both services should# communicate over the same local network.# Read more about ENSRainbow here:# https://ensrainbow.io# If you need to temporarily use the public ENSRainbow server for testing, set the following:# ENSRAINBOW_URL=https://api.ensrainbow.io (NOT RECOMMENDED - WILL MAKE INDEXING VERY SLOW!!)ENSRAINBOW_URL=http://localhost:3223
# Pinned Label Set Configuration for requests to ENSRainbow# Required. ENSIndexer must be pinned to a specific label set ID and version to ensure deterministic# indexing results across time.## For a list of available label sets and their configurations, visit:# https://ensnode.io/ensrainbow/usage/available-label-sets/## LABEL_SET_ID: The label set identifier that will be used for label healing requests sent to ENSRainbow.# Each label set id references a collection of rainbow records.# This must match the label set ID configured in your ENSRainbow server.## For full subgraph backwards compatibility, LABEL_SET_ID must be set to "subgraph"# and LABEL_SET_VERSION must be set to 0.LABEL_SET_ID=subgraph
# LABEL_SET_VERSION: A non-negative integer representing the version of the label set to request from ENSRainbow.# This "fully pins" ENSIndexer to a deterministic set of ENSRainbow label healing responses across time,# even if the connected ENSRainbow later ingests additional records into the same label set.# This must be less than or equal to the label set version configured in your ENSRainbow server.## For full subgraph backwards compatibility, LABEL_SET_ID must be set to "subgraph"# and LABEL_SET_VERSION must be set to 0.LABEL_SET_VERSION=0
# The "primary" ENSIndexer service URL# Required. This must be an instance of ENSIndexer using either `ponder start` or `ponder dev`,# (not `ponder serve`). This URL is used to read Ponder's internal indexing state to power the Config# and Indexing Status APIs. This should be configured so that ENSIndexer refers back to itself.# ex: http://localhost:{port}.ENSINDEXER_URL=http://localhost:42069
# A feature flag to enable/disable ENSIndexer's Subgraph Compatible Indexing Behavior# Optional. If this is not set, the default value is set to `DEFAULT_SUBGRAPH_COMPAT` (false).## When SUBGRAPH_COMPAT is true, ENSIndexer will:# 1. Interpret the Literal Labels and Literal Names encountered as Subgraph Interpreted Labels / Names# - https://ensnode.io/docs/reference/terminology#subgraph-interpreted-label# - https://ensnode.io/docs/reference/terminology#subgraph-interpreted-name# 2. Apply the following default configuration, which can be overridden:# - PLUGINS=subgraph# - LABEL_SET_ID=subgraph# - LABEL_SET_VERSION=0## Note: If SUBGRAPH_COMPAT is true but the resulting config is not Subgraph Compatible, an invariant will# be thrown.## When SUBGRAPH_COMPAT is false (default), ENSIndexer will:# 1. Interpret the Literal Labels and Literal Names encountered as Interpreted Labels / Names# - https://ensnode.io/docs/reference/terminology#interpreted-label# - https://ensnode.io/docs/reference/terminology#interpreted-name# 2. Heal all subnames of addr.reverse on the ENS Root Chain# 3. Apply the following default configuration, which can be overridden:# - PLUGINS=subgraph,basenames,lineanames,threedns# - LABEL_SET_ID=subgraph# - LABEL_SET_VERSION=0## SUBGRAPH_COMPAT=false