LoRA Scheduled (timestep)
Stop Letting Your LoRA Hog the Whole Denoise
- model
- MODEL
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 belowinject_at, the node quietly bumps it toinject_at + 0.01rather than erroring.apply_to-both,positive, ornegative. At CFG > 1 the model runs two passes: cond (your prompt) and uncond (the negative).positiveapplies the LoRA only to the cond pass, which gives you a cleaner "more LoRA" than crankinglora_strength.negativeapplies 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_toto mean anything. On distilled / CFG-free models (the CFG 1 default crowd), there's no uncond pass:positivejust behaves likeboth, andnegativehas 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-stylelora_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
forwardmethods 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.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| lora_name | COMBO | 0 options: | |
| enabled | BOOLEAN | true | — |
| apply_to | COMBO | both | 3 options: both, positive, negative |
| lora_strength | FLOAT | 1.00-3–3 | — |
| inject_at | FLOAT | 0.000–1 | — |
| stop_at | FLOAT | 1.000–1 | — |
| fade | FLOAT | 0.000–0.5 | — |
| force_rerun | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |