Here’s how this gets built at 90% of shops shipping a “prove you’re not a bot” gate in 2026: someone reaches for
jsonwebtokenor a hosted IAM SDK, wraps it in an Express or Fastify middleware, and calls it done. Every inbound request pays a synchronous crypto verify — usually RSA-2048 or ECDSA/P-256 — on the Node.js event loop, then a network round trip to a session store (Redis, or worse, a managed auth API) to check revocation status.This works in the demo. It works at 500 req/s. It falls over hard past 50K req/s per node, and the reason isn’t “Node is slow” — that explanation gets you nowhere in a postmortem. The reason is structural: you’ve made cryptographic verification and revocation lookup a per-request, userspace-synchronous, network-bound operation, and you’ve hidden that fact behind a middleware abstraction that looks like a one-liner.
Three concrete failures compound under load:
ECDSA verification is CPU-expensive and non-batchable. P-256 verification requires a per-signature CSPRNG draw and non-constant-time-friendly scalar multiplication in most JS crypto bindings. At 50K req/s with a single-threaded event loop, this alone serializes your CPU-bound work and blocks I/O callbacks — classic GIL-style serialization, just with V8’s event loop instead of Python’s GIL.
Revocation checks are a network hop per request. A Redis
GETat p50 1ms sounds free. At 50K req/s fan-out across a connection pool sized for “reasonable” concurrency, you exhaust the pool, queue requests behindTIME_WAITsockets, and your p99 latency goes from 2ms to 400ms — not because Redis is slow, but because you’re doing connection pool exhaustion in real time, in production, on the request-critical path.Bot traffic is adversarial and repetitive. The actual attack pattern for a “human-check” gate is a botnet replaying the same expired or forged credential thousands of times per second. A naive implementation pays full verification cost — CPU cycles, syscalls, network hop — for every single replay. You’re doing the most expensive possible thing on your most adversarial, most repetitive traffic. This is the exact inversion of what a cache is for.
None of this shows up in a load test against clean traffic. It shows up during an actual credential-stuffing event, which is precisely when you can least afford it.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.