Skip to main content

Performance & Caching

"DLT is slow" is the first objection. Here's the data.

The DLT latency penalty exists only on the write path — DID anchoring and credential issuance. The verification hot path, which is what matters for real-time agent interactions, never touches the ledger.

Numbers

OperationHelixID (cached)JWT/OAuthRaw Ed25519
Credential verification~1-6 ms1-5 ms~0.1 ms
DID resolution~0.01 ms (cache hit)N/AN/A
Revocation check~0.01 ms (cached)50-200 ms (introspection)Not supported
Full verification (warm)~1-6 ms1-5 ms~0.1 ms

"Warm" means the DID document and status list are already cached. Cold, each is a single static-document fetch.

The row that matters is revocation. A token introspection call costs 50–200 ms and cannot be cached — being asked fresh every time is its entire purpose. A status list is one shared static document, so it caches, sits on a CDN, and costs ~0.01 ms on a hit. Nothing in HelixID's path asks the issuer to authorize the request. See What "Offline Verification" Actually Means.

Context: A single LLM inference call takes 500 ms–5 s. HelixID verification at ~5 ms is noise in that budget. You get the same verification speed as JWT, backed by cryptographic trust that JWT can never provide.

Where HelixID actually wins on latency

Not on a single internal call — there, a cached OAuth token is roughly as fast, and HelixID adds complexity for no latency benefit.

The win is multi-hop delegation. Each hop is a local signature verification (~1 ms) rather than an issuer callback (500 ms–2 s). A five-hop chain lands around ~55 ms against 400–800 ms+ for per-hop OAuth callbacks. Position accordingly: use OAuth for internal APIs where it is perfect; add HelixID for cross-org APIs and delegation chains. See Comparisons.

Caching architecture

DID documents

Cached in-process automatically — no configuration needed.

MethodTTL
did:web5 minutes
did:hedera15 minutes
did:keyNot applicable — the key is in the identifier

DID_CACHE_L1_TTL_SECONDS (default 300) governs the API-side cache.

The TTL is a security parameter as much as a performance one — it bounds how long a verifier can keep using a rotated key.

Status lists

Fetched per verification by default. fetchStatusList is a plain fetch; there is no built-in verifier-side cache.

The bitstring is a static document shared by every credential from that issuer, so it caches well — pass a statusListResolver to verifyVP() to serve it from your own cache, CDN, or local storage. helix-api already does this for the list it hosts.

const result = await verifyVP(incomingVP, {
expectedTargetService: 'orders-service',
statusListResolver: myCachedResolver,
})

STATUS_LIST_CACHE_L1_TTL_SECONDS (default 60) governs the API-side serve cache, which applies only when a cache adapter is configured.

This TTL is a revocation-latency dial

Over-aggressive caching leads to use-after-revocation — a revoked agent keeps working until the cache expires. Choose the TTL from how quickly revocation must take effect, and treat it as part of your threat model rather than as a throughput knob.

Session token bridge

For high-frequency scenarios (1000+ RPS), verify the VC once (~5 ms) and issue an ephemeral JWT for subsequent calls (~0.1 ms). See Hybrid 3-Layer Design.

The session TTL is the same trade-off in a different place: a longer session means fewer verifications and a longer window in which a revoked credential still gets service. JWT_SESSION_TTL_SECONDS defaults to 600.

Current cache adapters

AdapterStatus
memory — L1 in-processShipped, and the default
Redis / L2 shared cachePlanned — parked for a future release, not required for current runs
HELIX_CACHE_ADAPTER=memory
CACHE_ENABLED=true
DID_CACHE_L1_TTL_SECONDS=300
STATUS_LIST_CACHE_L1_TTL_SECONDS=60

Only the L1 TTLs currently matter. See Environment & Configuration and the Roadmap.

TTLs worth setting deliberately

VariableDefaultWhat it bounds
ENROLLMENT_TOKEN_TTL_SECONDS900How long a one-time bootstrap token stays usable
CHALLENGE_TTL_SECONDS300Onboarding/user-challenge nonce validity
VP_TTL_SECONDS300How long a presentation is replayable before expiry
JWT_SESSION_TTL_SECONDS600Session-token lifetime after one verification
DID_CACHE_L1_TTL_SECONDS300Staleness window for a rotated key
STATUS_LIST_CACHE_L1_TTL_SECONDS60Staleness window for a revocation