Skip to content

Webhooks & events

Today, if you want your app to react to ENS state changes, you have two unappealing options:

  • Poll constantly. Hammer the GraphQL or RPC every few seconds and discard most responses. Wasteful, slow, and never quite fresh.
  • Build your own indexer. Stand up infrastructure to listen to chain events, decode them, and turn them into the ENS-level signals you actually care about. Way too much work for what should be a primitive.

Neither is good. The first is lossy and expensive at scale; the second is a project on its own.

We’re working on an ENS-native webhooks service so your app can subscribe to ENS state changes the same way you’d subscribe to a Stripe or GitHub webhook - except the events speak the language of ENS, not the language of raw chain logs.

Internally we refer to the planned service as ENSEngine: it watches your ENSDb for changes and turns them into ENS-aware webhook deliveries to any sink you configure.

POST https://your-app.example.com/webhooks/ens
Content-Type: application/json
{
"type": "domain.transferred",
"name": "vitalik.eth",
"chain": "mainnet",
...
}

The shape above is illustrative only.

The early thinking covers the events most apps actually care about:

  • domain.registered, domain.renewed, domain.transferred
  • resolver.address_changed, resolver.text_changed, resolver.contenthash_changed
  • subname.created

This list is not a committed API surface - it’s a sketch of what’s in scope. Final event names, payloads, and filter options will land with the service itself.

The headline use case - and the one we’re prioritizing first - is cache invalidation.

Build aggressive, edge-friendly caches for ENS data. The goal is to make it practical to cache profiles, avatars, text records, and resolver responses for much longer than polling-based integrations allow, then invalidate them when relevant onchain state changes. That’s the foundation for web2-grade UX on a web3 protocol - fast page loads, low RPC fanout, globally distributed reads - without giving up freshness as the product matures.

Where this matters:

  • Frontend apps caching ENS profiles
  • CDNs serving ENS-driven content
  • API gateways with ENS lookups
  • Any service that caches resolver records

Adjacent value props (enabled by the same primitive)

Section titled “Adjacent value props (enabled by the same primitive)”

Once a reliable change feed exists, a lot of follow-on patterns get dramatically easier to build on top of it. We’re not promising these as separate features - they’re examples of what the cache-invalidation foundation makes practical:

  • Notification services - expiry reminders, watchlists, security alerts on unexpected transfers, registration bots in Discord/Telegram.
  • Database sync - keep your own app database in step with ENS state, so marketplaces, portfolio trackers, analytics dashboards, and search indices don’t drift.
  • Realtime dashboards - surface registration / renewal / transfer activity as it happens.

Reactive webhooks build on the same foundation as the rest of ENSNode:

  1. ENSIndexer keeps ENSDb up to date with the live, multichain onchain state of ENS - including automatic chain reorg healing.
  2. The planned ENSEngine service watches that database for changes and turns them into enriched, filtered, ENS-aware events.
  3. Those events get delivered to your sinks - webhooks, cache invalidation hooks, database sync targets, notification systems, and more.

For the architecture overview and code-name notes, see ENSEngine - How it works.

This page is a teaser, not a spec. There’s no subscription endpoint to call yet, no signature verification documented, no SDK to integrate against. Those will arrive in dedicated reference docs once the service ships.

If your app would benefit from any of the use cases above, it’s a great time to share what you’d need from this service - we’re still shaping it.