Skip to main content
This tutorial shows how to deploy ComfyUI with SDXL Turbo on fal. We’ll create a proxy app that wraps ComfyUI with a clean REST API, complete with Pydantic validation and automatic CDN uploads. SDXL Turbo generates high-quality images in just 1-4 inference steps, making it ideal for fast serverless inference.

🚀 Try this Example

Steps to run:
  1. Install fal:
  1. Authenticate:
  1. Create the workflow file sdxl_turbo_workflow.json:
  1. Copy the code below into comfyui_sdxl_turbo.py:
  1. Run the app:
Before you run, make sure you have:
  • Authenticated with fal: fal auth login
  • Created the sdxl_turbo_workflow.json file in the same directory

Architecture Overview

The app runs ComfyUI as a background process and communicates with it via HTTP:

Key Concepts

Including the Workflow File

Container apps don’t support COPY instructions or app_files for including local files. Instead, we upload the workflow to fal’s CDN and use ADD in the Dockerfile:
See Use Custom Container Images for more details.

Runtime Model Loading

Large model weights are downloaded to /data (persistent storage) at runtime using download_model_weights from fal’s toolkit:
The download_model_weights function:
  • Atomic writes: Downloads to a temp file first, then renames (prevents corrupted files if multiple workers start simultaneously)
  • Automatic caching: Skips download if the file already exists
  • Smart storage: Saves to /data/.fal/model_weights/{hash}/{filename}
Why not bake models into Docker?
  • Docker images must be pulled on cold starts - larger images = slower cold starts
  • /data is a distributed filesystem - once downloaded, models are available to all workers

Symlinking Models

ComfyUI expects models in specific directories. We create symlinks from ComfyUI’s model directories to the downloaded paths:

Background Server with Popen

ComfyUI runs as a non-blocking background process using subprocess.Popen. Unlike subprocess.run() which blocks until completion, Popen starts the process and returns immediately, allowing your app to continue setup:
The server continues running for the lifetime of the worker, handling multiple requests.

ComfyUI API Interaction

The app communicates with ComfyUI via its HTTP API:
  1. Queue prompt: POST /prompt with the workflow JSON
  2. Poll for completion: GET /history/{prompt_id} until completed: true
  3. Get outputs: Extract file paths from the history response

Image Output with fal Toolkit

Use Image.from_path() to upload generated images to fal’s CDN:
The request parameter ensures proper metadata is attached for the fal playground.

Customizing the Workflow

Exporting from ComfyUI

  1. Build your workflow in ComfyUI’s web interface
  2. Click Save (API Format) to export as JSON
  3. Replace the contents of sdxl_turbo_workflow.json

Mapping Node IDs

When you export a workflow, each node has an ID. Update _build_workflow() to map your inputs to the correct node IDs:

Best Practices

  1. Use /data for model weights: Download large models to /data in setup() instead of baking them into the Docker image. This improves cold start times.
  2. Pin your dependencies: Specify exact versions in the Dockerfile to ensure reproducible builds.
  3. Set appropriate timeouts: Model loading and generation can take time. Use generous timeouts.
  4. Use keep_alive: Set keep_alive to avoid cold starts between requests.

Troubleshooting

Model Not Found

Check that:
  1. The model is downloaded to the correct path in /data
  2. The symlink points to the correct file
  3. The workflow uses the correct model filename

Permission Errors in Dockerfile

The falai/base image runs as a non-root user. Add USER root before apt-get:

Using an External Registry?

If you have a ComfyUI Docker image hosted on an external registry (Docker Hub, Google Artifact Registry, Amazon ECR, Azure Container Registry), you can pull it directly instead of building from a Dockerfile. See Using Private Docker Registries for setup instructions.

Next Steps