
Qwen-Image-2.1 Workflow: The Node Chain, the Dials, and What Changed Since Day Zero
- OrcaNEWOrca: OrcaCyber Zero 1.52026-10-10$3.00 / $7.50 per 1M tokens · 62 tok/s
- openaiNEWOpenAI: GPT-6.1 Sol2026-09-2952Intelligence
- anthropicAnthropic: Claude Sonnet 5.52026-09-2856Intelligence
- typesafeTypeSafe: Jev 1.132026-09-24$0.04 / $0.00 per 1M tokens · 324 tok/s
- OpenAIOpenAI: GPT-6 Luna2026-09-2238Intelligence
- OpenAIOpenAI: GPT-6 Sol2026-09-2248Intelligence
- AnthropicAnthropic: Claude Opus 5.52026-09-2258Intelligence
- xAIGrok 4.72026-09-2146Intelligence
- OrcaOrca: OrcaCyber Zero 1.02026-09-17$3.00 / $7.50 per 1M tokens · 42 tok/s
- OrcaOrca: OrcaVerify Text 1.02026-09-16$2.00 / $0.00 per 1M tokens · 239 tok/s
- DeepSeekDeepSeek: DeepSeek V4.1 Flash2026-09-1040Intelligence
- OpenAIOpenAI: GPT-6 Astra2026-09-0453Intelligence77Coding
- GoogleGoogle: Gemini 3.8 Flash2026-09-0241Intelligence76Coding
- AlibabaQwen: Qwen3.8 Max (0902)2026-09-0245Intelligence76Coding
- AnthropicAnthropic: Claude Fable 5.12026-09-0153Intelligence82Coding
- TencentTencent: Hy4 preview2026-08-28$0.83 / $2.50 per 1M tokens · 56 tok/s
- AlibabaQwen: Qwen3.8 Flash2026-08-26$0.15 / $0.47 per 1M tokens · 116 tok/s
- z-aiZ.ai: GLM 5.3 Flash2026-08-2642Intelligence72Coding
- DeepSeekDeepSeek: DeepSeek V4 Flash Vision (Exp)2026-08-21$0.22 / $0.66 per 1M tokens · 213 tok/s
- z-aiZ.ai: GLM 5.32026-08-1845Intelligence75Coding
What you get from this page is a Qwen-Image-2.1 graph you can rebuild from scratch and reproduce — the node chain by the names the loaders actually use, the four or five dials that decide whether the output is what you asked for, and the two settings people change without knowing they have changed the noise schedule. The model itself is the vendor's unified text-to-image and image-editing release, open-sourced on 20 September 2026 under a research licence: 7B parameters in the visual generation component, 32 single-stream DiT layers, a 64-channel RGBA VAE at 16x spatial compression, and up to ten reference images on the editing path. That date is here to tell you which checkpoint you are wiring, not to announce anything. The graph is the subject, and the graph has a revision history worth reading before you trust someone else's screenshot of it — the template that ships today is not the template that shipped on day zero, and four of the differences are exactly the things a reader gets wrong.
Which graph this page is describing
Everything below is read from the ComfyUI workflow template repository Comfy-Org/workflow_templates, at the revision current on 13 October 2026, running on ComfyUI stable v0.39.0 (published 5 October 2026). Node names are the display names the loaders use in the graph; where a node was added or renamed between revisions, the date is given. The route to these files is ComfyUI's own tutorial page for Qwen-Image-2.1 — there are three templates in it, and this page follows the text-to-image one, then bends it.
The three templates are Qwen-Image-2.1 Text to Image, Qwen-Image-2.1 Image Edit, and Remove Background: Qwen-Image-2.1. The last one is not a different graph: ComfyUI's documentation says it reuses the image-edit subgraph with the prompt "Remove the background, and output a PNG image". So there are two graphs to learn, and one of them is a prompt template on top of the other.
The node chain, in order
The text-to-image template is a subgraph — one collapsible node on the canvas with eighteen exposed inputs — wrapping a thirteen-node chain. Inside it, the order is:
• UNETLoader — loads qwen_image_2.1_int8_convrot.safetensors with the weight dtype left at default. This is the diffusion model, and the file you pick here is the first thing that decides whether your run matches anyone else's.
• Qwen Image 2.1 Cache — sits between the loader and the sampler. It is not optional in the current template, but it is bypassable, and it is the node most likely to be missing from a graph you downloaded in the first week.
• KSampler — takes the model from the cache node, the positive and negative conditioning from the text encoder, and an empty latent. Its widgets in the shipped template read: seed 0, control fixed, steps 25, cfg 1, sampler euler, scheduler simple, denoise 1.
• EmptyLatentImage — width and height are wired in from the Resolution Selector node that sits outside the subgraph, and its third input, batch size, ships at 1.
• VAEDecode → SaveImageAdvanced — the decoder hands pixels to the save node, whose filename prefix is Qwen_image_2.1 and whose format ships as PNG, 8-bit, sRGB. PNG is not cosmetic here: the VAE carries four channels, so 8-bit PNG is what keeps the alpha channel alive on the way to disk.
• CLIPLoader — loads qwen3vl_8b_int8_convrot.safetensors with the type set to qwen_image. Qwen3-VL 8B is the text encoder, and it is also the vision tower that reads your reference images.
• Text Encode Qwen Image 2.1 (node id TextEncodeQwenImage21) — conditions the prompt. It takes the clip, a prompt, a negative prompt, an optional VAE, a resolution integer, and an autogrowing set of image slots named image_1 through image_16. It returns three things: positive conditioning, negative conditioning, and a latent. That latent is the part people miss — it is an empty latent sized to the first reference image, and on the text-to-image graph it is unused because the empty latent comes from the Resolution Selector instead.
• VAELoader — qwen_image_2.1_vae_bf16.safetensors, feeding both the decoder and the text encoder's reference-image path.
The optional branch is the last piece. A second CLIPLoader loads qwen3.5_9b_qwen_image_2.1_pe_t2i.int8_convrot.safetensors with the type set to stable_diffusion — not qwen_image, and that difference is deliberate, because this is a text-generation checkpoint, not the vision encoder. It feeds a Generate Text node, whose output goes through Preview Any to the sampler's positive prompt, switched by a ComfySwitchNode wired to the refine_prompt input. A Primitive String (Multiline) node holds the system prompt the rewrite follows, and you can read it and edit it.
Count the chain and it is six nodes of real work: load the diffusion model, load the text encoder, load the VAE, encode the prompt, sample from an empty latent, decode and save. Everything else in the template is memory or convenience.

