comfyanonymous/ComfyUI
Architecture
ComfyUI is a Python process built around three concerns: a web server that talks to the frontend, a prompt executor that runs node graphs, and a diffusion engine that wraps PyTorch model code. Everything else — caching, model loading, custom nodes, the assets database, ComfyUI-Manager integration — hangs off these three.
Process layout
graph TB
subgraph Client
Browser[Web frontend<br/>Vue/TS bundle in web/]
Desktop[Desktop app]
ApiClient[HTTP/WebSocket client]
end
subgraph "ComfyUI process (main.py)"
Server[server.py<br/>aiohttp PromptServer]
Queue[PromptQueue]
Worker[prompt_worker thread<br/>main.py]
Executor[execution.py<br/>PromptExecutor]
Nodes[nodes.py + comfy_extras/<br/>NODE_CLASS_MAPPINGS]
Diffusion[comfy/<br/>diffusion engine]
ModelMgmt[comfy/model_management.py<br/>VRAM scheduler]
DB[(SQLite via Alembic<br/>app/database/)]
end
Browser -->|HTTP /prompt| Server
Browser <-->|WebSocket /ws| Server
Server -->|enqueue| Queue
Queue -->|dequeue| Worker
Worker -->|execute| Executor
Executor -->|invoke| Nodes
Nodes -->|load/sample| Diffusion
Diffusion --> ModelMgmt
Server --> DB
Worker -->|progress, previews| ServerThe HTTP server, prompt queue, and worker live in the same process; only the worker is on its own thread. All node execution happens on that worker so PyTorch models are touched from a single thread.
Layered code map
| Layer | Top-level paths | Responsibility |
|---|---|---|
| Entry | main.py, server.py |
Parse args, set up server, run prompt worker thread |
| Built-in nodes | nodes.py, comfy_extras/ |
The standard library of nodes (loaders, samplers, image ops, model-specific nodes) |
| API nodes | comfy_api_nodes/ |
Nodes that call paid third-party AI APIs (Kling, Veo, Stability, BFL, etc.) |
| Custom-node API surface | comfy_api/ |
Versioned public types and helpers that custom nodes import (io, ui, Input*, …) |
| Execution engine | comfy_execution/ |
Graph traversal, caching, lazy evaluation, progress tracking, jobs |
| Diffusion engine | comfy/ |
Models, samplers, text encoders, LoRA, VAE, model loading, memory management, quantization |
| HTTP routes (internal) | api_server/, middleware/ |
/internal/* routes for the frontend and middleware |
| App services | app/ |
Frontend manager, custom-node manager, user manager, model manager, assets system, DB |
| Configuration / paths | folder_paths.py, utils/extra_config.py, extra_model_paths.yaml.example |
Where models, inputs, outputs, user data live |
| Persistence | alembic_db/, app/database/, app/assets/database/ |
SQLite + Alembic migrations for assets and future data |
| Workflow templates | blueprints/ |
Stock workflow JSON files served to the frontend |
How a prompt becomes pixels
sequenceDiagram
autonumber
participant FE as Frontend
participant Srv as PromptServer (server.py)
participant Q as PromptQueue
participant W as prompt_worker (main.py)
participant Ex as PromptExecutor (execution.py)
participant N as Node class
participant CE as comfy diffusion engine
FE->>Srv: POST /prompt {prompt, client_id, extra_data}
Srv->>Srv: validate_prompt (execution.py)
Srv->>Q: put((number, prompt_id, prompt, extra_data, ...))
Q-->>W: blocking get()
W->>Ex: execute(prompt, prompt_id, extra_data, ...)
loop for each output node, then DAG ancestors
Ex->>Ex: check IsChangedCache + CacheSet
alt cached
Ex->>Ex: reuse cached outputs
else not cached
Ex->>N: NODE_CLASS_MAPPINGS[type]()
N->>CE: load_checkpoint / sample / decode
CE-->>N: tensors
N-->>Ex: outputs
end
Ex->>Srv: send_sync("progress", ...)
end
Ex->>Srv: send_sync("executed", history_result)
Srv-->>FE: WebSocket events (status, progress, executed)Validation happens before enqueue; everything else happens on the worker. The cache, configured by --cache-classic|lru|ram|none, is what makes "edit one node and re-run" cheap.
The diffusion engine in one diagram
comfy/ is a Python package, not a service. It is imported by nodes.py and comfy_extras/*.py to do the actual ML work. The two most central modules are comfy/sd.py (loaders) and comfy/samplers.py (the sampling loop).
graph LR
Checkpoint[(safetensors / ckpt)] -->|load_checkpoint_guess_config| SD[comfy/sd.py]
SD --> Detect[comfy/model_detection.py]
Detect --> Supported[comfy/supported_models.py]
Supported --> ModelBase[comfy/model_base.py]
SD --> CLIP[CLIP / text encoder<br/>comfy/sd1_clip.py + comfy/text_encoders/]
SD --> VAE[VAE<br/>comfy/ldm/.../*vae*]
SD --> Patcher[comfy/model_patcher.py<br/>ModelPatcher]
Patcher --> MM[comfy/model_management.py<br/>VRAMState scheduler]
Patcher --> Hooks[comfy/hooks.py<br/>LoRA, attention patches]
Sampler[comfy/samplers.py] --> Patcher
Sampler --> KDiff[comfy/k_diffusion/sampling.py<br/>+ extra_samplers/]
LDM[comfy/ldm/<br/>per-architecture nets] --> ModelBaseModelPatcher is the pivotal abstraction: it owns a model's weights, knows how to move them between CPU and GPU (with optional async offload), and applies LoRA and other "patches" lazily so the underlying weights stay reusable. See Model management.
Background subsystems
A few subsystems run alongside the main request/response loop:
- Asset seeder and scanner.
app/assets/seeder.pyandapp/assets/scanner.pywalkmodels/,input/,output/and populate the SQLite assets database. Enabled with--enable-assets. See Asset system. - Frontend manager.
app/frontend_management.pyresolves--front-end-version(e.g.,Comfy-Org/ComfyUI_frontend@latest) against GitHub releases and serves the chosen bundle fromweb/. - Custom-node loader.
nodes.init_extra_nodeswalkscustom_nodes/, runs prestartup scripts, imports each module, and merges itsNODE_CLASS_MAPPINGSinto the global registry. ComfyUI-Manager (when--enable-manageris set) layers extra logic on top. - Database / migrations.
app/database/db.pyinitializes SQLite via Alembic on startup. Currently used by the assets system.
Where to read next
- Prompt execution for the executor, caches, and graph
- Sampling pipeline for what
KSampleractually does - Model management for VRAM and offload
- Custom-nodes system for extension authoring
- Packages overview for a tour of every top-level Python package in the repo
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.