Self-contained fix for slow / black-screen ComfyUI loading when you have a huge model/LoRA collection (especially on a network mount). Just install the pack and restart ComfyUI — no nginx, no docker, no extra port.
ComfyUI's /api/object_info enumerates every node's inputs. With thousands of
LoRAs (worse on a network mount) it becomes tens of MB and takes minutes to
build on every page load — and the build freezes ComfyUI's whole event
loop, so you get a long black screen, worst over a remote network.
On load it injects an aiohttp middleware into ComfyUI that intercepts
/object_info and /api/object_info and:
- caches the built response in memory and on disk (
./cache/), so it is built once instead of on every load — and the disk copy makes restarts instant (no rebuild); - serves it gzipped (≈85% smaller transfer, independent of any CLI flag), straight from cache without running the build;
- because the build never runs on a normal load, the event-loop freeze (and the long black screen) is gone — page loads drop from minutes to seconds.
The only time a build runs is the first load after install, or when you explicitly refresh (below).
The cache holds the old model lists until you refresh. Three modes are available
from the Extensions menu (and the command palette):
| Mode | What it does | Speed |
|---|---|---|
| ⚡ Quick refresh | Re-walks only the folders whose timestamp changed since the last scan; reuses the cache for the rest. Catches new / removed / renamed files. | Fast on local disks; ~2× faster on a slow network mount (it still has to stat every folder to find which changed). |
| 🔄 Full refresh | Clears ComfyUI's folder cache and re-walks everything, ignoring timestamps. Catches moves/deletes anywhere. Use this for files you just added. | Slowest (the original behaviour). |
| ➕ Register new file… | You give it the path(s) of the file(s) you just added; it appends them to the cache with no folder walk. | Instant disk-wise — only the object_info rebuild remains. |
Also available:
- Graph node
🔄 Refresh Models/LoRAs (Tenaciousload)with amodewidget (quick/full), for automated workflows. - HTTP:
POST /tenaciousload/refreshwith{"mode": "quick" | "full" | "register", "folder": "loras", "files": ["pack/new.safetensors"]}, thenGET /object_info?nocache=1.
The first Quick refresh after install builds a folder index (one full walk), so it's as slow as a Full refresh that one time; every Quick refresh after that is incremental. The index is saved to
./cache/scan_snapshot.json.
Network mounts (CIFS/SMB/NFS): Quick refresh detects changes by directory timestamp, which network filesystems can report with a delay or coarse resolution (e.g. a
cache=looseCIFS mount), so it may occasionally miss a brand-new file. If a just-added model doesn't show up after a Quick refresh, use Full refresh — it re-walks everything and doesn't rely on timestamps.
Whichever mode you pick, the button shows a "refreshing…" toast and normal loads stay instant.
None to install. Only ComfyUI itself (tested on 0.23.0) and Python ≥ 3.8.
Everything used is Python stdlib or already bundled with ComfyUI (aiohttp,
folder_paths, server). The web button needs no npm packages.
Clone (or copy) this repo into your ComfyUI custom_nodes/ folder and restart
ComfyUI:
cd ComfyUI/custom_nodes
git clone https://github.com/ethanfel/ComfyUI-Tenaciousload.git
# then restart ComfyUINothing to pip install. ComfyUI-Manager can also install it from the registry.
After restart, load the page once (first time builds + caches), then:
curl -s -H 'Accept-Encoding: gzip' -o /dev/null \
-w '%{time_total}s | %{size_download} bytes | %header{x-tenaciousload-cache} | %header{content-encoding}\n' \
http://127.0.0.1:8188/api/object_info # use your ComfyUI port
# expect after the first load: ~0.00Xs | ~10 MB | HIT | gzipComfyUI's startup log should show Tenaciousload: object_info cache middleware installed.
This pack already gzips the cached object_info on its own. To also gzip
everything else ComfyUI serves — most importantly the hundreds of frontend
extension scripts, plus the other API responses — launch ComfyUI with its
built-in compression flag:
python main.py --listen --port 8188 --enable-compress-response-body- It's a stock ComfyUI option (defined in
comfy/cli_args.py), not part of this pack, and it's optional — Tenaciousload works fine without it. - It's strongly recommended for remote access: those extension scripts are
many small requests that compress very well, so the flag noticeably cuts the
total transfer on top of the
object_infocache. - It costs a little CPU per response to compress; on a fast machine this is negligible compared to the bytes saved over the network.
- Loading status: instead of ComfyUI's silent "Comfy" splash, a small status
line shows whether it's serving from cache or building (with node count +
elapsed time), so a long rebuild isn't a black screen with no feedback. It
removes itself once the app is ready. Status is also at
GET /tenaciousload/status. - The disk cache lives in
./cache/(git-ignored). Delete it, or use the refresh button, to force a rebuild. - An nginx reverse proxy can cache
object_infoat the HTTP layer too, but this pack does it in-process so no extra service, container, or port is needed. - New files in the
inputfolder are picked up by a refresh button by default (same as new models) — they do not trigger an automatic rebuild on restart. To auto-detect them on restart instead, setTENACIOUSLOAD_WATCH_INPUT=1. Only do this if your input folder is fairly static: on a busy input folder (e.g. a video workflow that adds clips constantly) the input dir changes on nearly every restart, which would invalidate the cache and force a slow rebuild each time — defeating the point.
This pack is a quiet neighbour:
- No dependencies — its
requirements.txtis empty, so it can't cause the pip version conflicts that break other nodes' installs/updates. It also never touches other nodes' files or the ComfyUI-Manager installer. - Auto-detects node changes — it fingerprints the installed node set
(
NODE_CLASS_MAPPINGS) and, on the first page load after a restart, drops the cache automatically if a node was installed, updated, enabled or removed — so new nodes appear with no manual refresh. - The only thing it gates is the full
/object_infolist (a cached snapshot); it passes every other request straight through, so other nodes' own routes, sidebars and refresh buttons are unaffected. For an in-place node tweak that changes an existing node's inputs without adding/removing a node class, use a refresh button.
Set TENACIOUSLOAD_DISABLED=1 (and restart) to turn the pack into a no-op:
no caching middleware, no fingerprint, no refresh routes, no graph node — ComfyUI
behaves exactly as if the pack weren't installed. The loading-screen status
bar stays (it just shows a generic "Loading node definitions…" since there's no
build to track). Useful for A/B comparing, or as a one-flag kill-switch if you
ever suspect the cache. Remove the variable (or set it to 0) and restart to
re-enable.
MIT — see LICENSE.