Nodes/ComfyUI-API-Optimizer/πŸ” Hash Vault (Check Cache)
ComfyUI Node

πŸ” Hash Vault (Check Cache)

Never pay for the same prompt twice

By jeremieLouvaertΒ·Created 5 months agoΒ·Updated 15 days agoΒ· 1
πŸ” Hash Vault (Check Cache)
  • any_input
  • any_input_2
  • any_input_3
  • any_input_4
  • cached_data
  • is_cached
  • hash_key
β—„payload_stringβ€”β–Ί
β—„cache_ttl_hours0β–Ί

ComfyUI's native caching is great - until it isn't. For local nodes it skips work it's already done and everybody's happy. But with external API nodes it falls apart: dynamic timestamps, non-deterministic seeds, images that differ by a single byte. Re-queue the same prompt and the API cheerfully charges you again. This node is the read half of a disk-cache layer built for paid API calls: it hashes whatever defines your call, looks it up in output/hash_vault/, and tells you whether you've already paid for exactly this result.

How the hash works

The cache key is a SHA-256 over payload_string plus up to four any_input slots. The important part is how it hashes. Tensors are hashed byte-for-byte - the full content including dtype and shape metadata, not some lossy perceptual approximation. Same image with a slightly different value is a different key. Nested structures (dicts, lists, tuples) hash recursively, and dict keys are sorted first, so the order keys appear in doesn't matter. Wire a different prompt, change a dropdown, nudge a strength slider - the key changes and the API runs again. That's the contract: strict identity, no fuzziness.

Cache files live at output/hash_vault/{hash_key}.pt and are loaded with map_location="cpu", so entries are portable across GPU configs. Every read/write is wrapped in a file lock, and writes are atomic - a crashed save can't corrupt an entry.

The inputs that matter

All of them are optional, which is the design: hash on whatever subset defines uniqueness for your call.

  • payload_string - the prompt, JSON params, or any string that factors into the key. For a prompt-driven API, this one input is usually all you need.
  • any_input through any_input_4 - any type: image, latent, conditioning, or a converted widget. Right-click a downstream node's widget β†’ Convert Widget to Input β†’ wire it here. One slot per thing that defines your call.
  • cache_ttl_hours (default 0) - time-to-live in hours. 0 = never expires. Set a TTL for anything where a stale result is worse than a fresh one.

The three outputs

  • is_cached - INT, 1 on a hit, 0 on a miss. Wire this into the Lazy API Switch; that's what lets ComfyUI skip the API node entirely.
  • hash_key - STRING, the cache key. Feed it to Hash Vault (Save API Result) so a miss writes under the same key.
  • cached_data - the stored result on a hit, None on a miss. Also goes to the Lazy Switch, which routes it downstream when it's there.

The sandwich pattern

This node never works alone. The standard wiring: fan your prompt/image out to both Check Cache and your API node. Check Cache's is_cached + cached_data go to the Lazy API Switch; the API node's output goes to Hash Vault (Save Result), using the same hash_key. First run misses, the API executes, Save banks the result. Second run hits, and the Lazy Switch feeds you the cached copy while the API node never executes - no call, no charge.

Gotchas

Watch the converted-widget trap. If your API node's dropdown becomes an input and you drive it with a raw string primitive, there's no validation - a typo silently changes the hash. The hash stays valid, the cache just never hits again, and the API errors at runtime. That's why the pack's example workflows use a Settings node (like Gemini Style Transfer Settings) that owns the real dropdowns and emits validated strings.

Cache not hitting? Something in your inputs is changing between runs - a timestamp, a seed that isn't fixed, a tensor that differs in dtype or shape. Since hashing is strict, any of those reads as "new" and you pay again.

Install

Ships with the ComfyUI-API-Optimizer pack. Via ComfyUI Manager, search "ComfyUI API Optimizer", or:

cd ComfyUI/custom_nodes/
git clone https://github.com/jeremieLouvaert/ComfyUI-API-Optimizer.git
pip install -r ComfyUI-API-Optimizer/requirements.txt

Restart ComfyUI. Dependencies are just filelock on top of the PyTorch you already have - no models to download.

CategoryAPI Optimization

Inputs (6)

NameTypeDefaultDescription
payload_stringoptSTRINGPrompt, JSON params, or any STRING that should factor into the cache key. Optional β€” you can hash purely on any_input slots if you prefer.
any_inputopt*Any input to hash: image, latent, conditioning, or a converted widget (convert a downstream node's widget to input and wire it here). Content is hashed recursively.
any_input_2opt*Second any-type input. Use one slot per widget you want to factor into the cache key β€” e.g. image on any_input, style dropdown on any_input_2, strength float on any_input_3.
any_input_3opt*Third any-type input.
any_input_4opt*Fourth any-type input.
cache_ttl_hoursoptFLOAT00–8760Cache time-to-live in hours. 0 = never expires

Outputs (3)

NameTypeDescription
cached_data*β€”
is_cachedINTβ€”
hash_keySTRINGβ€”