DID Resolution At Scale: Caching, Trust Anchors, And The Cost Of A Public Registry
Resolving 10,000 DIDs/sec is a systems problem with three load-bearing decisions: how the cache is layered, how trust anchors are selected, and how fresh the verifier needs the document to be.
Continue the reading path
Topic hub
Agent IdentityThis page is routed through Armalo's metadata-defined agent identity hub rather than a loose category bucket.
Turn this trust model into a scored agent.
Start with a 14-day Pro trial, register a starter agent, and get a measurable score before you wire a production endpoint.
TL;DR
A Decentralized Identifier (DID) is only as useful as the verifier's ability to resolve it. At 10,000 resolutions per second, a naive call to a method-specific registry on every verification will collapse the system, blow out cost, and force verifiers to weaken security to keep latency tolerable. The fix is not a bigger registry. It is a three-tier cache hierarchy with explicit freshness budgets, a trust-anchor selection policy that distinguishes registries you control from registries you tolerate, and a revocation path that flushes the cache before stale identity becomes stale authority. This piece gives the working architecture, the named artifact (DID Resolution Architecture Spec), and the operational defaults Armalo uses to keep trust oracle queries under 50 ms p99 without ever serving a revoked DID document as fresh.
Intro: A Verifier Hits A Wall At 4,000 Resolutions Per Second
The failure mode that forces this conversation is mundane and expensive. A trust oracle in front of a marketplace receives a query: "is agent certified at tier T, and is its score above S?" To answer, the verifier must resolve the DID document, check the controller's signing key, verify the verifiable credential the issuer signed, and then check the live score. The first three of those operations require a DID document. At low traffic, the resolver fetches the document from a method-specific registry, validates the signature, and returns. At 100 queries per second, this is fine. At 4,000 queries per second across hundreds of distinct DIDs, the registry begins to throttle, the verifier's tail latency degrades from 80 ms to 1.4 seconds, and the upstream marketplace starts timing out trust oracle calls and falling back to permissive defaults. Permissive defaults are the moment the trust layer dies, because the answer to "is this agent trustworthy" silently becomes "yes, because we could not check."
This is the architecture problem worth taking seriously. DIDs were designed for a world where identity is portable, controllable, and verifiable without a centralized authority. The portability is a feature; the resolution cost is a structural reality the verifier inherits. A DID document for an agent typically includes one or more public keys, service endpoints (the agent's invocation URL, its credential exchange endpoint, its trust oracle reference), an issuer reference, and timestamped revocation status. Pulling this on every verification is wasteful. Caching it is cheap, but caching identity has a famous failure mode: serving a stale document after key rotation, after revocation, after the agent's controller has been compromised. The verifier needs the document fast and current. Those requirements pull in opposite directions, and the architecture has to absorb the tension explicitly.
What follows is the system you build to handle 10,000 resolutions per second across a population of hundreds of thousands of agents, with a cache hierarchy designed for the real read pattern (heavy power-law: 1 percent of DIDs receive 80 percent of resolutions), a trust-anchor selection model that does not silently elevate every issuer to peer status, and a freshness budget that lets a verifier prove to itself, after the fact, that a given resolution was current within an acceptable window. None of this is theoretical. The mechanisms below are how Armalo's trust oracle stays correct, fast, and inspectable while serving the agent economy. The DID Resolution Architecture Spec at the end is the artifact your platform engineering team should be able to take, fill in, and operate.
Why DID Resolution Is Different From DNS Or PKI
The instinct to model DID resolution as "DNS for agents" is half right and dangerously incomplete. DNS solved name-to-address translation under three assumptions that DID resolution cannot inherit. First, DNS records change slowly relative to the rate of lookup, which makes aggressive caching at every layer (browser, OS, recursive resolver, authoritative nameserver) safe. Second, the threat model treats DNS as a hint: the application layer (TLS) re-establishes trust, so a poisoned DNS record produces a TLS failure rather than a silent trust violation. Third, the registry itself (the root nameservers, the TLD authorities) is a small and stable set with extreme operational discipline. None of these three assumptions hold for DIDs serving an agent economy.
A DID document changes more often than a DNS record. Agents rotate signing keys after suspected compromise, after personnel change at the controlling organization, after a scheduled rotation policy fires. They add and remove service endpoints when the agent is redeployed. They update issuer references when a new certifier joins. Worse, they revoke. Revocation is the operation that defines DID security: when an agent is decertified, the trust oracle must stop returning "trusted" within seconds, not within the cache TTL of some intermediate proxy. A 24-hour DNS TTL is acceptable for a hostname; a 24-hour DID document TTL is a security incident waiting to happen.
The second problem is that DID resolution does not have a TLS-equivalent failsafe. When a verifier gets a DID document and uses one of its public keys to check a signature, the verifier is making a final trust decision. There is no second layer that catches a poisoned document. If the document is wrong, the verification is wrong, and downstream actions (releasing escrow, paying out a deal, granting a tool capability) execute against an attacker. The architecture has to treat freshness and authenticity as load-bearing, not advisory.
The third problem is that the DID registry landscape is plural by design. Every DID method (did:web, did:key, did:ion, did:plc, did:ethr, plus method-specific extensions for Polygon, Solana, and Base) has its own resolution mechanism. A serious verifier supports several. Each method has its own performance envelope, its own threat model, its own revocation semantics, and its own operational maturity. Treating them all as a uniform pool is the mistake that produces the 4,000-QPS wall described above. The architecture has to model methods as first-class objects, not as opaque resolvers behind a common interface.
The Three-Tier Cache Hierarchy
The baseline architecture is a three-tier cache: edge cache (geographically close to the verifier), regional cache (per-region warm pool with consistent hashing), and origin resolver (the actual DID method handler that contacts the registry). Each tier has a different freshness budget, a different invalidation pathway, and a different cost profile. The art is in deciding what gets cached where and what gets invalidated when.
The edge cache is local to the verifier process or the verifier's CDN POP. It holds the hottest 5,000 to 50,000 DIDs depending on memory budget. Its freshness budget is short β typically 30 to 120 seconds β because the only reason to put something in edge cache is read amplification on a small hot set, and the cost of a stale read at the edge is a stale verification. Edge cache uses an LRU with TTL eviction, and it carries a resolved_at timestamp on every entry so the verifier can compute freshness on each hit. If a verifier is configured to require freshness within 60 seconds for high-stakes operations (escrow release, certification check), the edge hit is consulted; if it is older than 60 seconds, the verifier promotes the request to the next tier. This is the freshness budget pattern: the cache holds the document, but the consumer decides whether the entry is fresh enough for the decision being made.
The regional cache is a shared Redis or DragonflyDB cluster sized for the working set across all verifiers in a region. Its freshness budget is longer β typically 300 to 900 seconds β because the access pattern across many verifiers smooths out the long tail. The regional cache is the layer that absorbs the bulk of the cost reduction: at 10,000 resolutions per second, with a 90 percent hit rate at edge and a further 9 percent at regional, only 1 percent (100 RPS) reaches origin. That is the difference between a working system and a system that throttles. Regional cache entries also carry resolved_at, and the verifier consults the same freshness budget logic. Critically, the regional cache supports a pub/sub invalidation channel: when a revocation event arrives, every regional node receives an invalidation message within milliseconds and evicts the matching entry. This is the load-bearing mechanism that prevents the staleness-after-revocation incident.
The origin resolver is the actual implementation of each DID method. For did:web, it is an HTTPS GET against a well-known endpoint. For did:key, it is a deterministic transformation of the DID itself (no network call, free). For did:plc, it is a query against the PLC directory. For chain-anchored methods, it is a contract call. The origin tier should be partitioned by method, with separate connection pools, separate timeouts, and separate retry policies. A did:web resolution that times out should not exhaust a connection pool that did:plc resolutions also need. The origin tier is also where the verifier captures the canonical resolution metadata: the DID document, the document hash, the resolution timestamp, the issuer's signature on the document (if present), and the method-specific proof of currency (block hash, sequence number, registry version).
A fourth, often-overlooked layer is the negative cache. When a DID is revoked, deleted, or simply does not exist, the verifier should cache that fact. A negative cache prevents an attacker from forcing repeated origin lookups for non-existent DIDs (a classic amplification vector against the registry). Negative entries should have shorter TTLs than positive ones β 30 to 60 seconds β because revocation is reversible (a controller can re-register) and you do not want to permanently block a re-issued DID. Negative entries should also be flushed by the same pub/sub channel that handles positive invalidations.
Trust Anchor Selection: Who Gets To Vouch For An Identity
A DID document tells you what an agent's keys are. It does not tell you whether the agent's controller is reputable. That second question is answered by trust anchors: the set of issuers whose attestations the verifier accepts as meaningful. Trust anchor selection is the second load-bearing decision in DID resolution at scale, and it is the one most platforms get wrong by treating every issuer as if it were trusted equally.
The correct model is a trust anchor policy with explicit tiers. A tier-1 anchor is an issuer the verifier operates or controls β for Armalo, this includes the certification authority that signs composite score VCs, the multi-LLM jury that signs evaluation outcomes, and the on-chain escrow that signs settlement receipts. Tier-1 anchors are unconditional: their signatures are accepted, their revocation lists are consulted on every resolution, and their key rotation events propagate through the cache invalidation channel. A tier-2 anchor is a partner issuer the verifier has accepted into a trust agreement β typically a peer trust oracle, a partner certification body, or a marketplace that bridges scores. Tier-2 attestations are accepted but flagged, and the verifier may apply a confidence discount to the resulting trust decision. A tier-3 anchor is an unknown issuer β the signature is verifiable but the issuer's reputation is not established. Tier-3 attestations should not be silently elevated to tier-2 status; they should be visible to the verifier's policy layer, which can decide whether to accept, reject, or defer.
The trust anchor list is the single most security-sensitive configuration in the resolution stack. It must be source-controlled, signed, distributed via a separate channel from the cache invalidation channel (so a compromise of the cache layer cannot inject anchors), and reviewed on a fixed cadence. A common failure pattern is to load anchors from a database table that an operator can edit; the better pattern is to load them from a signed manifest that requires a multi-party signature to update.
One nuance worth being explicit about: the controller of a DID and the issuer of a credential about that DID are different actors. An agent's DID is controlled by its operator (the human or organization that holds the private key). A credential about that agent β a certification, a score attestation, a pact compliance receipt β is issued by a third party. Trust anchor selection applies to the issuers, not to the controllers. The verifier resolves the agent's DID to find its public key (used to verify the agent's own signed messages), then resolves the issuer's DID to find the issuer's public key (used to verify the credential the issuer signed about the agent). Both resolutions go through the cache hierarchy. Both can be poisoned. Both must be fresh.
Freshness Budget: How Stale Is Too Stale
The freshness budget is the verifier's contract with itself: "for this decision, the DID document and any relevant credential must have been resolved within X seconds." Without a freshness budget, the cache hierarchy becomes a liability, because every hit is implicitly treated as current. With a freshness budget, the cache hierarchy becomes a tool, because the verifier can hit the edge cache for low-stakes operations and bypass it for high-stakes ones.
The budget is decision-class specific. For a low-stakes read β "is this agent's tier above bronze?" β a 5-minute freshness budget is acceptable. For a medium-stakes write β "can this agent invoke this tool?" β a 60-second budget is appropriate. For a high-stakes settlement β "release escrow to this agent's wallet" β the budget should be 5 to 15 seconds, and the resolver should bypass the edge cache entirely, hitting the regional cache at most. For a security-critical operation β "add this agent to a high-trust group" β the budget should be zero, meaning the resolver must go to origin and capture a fresh proof of currency.
The budget interacts with revocation latency. If your revocation propagation takes 2 seconds (publish event, fan out to regions, evict cache, ack), then a 5-second freshness budget gives you a 7-second worst-case window in which a revoked agent might still be served as trusted. That window is the operational SLO you must publish to verifiers and to the agents being verified. Shrinking it requires faster propagation (synchronous eviction), or shorter budgets (more origin traffic), or both. There is no free lunch; the trade-off must be made deliberately and disclosed to the parties relying on the system.
The freshness budget should be enforced in code, not in convention. Every resolver call should accept a max_age_seconds parameter, and the resolver should refuse to return a cached entry older than that age. If the parameter is not provided, the resolver should use a conservative default (60 seconds) rather than an aggressive one. Logging should record the actual age of every served document so that post-incident review can prove what the verifier saw.
The Cost Of A Public Registry
A public registry is not free, and the economics determine the architecture. Three cost dimensions matter: write cost (registering a DID, updating a document, publishing a revocation), read cost (resolving a DID), and operational cost (hosting, monitoring, replication, key management).
Write cost is borne by the controller and is typically a one-time or rare event. For chain-anchored DIDs, write cost is the gas to publish the document or its hash. For did:web, write cost is the cost of hosting the well-known endpoint and updating it. Write cost should be high enough to discourage Sybil registration but low enough not to exclude legitimate small operators. The right answer is usually a few cents per registration for chain methods and effectively zero for self-hosted methods.
Read cost is borne by the verifier and scales with traffic. This is where caching pays off: every cache hit is a deferred read cost. A naive verifier paying per-resolution costs to a managed registry will spend orders of magnitude more than a verifier with a 99 percent cache hit rate. The cache hierarchy described above is designed to push the verifier's read cost asymptotically toward the cost of the regional cache plus a small fraction of origin traffic.
Operational cost is borne by the registry operator. A public registry serving millions of DIDs needs replication (geographic and within-region), backup, key management for the registry's own signing keys (yes, the registry signs the documents it serves, otherwise the verifier has no way to detect tampering at the registry layer), and a monitoring stack that can detect both performance degradation and integrity violations. For a method like did:plc that uses a centralized directory, the operator's reliability becomes a load-bearing assumption for every verifier using the method. For chain-anchored methods, the chain itself absorbs the integrity guarantee, but verifiers still need fast read access via indexer infrastructure.
The cost model should be transparent to verifiers and controllers. A registry that quietly raises its read pricing or quietly throttles popular DIDs is not a registry you should rely on for trust infrastructure. The DID method's specification should document its cost model, its operational SLO, and its incident response plan. If it does not, the verifier should treat the method as tier-3 trust and price it accordingly.
Revocation: The Operation That Defines Security
Everything above exists to make one operation correct: revocation. When an agent is decertified, when a key is compromised, when a controller signals that an identity should no longer be trusted, the verifier must stop returning trust within a published, enforced window. Revocation is the failure mode that determines whether your trust layer is real infrastructure or a marketing claim.
The revocation pipeline has four stages. Detection: the issuer or controller signals revocation, either by publishing an updated DID document with a deactivated: true flag, by publishing a revocation list entry, or by burning an on-chain marker. Distribution: the revocation event is broadcast through a channel separate from the registry itself β typically a pub/sub topic or a webhook fan-out β so verifiers do not have to poll. Eviction: each verifier's cache hierarchy receives the event and removes the matching entry from edge and regional tiers, and inserts a negative cache entry with a short TTL. Verification: the next resolution attempt either misses the cache entirely and goes to origin (where the deactivated state is now visible) or hits the negative cache and returns immediately.
The load-bearing assumption is that the distribution channel is fast and reliable. If the channel takes 30 seconds to fan out, your worst-case freshness window is 30 seconds plus your freshness budget. If the channel can drop messages, your eviction will be incomplete and some verifiers will continue serving stale documents until their TTL expires. The right pattern is a durable, ordered, at-least-once channel with explicit acknowledgments, and a periodic reconciliation pass where each verifier walks its cache and re-resolves entries older than a threshold to detect any silent revocations missed by the fast path.
A harder problem is revocation across DID methods. If an agent has multiple DIDs (one chain-anchored, one did:web, one did:key for ephemeral signing), revocation of one does not automatically revoke the others. The trust oracle must know the full identity graph for each agent and treat any tier-1 revocation as a compound revocation across the graph. This is a place where a central trust layer (Armalo's trust oracle) earns its place: it can hold the cross-method identity graph and propagate revocation across all of an agent's DIDs in one operation. A federation of independent verifiers cannot easily do this without a shared coordination layer.
Named Artifact: DID Resolution Architecture Spec
The deliverable from this discipline is a one-page architecture spec your platform engineering team can fill in for any new verifier. The fields are deliberately concrete:
Identity: which DID methods does this verifier accept? Which are tier-1, tier-2, tier-3? Where is the method-handler code? Who owns it?
Cache hierarchy: what is the edge cache size and TTL? What is the regional cache cluster, its size, its eviction policy, its invalidation channel? Where is the origin resolver, what is its rate limit, what is its retry policy?
Freshness budgets: what is the budget for each decision class (read, write, settlement, security-critical)? Who enforces the budget β the resolver or the caller? What happens on a budget violation (refuse, warn, log)?
Trust anchors: what is the tier-1 anchor list? Where is it stored? Who can update it? What is the signature requirement for an update? When was the last review?
Revocation: what is the publish-to-evict SLO? What is the distribution channel? What is the reconciliation cadence? What is the cross-method propagation rule?
Cost model: what does each tier cost per million resolutions? What is the budget? What is the cost ceiling that triggers a re-architecture?
Observability: what is logged for each resolution (DID, method, tier hit, age, decision)? What is the dashboard? What are the alerts? What is the incident response runbook?
This spec is the artifact a security reviewer asks for, an SRE leans on during an incident, and a new platform engineer reads on day one. If your verifier does not have this spec written down, the architecture is a folk tradition, and folk traditions degrade silently.
Counter-Argument: "Just Use A Centralized Registry"
The steelman objection is that all of this complexity is self-imposed. A single centralized registry β say, a managed identity service from a major cloud provider β would absorb the resolution problem with a published SLO, a global CDN, and a billing model that makes the cost predictable. The verifier just calls the API and trusts the response. Why build a cache hierarchy and a trust anchor policy when you can outsource both?
The answer has three parts. First, centralization re-introduces the problem DIDs were designed to solve. A central registry becomes a chokepoint: an outage takes down the entire trust layer, a policy change at the registry operator (which agents are allowed, which methods are supported, which credentials are visible) becomes a unilateral edit to your trust system, and a compromise of the registry compromises every verifier that depends on it. The DID architecture exists because identity infrastructure should not have a single point of failure or a single point of authority.
Second, centralization does not eliminate the cache problem; it relocates it. The central registry will throttle, will charge per-resolution, and will have its own freshness window. A verifier that does not cache locally will pay 10x the cost and inherit the registry's worst-case latency. The cache hierarchy is not avoidable; it is just a question of where you put it. Putting it in your own infrastructure means you control the freshness budget, the trust anchor policy, and the revocation propagation; outsourcing it means accepting whatever the registry operator decided.
Third, centralization does not solve the trust anchor problem at all. Even if you trust the registry to serve documents, you still have to decide which issuers' attestations you accept, which scores you treat as authoritative, which counterparties you allow to vouch for an agent. That decision is yours, not the registry's, and it is the part of the system that determines whether the trust layer matches your business model.
The honest position is that managed registries can be a useful tier-2 anchor β a fallback resolver, a discovery layer for DIDs you have not seen before, a redundancy for did:web documents whose hosting endpoint is down. They should not be the only resolution path, and they should not be the trust authority. The architecture above absorbs them as one source among several.
What Armalo Does
Armalo's trust oracle (/api/v1/trust/) sits in front of the agent population and answers two questions: "is this DID a known, current, non-revoked Armalo identity?" and "what is its composite score, certification tier, and most recent pact compliance status?" Underneath, the resolver supports did:web for self-hosted agents, did:key for ephemeral signing, and chain-anchored methods on Base for agents with on-chain wallets. The cache hierarchy is three tiers (Vercel edge, regional Redis, origin resolver in apps/web/lib/), with a freshness budget defaulting to 60 seconds and configurable per decision class. Revocation is propagated within 3 seconds via a pub/sub channel, and every Armalo-issued credential references the DID it certifies, so revoking a DID invalidates every downstream attestation in one operation. The trust anchor list is a signed manifest, updateable only with multi-party signature from Armalo's operations key set. Verifiers using the public oracle get the cache benefit transparently; verifiers running the resolver locally inherit the same architecture by deploying the same code path. The DID-to-score linkage is enforced at the schema level: scores cannot be issued without a resolved, current DID, and they cannot be served without the DID's revocation status being checked first.
FAQ
What happens if the regional cache is unavailable? The resolver degrades to edge cache plus origin. Throughput drops by an order of magnitude, but correctness holds. The freshness budget enforcement is unchanged, so verifiers continue to refuse stale entries. Most production systems will rate-limit incoming queries during this state to protect origin.
Can I cache across DID methods?
The document is keyed on the full DID, including the method prefix, so there is no risk of cross-method collision. But the cache hierarchy should be partitioned by method for invalidation purposes, because revocation channels are method-specific. A did:web revocation does not arrive on the same channel as a did:plc revocation.
How do I detect a registry-level integrity violation? The DID document should be signed by the registry (most modern methods do this). The verifier should verify the registry signature on every origin fetch and log mismatches. A mismatch is a P0 incident: it means the registry's signing key is compromised or the document has been tampered with in transit. The trust anchor policy should include a fallback: which method should the verifier prefer if the primary method's registry has lost integrity?
What is the right freshness budget for a low-stakes feed read? Thirty seconds to five minutes. Lower than 30 seconds creates origin traffic for no security benefit. Higher than five minutes risks serving an agent that was decertified earlier in the session. Most platforms settle on 60 to 120 seconds as a default and document the budget in the verifier's configuration.
Is did:key safe to use without resolution?
did:key resolves deterministically β the public key is encoded in the DID itself, so no network call is required. This is fast and free, but it means a did:key is not revocable through any registry. If you accept did:key for any operation, you must build revocation at the application layer (a separate revocation list) or restrict its use to ephemeral, low-stakes signing.
How do I prove to an auditor that my verifier was current?
Log the resolved_at timestamp, the freshness budget, the method, the tier hit, and the document hash for every resolution that informed a trust decision. The audit trail should be append-only and tamper-evident (signed batches, optionally chain-anchored). When the auditor asks "was this DID current at the time of escrow release," the log answers it with cryptographic proof.
Operational Patterns You Will Reach For
The architecture above describes the steady state. The operational patterns describe how to get there and how to keep it healthy. Three patterns are worth naming because they recur across every serious deployment.
The first is the warm-up pattern. A cold cache is a hot incident waiting to happen: when the verifier comes online, the regional cache is empty, and the first thousand resolutions all hit origin. If origin is rate-limited, the verifier degrades to high-latency or refusal mode just when traffic is ramping. The fix is to pre-populate the regional cache from a snapshot of recent activity (the verifier maintains a rolling list of recently-resolved DIDs and writes it to durable storage on a fixed cadence; on cold start, the verifier reads the snapshot and bulk-resolves the listed DIDs before accepting traffic). Warm-up takes minutes, but those minutes are worth more than the hour of degraded service that follows an unhealthy cold start.
The second is the canary resolution pattern. The verifier should periodically (every 30 to 60 seconds) resolve a small set of canary DIDs through every layer of the cache and through every method handler, and assert that the results match expectations (correct document hash, correct freshness, correct method-specific proof of currency). This is cheap (handful of requests per minute), and it catches integrity failures before they affect production: a poisoned cache entry, a degraded origin resolver, a method handler that has silently broken because of a registry-side change. Canary failures should page on-call before customer impact arrives.
The third is the staged rollout pattern for trust anchor changes. Adding a new tier-1 anchor or rotating an existing anchor's keys is the highest-risk change in the resolution stack. The pattern is to deploy the change to a small percentage of verifiers first, with a fast rollback path, and to monitor resolution success rates for the affected DIDs across the canary window. If anything degrades, roll back immediately. Only after the canary window passes cleanly should the change propagate to the full fleet. The instinct to push trust anchor changes immediately because they feel security-critical is exactly the wrong instinct: security-critical changes deserve the most careful rollout, not the least.
The Verifier's Internal Telemetry
The verifier should expose its own health as structured telemetry, not just operate as a black box. The minimum metrics that matter for DID resolution at scale are: cache hit rate per tier (edge, regional, negative), origin resolution latency per method (p50, p95, p99), freshness budget violations per second (these should be very rare; if they are not, your budgets or your propagation are wrong), revocation propagation lag (time from revocation publication to cache eviction across the fleet), trust anchor list version (so you can correlate behavior with anchor changes), and method handler error rates per method.
These metrics are dashboard candidates, but more importantly they are alert candidates. A cache hit rate that drops by 10 percent over an hour suggests either a working set shift (real, may need cache resizing) or a regional cache problem (alert). An origin latency spike on a specific method suggests the registry for that method is degraded (alert and consider promoting the method to a fallback resolver). A freshness budget violation rate above zero on any high-stakes call class is a P0 (the verifier is serving stale documents to high-stakes operations; investigate immediately).
The telemetry also informs capacity planning. The cache hit rates and origin call rates determine your sizing for the next traffic doubling. The method-specific latencies inform which methods to prefer when an agent presents multiple DIDs. The revocation propagation lag tells you whether your distribution channel can scale, or whether you need to invest in faster eviction infrastructure before your verifier population grows further. Capacity planning without these metrics is guessing; with them, it is engineering.
Multi-Region Deployment And The Consistency Question
Verifiers deployed in multiple regions need to coordinate, but the coordination cannot be synchronous without destroying the latency advantages of regional caches. The right answer is eventual consistency for cache contents and strong consistency for the trust anchor list. Cache entries in one region may be stale relative to another for the duration of the freshness budget; trust anchor lists must match across regions immediately.
The trust anchor list is small (kilobytes), changes rarely, and is highly security-sensitive. Distributing it through a synchronous mechanism (push to every region with acknowledgment, fail closed if any region cannot confirm) is feasible and correct. The cache contents are large (gigabytes), change constantly, and are individually less security-sensitive. Distributing them through a regional cache hierarchy with pub/sub invalidation is the right pattern, accepting that two regions may briefly disagree about whether a specific DID document is the latest.
The consequence is that a verifier in one region may serve a slightly different document than a verifier in another region for a brief window after a revocation. The freshness budget is what bounds the badness: if the budget is 60 seconds and the propagation is 3 seconds, the worst-case disagreement window is 60 seconds, after which both regions converge. This is acceptable for almost all decision classes; it is not acceptable for security-critical operations, which is why those operations should bypass the cache hierarchy entirely and resolve through origin.
A harder problem is verifier coordination during partial outages. If the regional cache in one region is unavailable, that region's verifiers should fall back to a peer region's regional cache rather than going directly to origin. This requires explicit cross-region failover configuration and the bandwidth to absorb the additional cross-region traffic. Most teams discover this requirement during the first regional outage; planning for it ahead of time saves the incident.
Bottom Line
DID resolution at 10,000 QPS is not a registry problem. It is a cache problem, a trust anchor problem, and a freshness budget problem, in that order. The cache hierarchy absorbs the read load. The trust anchor policy keeps the verifier from elevating unknown issuers to peer status. The freshness budget keeps cache hits honest. Revocation is the operation that ties all three together: if revocation propagation is slow, the cache becomes a vulnerability; if the trust anchor list cannot be updated safely, revocation cannot be enforced; if the freshness budget is not enforced, the verifier will accept stale documents from any layer. Build the architecture, fill in the spec, and resist the temptation to outsource the trust decision to whoever happens to be hosting the registry today. The agent economy needs identity infrastructure that scales correctly, and correctness is the part that does not optimize itself.
The Trust Score Readiness Checklist
A 30-point checklist for getting an agent from prototype to a defensible trust score. No fluff.
- 12-dimension scoring readiness β what you need before evals run
- Common reasons agents score under 70 (and how to fix them)
- A reusable pact template you can fork
- Pre-launch audit sheet you can hand to your security team
Turn this trust model into a scored agent.
Start with a 14-day Pro trial, register a starter agent, and get a measurable score before you wire a production endpoint.
Put the trust layer to work
Explore the docs, register an agent, or start shaping a pact that turns these trust ideas into production evidence.
Comments
Loading commentsβ¦