πΎ Hash Vault (Save API Result)
Bank your API result so you never call it again
- api_output
- api_output
The Hash Vault has two halves. Hash Vault (Check Cache) is the lookup, the Lazy API Switch is the wallet, and this node is the bank - the write side. When a cache miss sends you off to the API, it banks the result on disk under the key Check Cache computed, so the next identical call is served from the vault instead of the bill. First run costs you money; every run after that costs nothing.
What it writes and how
It takes whatever your API node returned, recursively moves every tensor to CPU, and saves it as a PyTorch .pt file at output/hash_vault/{hash_key}.pt. The write is atomic (temp file, then rename) and wrapped in a file lock, so an interrupted run can't corrupt an entry. Moving everything to CPU first means the files are device-portable - you can load a vault entry on a different GPU and it just works.
Since v1.3.0 it also writes a sidecar. Alongside the .pt you get a {hash_key}.json with a human-readable label, created_at, last_accessed_at, and a payload summary, plus a 256px {hash_key}.thumb.png preview if the output contained an image. That sidecar is what the Hash Vault Browser (Ctrl+Shift+H in ComfyUI) reads to show you cards with thumbnails and labels instead of opaque hashes.
The inputs that matter
hash_key(required) - the STRING from Check Cache. This is what names the file, and it's what guarantees the write lands where the next lookup will find it. Don't invent your own; wire it.api_output(required) - the exact thing to cache: your API node's output.label(optional) - a human-readable string like"Alec Soth / Songbook / full"for the Browser. Crucially, it's stored in the sidecar only and never factors into the hash - edit the label all you want, the cache key stays valid.
The single output, api_output, is a passthrough so you can keep routing the fresh result downstream (normally to the Lazy API Switch).
The design detail people miss
This node deliberately is not an output node. If it were, ComfyUI would execute it on every run - even cache hits - which defeats the whole point. Instead it only runs when the Lazy API Switch demands the API branch, i.e. on a miss. If you wire the workflow so the API output bypasses the switch, the save node runs on hits too. Harmless (it just re-saves the same bytes), but wasteful, and it means the API node itself is also running, which is the expensive part.
Gotchas and maintenance
The vault grows forever. With no TTL on an entry and no built-in pruning, every unique call adds a .pt (plus sidecar + thumb) to output/hash_vault/. Big image outputs add up. Set a cache_ttl_hours on Check Cache for anything you don't want to keep forever, or clean the directory yourself - it's just files.
The vault doesn't travel with the workflow. It lives in your output directory. Moving to another machine means a fresh vault and paying again until you copy it over. It's device-portable, not network-distributed.
Pre-1.3.0 entries have no sidecar (that's the .pt-only format). The pack ships a backfill tool:
python tools/migrate_hash_vault.py --dry-run # preview
python tools/migrate_hash_vault.py # execute
Install
Part of the ComfyUI-API-Optimizer pack - one install covers all five nodes. ComfyUI Manager: search "ComfyUI API Optimizer". Or clone it into custom_nodes/, pip install -r requirements.txt (just filelock on top of your existing PyTorch), and restart. No model downloads.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| hash_key | STRING | β | |
| api_output | * | β | |
| labelopt | STRING | Human-readable label for the Hash Vault Browser (e.g. 'Alec Soth / Songbook / full'). Written to sidecar metadata only β does NOT factor into the hash, so editing this never invalidates cache. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| api_output | * | β |