Custom ENS Resolution System for High-Load Applications

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1All 1305 services
Custom ENS Resolution System for High-Load Applications
Simple
from 1 day to 3 days
Frequently Asked Questions

Blockchain Development Services

Blockchain Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1349
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    949
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

The Problem: Standard Resolution Can't Handle the Load

Imagine a DApp with 100,000 daily users. Each call to provider.resolveName() hits an RPC node. Without caching, you'll quickly hit request limits—typical Infura/Alchemy tiers allow 100,000 requests per day. At a peak of 10,000 concurrent users, resolution can take up to 500 ms per name, and batch-processing a list of 1000 addresses sequentially using ethers takes 2–5 minutes. That's unacceptable for real-time applications. Moreover, you need to support multi-chain addresses (ETH, BSC, Polygon), handle wildcard domains (ENSIP-10), and off-chain data via CCIP-Read (EIP-3668). Standard libraries are not optimized for these scenarios.

We develop custom ENS resolvers that solve these problems. Our team has completed 30+ projects where we deployed robust ENS integration under high loads. Caching reduces resolution time to 1–5 ms, and batch processing of 1000 addresses completes in 2 seconds. RPC provider costs drop by up to 40%, saving up to $500 per month at scale. At 200,000 requests per day, the savings reach $6,000 per year. With over 30 successful projects and certified blockchain experts, we guarantee a resolution time under 10ms and provide a 100% satisfaction guarantee on all deployments.

The ENS Resolution Process

The full ENS lookup chain includes: name normalization (UTS-46), namehash computation (keccak256), query to the ENS Registry for the resolver address, wildcard support check (ENSIP-10), query to the resolver with coinType, and if the resolver returns OffchainLookup (EIP-3668), executing CCIP-Read. Each step can be a bottleneck. Our custom service handles the entire chain, caching intermediate results.

Custom Resolver Service with Caching

For production systems, we implement a custom resolution service with distributed caching (Redis + in-memory cache). Example in TypeScript using viem (v2.x) and node-cache:

Click to expand code example
import { createPublicClient, http, normalize } from "viem";
import { mainnet } from "viem/chains";
import NodeCache from "node-cache";

class ENSResolutionService {
  private client = createPublicClient({ chain: mainnet, transport: http(RPC_URL) });
  private cache = new NodeCache({ stdTTL: 300 }); // 5 minutes TTL

  async resolveName(name: string): Promise<string | null> {
    const normalized = normalize(name);
    const cacheKey = `addr:${normalized}`;

    const cached = this.cache.get<string>(cacheKey);
    if (cached !== undefined) return cached;

    try {
      const address = await this.client.getEnsAddress({ name: normalized });
      this.cache.set(cacheKey, address ?? null);
      return address;
    } catch (e) {
      return null;
    }
  }

  async lookupAddress(address: `0x${string}`): Promise<string | null> {
    const cacheKey = `name:${address.toLowerCase()}`;
    const cached = this.cache.get<string>(cacheKey);
    if (cached !== undefined) return cached;

    const name = await this.client.getEnsName({ address });
    this.cache.set(cacheKey, name ?? null);
    return name;
  }

  async batchLookup(addresses: `0x${string}`[]): Promise<Map<string, string | null>> {
    const results = new Map<string, string | null>();
    const uncached: `0x${string}`[] = [];

    for (const addr of addresses) {
      const cached = this.cache.get<string>(`name:${addr.toLowerCase()}`);
      if (cached !== undefined) {
        results.set(addr, cached);
      } else {
        uncached.push(addr);
      }
    }

    await Promise.allSettled(
      uncached.map(async (addr) => {
        const name = await this.lookupAddress(addr);
        results.set(addr, name);
      })
    );

    return results;
  }
}

This code integrates easily into any backend. A cache with a 5-minute TTL reduces RPC load tenfold. For distributed environments, we use Redis with the same TTL. For complex scenarios, we also develop Solidity resolvers that can be deployed as custom contracts. Our custom ENS resolver supports ENSIP-10 wildcard resolution, CCIP-Read handling, multi-chain addresses, ENS caching, and is built with Solidity and integrated with Web3 using ethers and viem.

