Nodes/comfyui-obvpm/Clean VRAM (obvpm)
ComfyUI Node

Clean VRAM (obvpm)

Free the memory between two stages that hate each other

By chanon·Created about a month ago·Updated a day ago· 42
Clean VRAM (obvpm)
  • anything
  • output

You know the failure. A long video sample finishes, the VAE decode starts, and the card that was fine a second ago is now out of memory - not because either stage is too big, but because both of them are sitting in VRAM at once and neither will volunteer to leave.

Clean VRAM (obvpm) is the manual override. It unloads every loaded model, drops the cached allocations, and passes its input straight through, so you can place the cleanup exactly where the peak is.

What it does under the hood

Three lines, and they matter:

  • gc.collect() to reclaim Python-side garbage,
  • comfy.model_management.unload_all_models() - the same call ComfyUI's own free-memory path uses, evicting every loaded model from VRAM,
  • comfy.model_management.soft_empty_cache() - the allocation-cache release, letting the CUDA allocator hand memory back instead of hoarding it.

Then it returns your input unchanged.

The important structural detail: it's registered as an output node. A pure passthrough whose result nobody consumed would be pruned before it ran, so a side-effect-only plumbing node like this one has to be an execution root. That's also why it works even when the output goes nowhere. Wiring it onward is still the polite thing to do - it's what puts the cleanup in the right place in execution order.

The one input and one output

  • anything - required, wildcard type (*). Anything at all: a latent, an image, a model. It's passed through untouched. In the author's words, its only job is to place the cleanup in execution order.
  • output - the same value, unchanged.

So the node reads as a bead on a wire you already had. Latent → Clean VRAM → decode is the canonical placement.

When to actually use it

Put it between two stages that won't fit together, and put it where a reload is cheaper than an OOM. That's the trade, stated plainly: everything this node unloads gets loaded again on next use, so you're paying model load time (tens of seconds for a big checkpoint, more for a video model) to buy back the VRAM.

Good placements:

  • after a long sampler run, before a VAE decode that wants its own few GB;
  • between two different base models in one graph - sample with A, refine with B;
  • before an upscale pass that loads a second model of its own;
  • in video workflows, where the sampling peak and the decode peak are the two walls people hit.

Bad placement: exactly where you think it'll help but the model you just unloaded is needed one node later. That's pure loss.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/chanon/comfyui-obvpm

Restart ComfyUI, look for Clean VRAM (obvpm) under obvpm/misc, or search the node menu for obvpm. Nothing extra installs - the pack declares zero Python dependencies, and this node uses only ComfyUI's own model_management module. (If you were using a similar node from another pack, this is a like-for-like replacement; the pack's THIRD_PARTY_NOTICES.md credits the two it was written to stand in for.)

If it doesn't seem to help

Two honest caveats. First, this only affects ComfyUI's own model and allocation cache - anything held by a custom node that keeps its own tensor reference won't be freed by a call the pack doesn't own. Second, it unloads everything, not selectively: if your graph keeps a CLIP encoder loaded for a later text encode, you've just paid to reload it. Check the console - the node logs obvpm: unloaded all models and released cached VRAM when it fires, which is the fastest way to confirm it exists in the order you think it does.

And it is not a substitute for the memory flags. If you're on a card that barely fits the model, --lowvram/--reserve-vram territory is a different lever - and worth re-testing, because low-VRAM flags can make a card that just fits slower rather than faster.

Categoryobvpm/misc

Inputs (1)

NameTypeDefaultDescription
anything*Passed through untouched. Its only job is to place the cleanup in execution order.

Outputs (1)

NameTypeDescription
output*The input, unchanged. Wire it onward so the cleanup is ordered before whatever needs the room.