What changed between the day-zero graph and this one
This is the part worth knowing before you copy a workflow out of a tutorial screenshot, because the Qwen-Image-2.1 templates were edited five times after they first landed, and the edits are not cosmetic.
• 20 September 2026 — the first template. Commit 96309bd530, "Add Qwen Image 2.1 template". Seven nodes in the text-to-image subgraph: the loaders, the encoder, the empty latent, the sampler, the decoder. The CLIP loader was set to the bfloat16 text encoder, qwen3vl_8b_bf16.safetensors — the 16.33 GB file.
• 20 September 2026, later the same day. Commit 371a7b7171 switched that loader to qwen3vl_8b_int8_convrot.safetensors, the 8.71 GB file, with the message "Switch Qwen Image 2.1 CLIP to int8 convrot". The template's own note labels it "loaded by the templates, lower memory". A workflow built from the morning's file and one built from the evening's are not the same workflow.
• 25 September 2026. The Qwen Image 2.1 Cache node appeared in the graph for the first time, together with the whole prompt-enhancement branch — the second CLIP loader, Generate Text, Preview Any, the switch, the system-prompt node. Before this date there was no cache node to set and no rewrite step to turn off. The image-edit template gained the matching inputs on the same day. The text-to-image note also gained, in this revision, both the 4-megapixel line and the transparent-image prompt wrapper.
• 28 September 2026. File sizes were added to the download notes — a documentation change, not a graph change, but it is where the numbers a reader checks against their download manager come from.
• 30 September 2026. Commit 9fae1041be, "Qwen Image 2.1: Update PE settings" — the last time either 2.1 template was touched. This is the one that matters most and the least visible. Three values on the Generate Text node moved: the token budget max_length from 16256 down to 4096, the repetition penalty from 1.05 to 1.0, and thinking from off to on, with the node's own note now saying the checkpoint "was trained with a reasoning block and loses quality without it". The template notes describe the earlier values as the official ones and say the cap exists so "a single rewrite cannot run for many minutes".
What did not change is the useful half of this. The sampling block is byte-identical between the day-zero template and today's: steps 25, cfg 1, euler, simple, denoise 1, seed control fixed, an empty latent at the Resolution Selector's output, batch size 1. The graph was never fixed by moving the sampler. It was fixed by changing which text-encoder file loads, adding the cache node, and correcting the prompt-enhancer's own settings.
One more layer sits under the graph. ComfyUI's core kept changing after the templates settled: v0.38.0 on 29 September improved the Qwen 2.1 KV cache location logic, and v0.39.0 on 5 October shipped "Fix crash when selecting int8 or int4 cache in qwen image 2.1". If your graph is today's and your build is older than that, the cache dropdown is not a slow option, it is a crash.

The dials a reader is most likely to get wrong
Start from what the docs state flatly, because it removes most of the guesswork. All three Qwen-Image-2.1 workflows sample with steps 25, cfg 1, the euler sampler, and the simple scheduler. That is ComfyUI's own summary, and it matches the shipped widgets exactly.
The complication is that 25 and 40 are both correct answers to different questions. The vendor's own model card runs the diffusers pipeline at num_inference_steps=40, and the diffusers pipeline's default is 40 as well; ComfyUI's documentation says the published pipeline "uses about 40 to 50 steps with the euler sampler, and the template starts lower at 25". Neither number is an error. They are a graph default and a reference run.
• Steps — direction and trade-off. Lower is faster and, per ComfyUI's documentation, holds up differently depending on the job: simple localized edits hold up at 4 to 8 steps, "while edits that rewrite the whole frame lose coherence and need the full 25". Stubborn fine detail such as hands and fingers "settles by about 30 steps", and going from 25 to 40 reduces fizzle in detailed areas. The direction is monotone and the trade-off is linear: the doc's advice is to adjust steps only when something specific fails to resolve, not to raise them for safety.
• Guidance — cfg 1 is guidance off, and that is the published path. At cfg 1 ComfyUI skips the negative conditioning pass, so a negative prompt has no effect. The template keeps cfg 1, "which is the path Qwen-Image-2.1 is published for"; the diffusers pipeline says the same thing in its own words, defaulting true_cfg_scale to 1.0 because "Qwen-Image 2.1 is meant to be sampled without guidance". Raise it only when you actually want the negative prompt to take effect, and know the price: cfg 2 follows dense prompts more closely, including small text and numbers, "at the cost of over-sharpened edges"; higher values shift exposure toward over-bright or over-dim; cfg 5 degrades quality badly; cfg 0.5 breaks the image. ComfyUI's instruction is to change one value at a time and compare at a fixed seed.
• Resolution is a megapixel target, not a rectangle. The Resolution Selector node sets an aspect ratio and a megapixel budget, where 1.0 MP is about 1024x1024. Qwen-Image-2.1 generates natively at 2K, so the target for a 2048x2048 square is about 4.0 MP. Multiples of 32 are what the model wants — the tooltip on the text encoder's resolution input says references are resized to about resolution x resolution pixels at multiples of 32, aspect ratio preserved, and the pipeline's own dimension helper rounds to 32 as well. The vendor's model card publishes the 2K presets: 1:1 at 2048x2048, 4:3 at 2400x1792, 3:4 at 1792x2400, 3:2 at 2528x1696, 2:3 at 1696x2528, 16:9 at 2752x1536, 9:16 at 1536x2752.
• Overshooting 2K costs adherence, not sharpness. Targets well above the model's trained 2K size, such as 4K, lose prompt adherence. That is a documented behaviour, not an inference from the architecture.
• The one that is genuinely counter-intuitive: resolution also moves the noise schedule. Qwen-Image-2.1 samples with a flow-matching Euler scheduler whose timestep shift is dynamic, and the pipeline computes the shift from the length of the latent sequence — that is, from how many tokens your chosen resolution produces. The checkpoint's scheduler config sets base_shift 0.5 and max_shift 0.9 across an image-sequence range of 256 to 8192, and the pipeline feeds your run's sequence length into that formula on every call. Changing the canvas therefore changes the sampler's schedule, not just the frame. In the ComfyUI template there is no shift control to set — the KSampler's inputs are model, positive, negative, latent image, seed, steps, cfg, sampler name and scheduler, and that is the whole list. If your results at 4 MP look unlike your results at 1 MP in a way you cannot explain by detail alone, this is why.
• On the edit graph, resolution behaves differently and is the single most expensive default. With custom_size off — the template default — the edit is generated at the size of the first reference image. resolution 0 keeps each reference at its own pixel size rounded to a multiple of 32, so a 3000x4000 photo produces a 3008x4000 canvas. A value above 0 instead scales that image's aspect ratio to a resolution x resolution pixel budget — a total pixel count, not a width. ComfyUI's own cost example, measured on an RTX 5090: the 3000x4000 reference at resolution 0 is about 6 seconds per iteration; the same edit at resolution 1024 is about 0.3 seconds per iteration, at roughly 896x1184. Turn custom_size on and take the canvas from the Resolution Selector, and keep it close to the resized first-image size, "otherwise the edit can shift".
Determinism: what a seed fixes, and what it does not
A fixed seed is necessary and not sufficient, and the shipped templates disagree with each other about it. The text-to-image KSampler ships with control fixed; both edit templates — the image edit and the background removal — ship with control randomize. Same sampler, same defaults, opposite behaviour on re-queue.
Assume the seed is fixed. Here is what still moves the image:
• The KV cache. This is the big one, and it is documented rather than folklore. Qwen-Image-2.1 caches the text and reference-image keys and values after the first step; the pipeline source explains that this is valid because the conditioning tokens are step-independent under the model's causal conditioning. Then it says the thing that matters to anyone trying to reproduce a picture: toggling the cache "does not reproduce the same image bit-for-bit in reduced precision", because the decode step attends with a different sequence layout than the prefill step, the two tile differently and land on different rounding — and a one-ULP difference at the first block is amplified by 32 blocks and every sampler step, so "the two settings give equally valid but visibly distinct samples". The source's own instruction is: fix a sample by fixing this flag. In ComfyUI the flag lives on the Qwen Image 2.1 Cache node, as device (auto, gpu, cpu, off) and dtype (default, int8, int4).
• The cache node's own release history. It did not exist before 25 September 2026, so a day-zero workflow has no such setting and does not behave like today's. And off — the one setting that rules the cache out — "recomputes the prefix every step, which is slower but is the one way to rule the cache out".
• Which model files. The template loads an int8 diffusion model and an int8 text encoder. Swap either for the bf16 file and you have changed the arithmetic. The download notes list both, with their sizes, precisely because the choice is real.
• The prompt enhancer, if it is on. With refine_prompt on, the image model samples from the rewritten prompt, not the one you typed — and the rewrite is generated by a separate Generate Text node with its own sampling parameters: temperature 1.0, top_k 20, top_p 0.95, its own seed field, and a max_length token budget. Your KSampler seed does not cover any of that. The Preview Any node inside the subgraph shows the prompt that actually reached the image model, which is the only way to know what you just reproduced.
• The ComfyUI build. The templates carry their own warning: missing nodes when loading a workflow usually mean the build predates the nodes, and Desktop and Cloud follow stable releases and can lag a nightly.
So reproducing someone else's Qwen-Image-2.1 image is not a seed swap. It is the template revision, the two model files, the resolution setting, steps, cfg, sampler, scheduler, the cache device and dtype, the enhancer's on/off state and its own seed — and, for the edit graph, the size of the first reference image. ComfyUI publishes no seed-reproducibility guarantee for these workflows, and the diffusers source says plainly that a cache toggle changes the sample; treat an exact match as something you assemble deliberately rather than something a seed hands you.