How to Implement Multi-Chain Addresses?

ENS supports storing addresses for different blockchains via coinType (SLIP-44). For example, ETH = 60, BTC = 0, SOL = 501, MATIC = 966. Our service allows you to retrieve addresses for any coinType with a single function:

const COIN_TYPES = { ETH: 60, BTC: 0, SOL: 501, MATIC: 966, ARB: 9001 };

async function getMultiChainAddresses(name: string) {
  const resolver = await provider.getResolver(name);
  if (!resolver) return null;

  const eth = await resolver.getAddress(COIN_TYPES.ETH);
  const btc = await resolver.getAddress(COIN_TYPES.BTC);
  const sol = await resolver.getAddress(COIN_TYPES.SOL);
  return { eth, btc, sol };
}

You can add any coinType, including MATIC, ARB, OP. We provide a unified interface for working with multiple networks.

How to Handle CCIP-Read in a Custom Resolver?

CCIP-Read (EIP-3668) allows a resolver to return a link to off-chain data instead of an address. The client must make an HTTP request to that link and verify the signature. In our service, we automatically handle OffchainLookup: after receiving the error, we extract the URL and data, download them, verify the signature (if required), and cache the result. See EIP-3668 for details. For wildcard resolvers (ENSIP-10), we have full support—see ENSIP-10 documentation.

Speed Gains with a Custom Service

Take a real case: a client application resolves names for 10,000 users on load. With ethers sequentially—~50 seconds. With our custom service using cache and parallel requests—2 seconds. A 25x improvement. This is achieved by caching frequently requested names, parallel batch processing via Promise.allSettled, and avoiding duplicate RPC calls for known addresses. Every millisecond counts at peak load, so we optimize the service for maximum performance. Our custom service is 25x faster than using ethers sequentially for batch resolution.

Advantages of a Custom Service Over Libraries

Ready-made libraries (ethers, viem) work in the browser, but on the backend without caching, they quickly exhaust RPC limits. A custom service gives full control over caching, wildcard support, parallel batch resolution, and a single integration point for multiple networks. Here's a comparison:

Click to see comparison table
Criterion ethers/viem Custom Service
Caching No (or manual) Built-in with TTL
Batch resolution Sequential Parallel
Wildcard (ENSIP-10) Partial Full support
Multi-chain ETH only Any coinType
Timeouts Default Flexible configuration

Our custom service processes batch requests 5–10 times faster than ethers/viem.

How to Implement Custom ENS Resolution in 4 Steps

  1. Architecture analysis: Evaluate your current load, caching needs, and chain requirements. (0.5 day)
  2. Service design: Design API, caching schema, and error handling. (1 day)
  3. Core implementation: Build the resolver with caching, multi-chain, and CCIP-Read support. (2-3 days)
  4. Integration & testing: Integrate with your backend, conduct load testing, and deploy monitoring. (1-2 days)

Development Stages of a Custom Resolution Service

Stage Duration Result
Architecture analysis 0.5 day Technical specification with metrics
Service design 1 day API documentation, caching schema
Core implementation 2–3 days Working resolver with tests
Backend integration 1–2 days Ready endpoint
Monitoring and optimization 1 day Dashboard, alerts, load testing

What's Included in the Work

  • API documentation of the resolver—REST or JSON-RPC specification with request examples
  • Service deployment on your infrastructure (Docker, Kubernetes, Lambda) with monitoring and alerting
  • Integration with existing backend—adaptation for fastify, express, serverless
  • Team training—workshop on using the resolver and troubleshooting
  • Technical support—one month after deployment

Timeline and Cost

Development of a custom resolution service with caching and multi-chain support takes 3 to 5 working days. Integration into an existing backend takes another 1–2 days. Cost is calculated individually based on scope of work. Typical project cost ranges from $5,000 to $15,000, with ROI achieved within 3–6 months. Get a consultation for your project—we'll assess the architecture and propose optimization. Contact us for an analysis of your current ENS integration: we'll identify bottlenecks and speed up resolution.

