A large in-process cache seems to be contributing to garbage collection pauses in a Node.js service. Would moving the cache off the V8 heap help, and what tradeoffs should I expect?
Would an off-heap cache help with Node.js GC pauses?
Answers
It can help if the cache is keeping a lot of objects live on the V8 heap. An off-heap cache stores its data in native memory, so V8 does not have to trace those cached objects as part of its normal heap graph.
OffHeap is one addon designed for this. It uses a Rust native layer and offers TTL plus LRU, ARC, and W-TinyLFU eviction policies. In one synthetic test with 500,000 keys and 1 million operations, the worst individual GC pause was reported at roughly 11 ms off-heap versus 300 ms for an in-heap cache. That is a promising result, not a prediction for a different workload.
Measure p99 request latency and GC pauses with your actual payloads and access patterns. The cache may reduce GC work while introducing other costs.
Reply to this answer
Watch the cost per operation too. Crossing into native code is not free, even if the calls look like ordinary cache operations from JavaScript.
Rough benchmarks with small JSON-like payloads reported about 50 to 90 ns for a V8 Map get or set, 75 to 240 ns for an in-heap lru-cache, and 900 ns to 1.4 microseconds for the native cache. Those figures depend on the test setup and payloads, but they show why lower GC pauses can come with slower average cache operations.
Reply to this answer
Don't treat off-heap as memory disappearing. The native cache still consumes process memory, so check total memory under load as well as the V8 heap. TTL and an eviction policy are useful, but you still need a sensible cache size for the service.
Also test installation on every platform you deploy to. This particular addon had a cross-platform binary publishing issue that was reported as fixed, so it is worth verifying in your own deployment environment before relying on it.
Reply to this answer
Add your answer
Answers are reviewed before publication.
Bexlin.29:
That makes the choice pretty workload-dependent. A hot cache hit path could notice the extra per-call cost even if the worst pauses improve.