Build1 publisher3 min readPublished Updated
Three failed lookups at 8-wide made DEGEN's warm map disagree with its cold one
Doubling the worker pool against Nansen's API bought 5.8 seconds of median wall clock across four tokens and cost three calls in 441. Holder Atlas's defaults are back at 4-wide under 5 requests per second.
The Engineer · Build desk

What happened
- A cold Holder Atlas run for PEPE spent 117 Nansen credits across 110 calls in 57.3 seconds, with nothing served from cache.
- Raising the worker pool from 4 to 8 and the rate bucket from 5 to 10 requests per second moved cold p50 across the four benchmark tokens from 40.3 to 34.5 seconds, a 14 percent gain.
- p95 did not move with it: DEGEN on Base took 59.0 seconds at 4-wide and 58.1 seconds at 8-wide.
- The wider run produced three failed lookups, all of them on DEGEN, where the 4-wide run had none.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- constraint The remaining 58 seconds on the slowest token is Nansen's to spend, not the client's, so pool width is no longer a lever anyone should pull for it.
- exposure Anyone using the warm hash as a regression check gets a false mismatch whenever a call failed on the cold run the day before.
- cost A failure occupies a worker for up to 17 seconds before it is even reported, so a handful of them spends more worker time than the wider pool bought back.
- decision The 5 rps default was sized for a second concurrent visitor, so anyone who raises it for one user's latency is spending the multi-tenant headroom to do it.
The throughput model behind the change was simple: 110 calls, W workers, about two seconds each, so double W and halve the clock [20]. On that model the 4-wide cold p50 of 40.3 s should have come out near 20.2 s [3]. It came out at 34.5 s [11].
The model fails on the shape of the distribution. A map's wall clock is set by its slowest handful of calls, and the slow one here is tgm/transfers with a to_address filter over a year of a high-volume token, which stays slow no matter how many siblings run beside it [21]. In the PEPE run tgm/transfers went 78 times at 1695 ms average and the token-transfer lookup 29 times at 2007 ms [5]. Those 78 plus 29 are exactly the 107 calls that average 1.7 to 2.0 s [8][6]. Widening the pool compresses the middle of that distribution and leaves the tail where it was [21].
DEGEN on Base is the token that needed the width, and it gained 0.9 seconds [4].
It also paid for the width in failed calls. The client marks a call failed only after an 8 s timeout and one retry, the same path that handles 429 and 5xx, so each of the three failures held a worker for up to about 17 s [22]. That is up to 51 worker-seconds [5] against 5.8 seconds of median gain across the four tokens [2]. Three failures in 441 calls is 0.68% [1]. The bench recorded the count but not the class, and the author says he will not claim which of timeout, 429 or 5xx each one was [24]. The same lookups had succeeded at 4-wide four days earlier [23].
Successful calls are cached for 24 hours, which is why a warm map comes back in 7 ms and costs nothing in credits [8]. A failed lookup is not cached [14]. So the warm run re-issues the calls that failed, makes a different set of calls than the cold run made, and draws a different picture; DEGEN's warm hash stopped matching its cold hash [14].
The default that came back is one line: `this.limiter = new RateLimiter(opts.rps ?? 5, opts.rpm ?? 300);` [19]. Five requests per second sustained is 300 a minute, which is Nansen's documented cap exactly [6]. The comment above it says who the slack is for: at 5 rps, one roughly 110-call atlas fits inside the cap with headroom for a second visitor, and the rolling 300/min window is the hard stop for a third [16]. A single 110-call map at 10 rps asks for only 11 seconds of full-rate service, so on its own it stays inside the rolling minute [7], which is the sense in which the author calls 10 rps fine for one map in isolation [10].
The 14% describes a workload where the time is spent on the server and the client waits, with 107 of 110 calls in the 1.7 to 2.0 s band [6][11]. For it to transfer, your per-call time has to be in seconds and your tail has to sit on the server, not in a queue you own. At tens of milliseconds a call, pool width is worth tuning and none of this applies.
The author's conclusion, in the DX report written for Nansen alongside the repo, is that latency is the product's ceiling and that the per-call time is where it lives; the client is not [25]. The comment in the code puts it in one clause: "per-call latency, not the pool, is the ceiling" [18].
What to watch
- A rerun at 8-wide with the failure class logged would show whether the three DEGEN misses were 429s or server timeouts.
- If the client starts caching failures, or retrying them out of band, the warm-versus-cold hash comparison becomes usable again.
- Any drop in Nansen's tgm/transfers response time would move p95 for the first time; nothing on the client side did.