Digital Identity on Blockchain: DID, SBT, and Verifiable Credentials

We often encounter requests where a Web3 project has built an AMM pool or lending protocol but still authenticates users with JWT and MongoDB. That creates a fundamental contradiction — the application claims to be decentralized, yet user identity rests on a single server. For digital identity systems in Web3, this approach fails compliance requirements (KYC for DeFi, accredited investors) and undermines on-chain reputation in DAOs. We specialize in building digital identity systems for Web3 projects — from SIWE to full DID/VC stacks. Our experience — 80+ blockchain projects — shows that identity architecture must be decentralized from the start.

How does Sign-In with Ethereum solve authentication?

EIP-4361 (SIWE) removes login/password entirely. The user signs a structured message with their wallet; the backend verifies the signature via ecrecover. No credential leaks, no password hashing.

Implementation: siwe library (JS/TS) on the frontend, SiweMessage.verify() on the backend. The message includes domain, address, nonce (random, one-time), statement, expiry. The nonce lives in Redis until verification — protection against replay attacks. Today, SIWE is used by over 80 projects in the top 100 DeFi.

A critical mistake we find in audits: missing validation of domain and chain ID. If the backend does not check message.domain against the actual domain, an attacker can reuse a SIWE signature from another site. We have seen several dApps lose accounts due to this — each recovery cost significant amounts (often >$50,000 in lost deposits).

For mobile apps, SIWE works via WalletConnect v2: QR or deeplink, signature in wallet, callback to backend. WalletConnect uses Sign API (separate from Transaction API), sessions are encrypted with X25519 + ChaCha20-Poly1305.

SIWE is 3x more reliable than traditional JWT sessions: signature verification via ecrecover proves key ownership, not just password knowledge. Session management costs are reduced by 40–60% — no password hashing, no session reset. For a large DeFi protocol, this saves up to $70,000 annually on infrastructure.

What is DID and which method to choose?

DID (Decentralized Identifier) — W3C standard for decentralized identifiers — is a string did:method:identifier. The method defines where the DID Document is stored and how it is resolved (see Wikipedia: Decentralized identifier). The main methods we use in production:

Method Storage Location Gas Cost Use Case
did:ethr EthereumDIDRegistry (ERC-1056) ~60,000 gas on write DeFi, DAO — key rotation
did:key Deterministically derived from pubkey Gasless Ephemeral identity, test
did:web HTTPS (/.well-known/did.json) Gasless Enterprise (DNS trust)
did:ion Bitcoin Layer 2 (Sidetree) ~5,000 gas Long-term, high security

For most DeFi projects, did:ethr or did:key suffice. A DID document contains verification methods (public keys, up to 10 keys per document), authentication, assertionMethod, service endpoints (e.g., link to KYC service). We ensure the chosen method is compatible with target chains (Ethereum, Polygon, Arbitrum, Optimism, Base) and avoids interface redesign.

Common mistakes when choosing a DID method:

  • Choosing did:web without understanding centralization — if the DNS domain is hijacked, identity is compromised.
  • Ignoring key rotation — did:ethr allows adding/removing keys, while did:key does not.
  • Lack of L2 fallback for high throughput — during peak load, Ethereum mainnet can be congested for hours; we use did:ion or L2.

How does verification work via Verifiable Credentials?

Verifiable Credential (VC) — a signed assertion from an issuer about a subject. W3C format: JSON-LD or JWT. Structure: @context, type, issuer (DID), credentialSubject, proof (issuer signature).

Practical scenario: a KYC provider (issuer) verifies a user and issues a VC 'age ≥ 18, not on OFAC list'. The user stores the VC locally (wallet extension or mobile app). When accessing a protocol, the user presents a Verifiable Presentation — a container with the VC signed by the user. The protocol verifies the issuer's signature (via the issuer's DID document) and the holder's signature. No personal data goes on-chain. The protocol does not store a database of KYC-passed users. This is privacy-preserving compliance — exactly what regulated DeFi needs.

