Nodes/lora-scheduled-comfyui/LoRA Scheduled (timestep)
ComfyUI Node

LoRA Scheduled (timestep)

Stop Letting Your LoRA Hog the Whole Denoise

By Murdunbad·Created 3 months ago·Updated 3 months ago· 0
LoRA Scheduled (timestep)
  • model
  • MODEL
lora_name
enabledtrue
apply_toboth
lora_strength1.00
inject_at0.00
stop_at1.00
fade0.00
force_reruntrue

Ever notice how a strong character or style LoRA gives you the same pose, same camera angle, same framing, every single seed? That's not bad luck, it's the mechanism. A normal LoRA loader merges the weights in from step one, so the model is steered toward the LoRA's learned distribution before the image even has a shape. And composition gets locked in during those first denoising steps. You've handed the LoRA the steering wheel for the whole drive.

LoRA Scheduled (timestep) - a single node from the lora-scheduled-comfyui pack - fixes exactly that. It applies a LoRA only inside a window of the denoising process, and optionally only to one side of the CFG split. Let the base model compose, then drop the LoRA in when it's time for style, character, and fine detail. The result: diverse poses and angles with a consistent character. It was built and tested on Anima / Qwen-Image DiT models, but it works anywhere the LoRA keys resolve onto the diffusion model.

How it actually works

Instead of merging weights like LoraLoaderModelOnly, this node hooks the forward pass of the matched modules. Every denoising step, it computes the LoRA's low-rank contribution (up after down, the standard LoRA sandwich) and adds it to that module's output, scaled by a weight that depends on the current sigma. The up/down matrices live in fp32, and the add happens in the model's native dtype.

The clever part is the window. inject_at/stop_at are denoise percentages; the node converts them to sigma bounds via the model's own sampling (percent_to_sigma), then a smoothstep ramps the weight across the window edges when fade is set. All of that runs inside a UNet function wrapper, so it survives dynamic VRAM loading - it adds to outputs, never to stored weights.

The inputs that matter

  • inject_at - where the LoRA turns on (0.0 = start, 1.0 = end). This is your main dial. 0.10–0.20 is the sweet spot; below ~0.1 you're back to constraining composition like a stock loader, above ~0.3 the effect gets noticeably weak.
  • stop_at - where it turns off. Default 1.0 (run to the end) is usually right. If you ever set it below inject_at, the node quietly bumps it to inject_at + 0.01 rather than erroring.
  • apply_to - both, positive, or negative. At CFG > 1 the model runs two passes: cond (your prompt) and uncond (the negative). positive applies the LoRA only to the cond pass, which gives you a cleaner "more LoRA" than cranking lora_strength. negative applies it only to the uncond pass - the model gets pushed away from the LoRA, so any distinctive LoRA becomes a "negative concept." That one needs strength 2.0–3.0 to be visible, and it's inherently diffuse.
  • lora_strength - same meaning as a normal loader, range −3 to 3.
  • fade - smoothing on both window edges. 0.0 is a hard on/off; 0.1–0.2 is soft.

One input that'll surprise you: force_rerun defaults to True, so every queue fires a fresh generation (its IS_CHANGED stamps the time). Great while tuning, wasteful once you've settled - flip it off.

The output is a single MODEL, and it's chainable: run one instance's output into another's model input to stack multiple scheduled LoRAs, each with its own window and its own CFG branch, all feeding one sampler. No split needed.

Install

No dependencies, no model downloads, no requirements.txt - just the node. Via ComfyUI Manager: Manager → Install via Git URL → paste https://github.com/Murdunbad/lora-scheduled-comfyui → restart. Or manually:

cd ComfyUI/custom_nodes
git clone https://github.com/Murdunbad/lora-scheduled-comfyui lora_scheduled

Restart and it appears under advanced/lora_schedule.

Gotchas worth knowing

  • CFG needs to be > 1 for apply_to to mean anything. On distilled / CFG-free models (the CFG 1 default crowd), there's no uncond pass: positive just behaves like both, and negative has nothing to attach to.
  • Use a clean base model, not a merge. The author is blunt here and right: merges have already collapsed toward a narrow compositional distribution, so there's little diversity left to preserve - scheduling on a merge buys you nothing.
  • Key-namespace caveats: native-format LoRAs (diffusion_model. keys) are fully supported; Kohya-style lora_unet_ keys are best-effort and may not map cleanly. Only the diffusion model is scheduled - no text-encoder portion, ever.
  • It monkey-patches module forward methods on the live model. That's gated and inert when no scheduled LoRA is active, but it's the trade-off that makes the dynamic-loading compatibility possible.

A sane starting recipe: apply_to = positive, lora_strength 0.5–0.8, inject_at 0.2, stop_at 1.0, fade 0.05. If you're fighting a merged checkpoint anyway, drop quality tags, lower CFG, or raise the shift - the author's own fallback advice.

Categoryadvanced/lora_schedule

Inputs (9)

NameTypeDefaultDescription
modelMODEL
lora_nameCOMBO0 options:
enabledBOOLEANtrue
apply_toCOMBOboth3 options: both, positive, negative
lora_strengthFLOAT1.00-3–3
inject_atFLOAT0.000–1
stop_atFLOAT1.000–1
fadeFLOAT0.000–0.5
force_rerunBOOLEANtrue

Outputs (1)

NameTypeDescription
MODELMODEL