Skip to main content
If you have been running serverless GPU workloads on RunPod, this guide maps RunPod concepts to their fal equivalents and shows how to convert your code. The core ideas are similar: both platforms run your code on GPU machines that scale based on demand. The main difference is that RunPod uses a handler function pattern with explicit Docker builds, while fal uses a class-based fal.App with automatic container builds. For a broader overview of deploying existing Docker containers on fal (regardless of where they came from), see Deploy an Existing Server. If you are comparing fal to other platforms, see Migrate from Replicate or Migrate from Modal.

Concept Mapping


Migration Path: Handler to fal.App

The most common pattern on RunPod is a handler function that loads a model at module level and processes requests. On fal, this maps to a fal.App class where model loading moves into setup() and the handler becomes an endpoint method.
Key differences in the fal version: The model loading moves from module-level into setup(), which runs once per runner rather than once per container build. Inputs are validated through a Pydantic model instead of manually extracting from job["input"]. Outputs are also typed, and images are automatically uploaded to the fal CDN rather than saved to a local path. You do not need to write a Dockerfile or push to Docker Hub since fal builds the container from your requirements list.

Calling Your Deployed App

RunPod exposes /run (async), /runsync (sync), and /stream endpoints. fal provides equivalent patterns through the client SDK.
For the full range of calling patterns including streaming, real-time WebSockets, and webhooks, see Calling Your Endpoints.

Deployment Workflow

On RunPod, the deployment unit is a Docker image. Your handler code lives inside the image, and the workflow requires several manual steps: write a Dockerfile that copies your handler and installs dependencies, build the image locally, push it to Docker Hub, then deploy through RunPod’s console by pointing it at the image URL.
On fal, the normal RunPod queue-handler migration does not require a manual Docker build, Docker Hub, or console-based deployment. Validate your app with fal run first — it runs setup() and your endpoints on a temporary worker so container-build and model-loading errors surface before they become a production crashloop — then run fal deploy and fal handles the container build, image storage, and deployment. Your code and your environment definition live in the same Python file.

Reusing an HTTP server image

RunPod always deploys a container image, but not every RunPod Serverless image is an HTTP server. Queue endpoints typically run a handler with runpod.serverless.start(...); those still need the migration path above. If your RunPod image already exposes an HTTP server, you can reference the existing image directly from pyproject.toml instead of converting it to fal.App.
If the image itself is private, configure registry credentials under the app’s image configuration. See Private Docker Registries for Docker Hub, Google Artifact Registry, Amazon ECR, and Azure Container Registry examples. Deploy it by app name:
For the full direct-server flow, including private registry setup and OpenAPI notes, see Deploy an Existing Server.

Environment and Dependencies

Because fal eliminates the Docker build step for most use cases, you have two options for defining your environment: Option 1: pip requirements (recommended). List your packages in the requirements attribute. fal builds the container automatically. This is the simplest migration path since you can copy the pip install lines from your RunPod Dockerfile directly into the list.
Option 2: Custom Docker container. If you need system packages, a specific CUDA version, or want to reuse your existing RunPod Dockerfile with minimal changes, use ContainerImage. You can paste your RunPod Dockerfile almost as-is, just remove the COPY handler.py and CMD lines since fal handles those.

Model Storage

RunPod offers three approaches for model weights: Hugging Face cache, baked into the Docker image, or network volumes. fal’s equivalent is persistent storage at /data, which is mounted on every runner and shared across your account. Models downloaded to /data are cached automatically and survive runner restarts, similar to RunPod’s network volumes but without explicit volume configuration.

Next Steps

Once you have migrated your handler, the App Lifecycle page explains how the full lifecycle works on fal, from code serialization to runner shutdown. For scaling configuration, see Scale Your Application. For monitoring your deployed app, see App Analytics.