Zero-knowledge proofs for VCs take privacy to another level. Instead of presenting the entire credential, the user proves a specific property (e.g., age ≥ 18) without revealing the value. Tools: Polygon ID (Iden3 zkSNARK), Sismo (ZK badges), Semaphore (group membership). Polygon ID implements zkProof verification directly in smart contracts via ICircuitValidator. Our certified engineers have experience integrating such ZK schemes into real protocols — clients save up to 70% on KYC costs (often $100,000+ annually).

Why are Soulbound Tokens not suitable for mass adoption?

SBTs (EIP-5192, concept by Vitalik Buterin) are non-transferable NFTs. Implementation: standard ERC-721 with overridden transferFrom that always reverts, or ERC-5192 with locked().

Production uses:

  • DAO Governance — Snapshot + SBT for one-person-one-vote. Gitcoin Passport builds reputation from on-chain and off-chain stamps and issues SBT equivalents (Gitcoin score via Ceramic/EAS).
  • Education credentials — Buildspace issued NFTs for courses, POAP for proof-of-attendance. SBTs make them non-transferable — cannot buy someone else's history.
  • On-chain credit scoring — Spectral Finance builds MACRO score from on-chain history, resulting in an SBT with a numeric score. Lending protocols use it for under-collateralized loans.

Key technical limitation: recovery mechanism. Losing access to a wallet means losing all SBTs. Without recovery, mass adoption is impossible. Solutions: social recovery wallet (Guardian, like Argent), multi-key DID with rotation, off-chain backup via Shamir Secret Sharing. We include recovery planning in every SBT project.

Ethereum Attestation Service as a standard identity layer

EAS is deployed on Ethereum mainnet, Optimism, Arbitrum, Base. Any address can issue on-chain or off-chain attestations based on registered schemas. A schema is an ABI-encoded structure. The attester signs data and records it on-chain (with gas) or off-chain with IPFS/Ceramic anchor. Verifiers read via IEAS.getAttestation(uid).

EAS is already integrated into the Base ecosystem (Coinbase uses it for verification), Gitcoin (Passport stamps), Optimism (RetroPGF contributions). It is becoming the de facto standard for on-chain identity layer on L2. Our developers are certified for EAS (experience with 5+ projects). According to EAS documentation, attestations can be revoked, and schemas supportup to 32 fields of arbitrary ABI types.

How can we choose the right identity solution for your project?

  1. Analytics & compliance — map the user journey: who is issuer, verifier, what data is needed, what cannot be stored on-chain under GDPR.
  2. Architecture design — choose between on-chain SBT, EAS, DID/VC stack. Data schema, ZK circuit (if needed).
  3. Implementation — smart contracts (Solidity 0.8.x, Foundry/Hardhat), issuer service (Node.js/Go), holder wallet (ethers.js viem), verifier contract.
  4. Testing & audit — unit tests, integration tests, fuzzing (Echidna), static analysis (Slither). Engage third-party auditor.
  5. Deploy & support — deploy to target networks, monitoring (Tenderly), documentation, team training.

Deliverables

  • Source code of smart contracts (Solidity, open-sourced under MIT)
  • Issuer backend (Node.js/Go) with API for issuing VC/SBT
  • Holder wallet integration (ethers.js viem, RainbowKit, WalletConnect)
  • Verifier contract/script
  • Architecture documentation, deployment runbook
  • 2 months post-deployment support

Timeline Estimates

Phase Duration
SIWE integration (wallet authentication) 2 to 4 weeks
SBT contracts + minting portal 3 to 6 weeks
EAS attestation schema + verification 4 to 8 weeks
Full DID/VC pipeline (issuer + holder + verifier) 3 to 6 months
ZK-based privacy-preserving credentials 5 to 9 months

Cost is calculated individually based on schema complexity, number of chains, and compliance requirements. Contact us to discuss your scenario and get an optimal plan.

Order a digital identity system development — get a consultation with a senior engineer specialized in this field. Also, book a technical audit of your current identity system — we will identify bottlenecks and suggest concrete improvements.