More than one image, and where the memory goes
The graph produces one image per run in the shipped configuration, and the knob for changing that is unglamorous: the EmptyLatentImage node's third input, batch size, wired at 1. Raising it is what makes the sampler emit several images from one queue.
What that costs is where this gets honest. The templates tell you exactly where the cache lives — auto uses spare VRAM and then system RAM; cpu prefetches behind compute and the documentation describes it as costing little speed; off recomputes the prefix every step and is slower. They quantify the precision side: int8 halves the cache at about bf16 accuracy, and int4 quarters it but roughly doubles the per-step error. What they do not publish is a batch-size-to-VRAM table, and neither does ComfyUI's documentation. If you are sizing a batch for a card, the honest answer is that no first-party figure covers it; the levers with published effects are the cache device and dtype, and the resolution target, which raises both the latent count and the cached prefix.
Two batch traps sit on the other side of the fence, in the diffusers pipeline, and both are worth knowing because the ComfyUI graph hides them. There, num_images_per_prompt multiplies the batch, and if you pass a list of generators its length must match the effective batch size exactly or the pipeline raises. And a list of condition images is "one set of images shared by every prompt in the batch, not one entry per prompt" — you cannot give each prompt in a batch its own reference image; the source's instruction is to call the pipeline once per prompt instead. The editing subgraph has the same shape of constraint in a different place: its BatchImagesNode batches up to ten reference images into the text encoder, which is batching inputs, not outputs. Ten references do not give you ten pictures.
Image-to-image from the same graph
You do not need a different graph for this. The image-edit template is the text-to-image chain with the empty latent swapped for the text encoder's latent output, two LoadImage nodes feeding image_1 and image_2 into the subgraph's reference slots, and an ImageCompare node at the end so you can see the input beside the output. Put one image in image_1, leave image_2 empty, write an instruction, and that is image-to-image: your picture is context the model reads, not a starting latent it partially denoises. There is no strength or denoise slider on this path to set, because the target starts from noise and your reference enters through the encoder and the VAE instead.
Here is the boundary, in one sentence each, because these two are one search apart and people reach for the wrong one.
• Image-to-image is when you want a variation: you hand the model an image and a description, and it paints a new picture that resembles yours, at a canvas you choose.
• Editing is when you want a change: you hand the model an image and an instruction naming what should be different, plus optionally a mask or painted marks, and the model keeps the rest of the frame.
The tell is in the sentence you are about to type. "Make it look like this but at night" is i2i; "change the jacket to red, leave everything else" is an edit, and on this graph the edit path is where masks, the ten reference slots, and the localized-edit behaviour live. That neighbouring question is a different page's subject, and this one stops at the line so you can tell which you are on.
The turbo checkpoint, in one paragraph
One cross-reference, because the turbo spelling sits inside this query family and a reader will meet it. Qwen-Image-2.1-Turbo is a separate 8-step checkpoint of the same 7B visual generation architecture, released on 9 October 2026 and loaded by the same QwenImage21Pipeline. Its own model card says the checkpoint "includes its recommended sampling schedule, so it is ready to use without manually configuring the scheduler", that generation uses CFG 1 by default, and that setting num_inference_steps alone does not override the saved schedule — an explicit call-time sigmas argument does. None of that changes the node chain on this page: same loaders, same encoder, same sampler node. What changes is where the schedule comes from, which is the one thing worth checking in your graph before you compare a turbo run against a base-model run and conclude the model got worse.
What to do next, in the graph
Load the template from ComfyUI's template library rather than from a screenshot, then read four nodes before you queue anything. On Resolution Selector, set the aspect ratio you actually want and, if you want the model's native 2K, the 4.0 MP target. On the KSampler, confirm control is fixed if you intend to reproduce a run, and leave steps at 25 and cfg at 1 until something specific fails. On the Qwen Image 2.1 Cache, decide device and dtype now and write them down, because you cannot change them later and compare two images as if only the prompt moved. And on the Generate Text node, leave refine_prompt off until you have a baseline you like — then turn it on, read the rewrite in Preview Any, and keep the seed you were on so the comparison means something.
