The App Class
An App is a Python class that inherits fromfal.App. It is the unit of deployment on fal. Your app defines what hardware it needs, how to initialize your model, and what endpoints are available for callers. When you run fal deploy, fal serializes this class and ships it to the remote runtime.
machine_type attribute tells fal which hardware to provision. The setup() method runs once when a runner starts, loading your model into GPU memory. Endpoint methods handle individual requests. And teardown() runs when the runner shuts down, giving you a chance to release resources. For the full lifecycle, see App Lifecycle.
What Runs Locally
When Python imports your app file, all top-level code executes on your machine. This is standard Python behavior: class bodies are evaluated, module-level variables are assigned, and helper functions are defined. This happens duringfal run or fal deploy, before anything is sent to the cloud.
This means that if you reference an environment variable at the top level, it reads from your local environment, not the remote runner’s environment. If you construct a large object at module scope, it will be serialized (pickled) and shipped as part of the app payload. This is intentional for small configuration values but problematic for large objects.
CONFIG is evaluated locally and pickled into the app payload. The helper function is defined locally but its body only executes remotely when called. The import torch inside the function runs on the remote runner, not on your machine.
What Runs Remotely
Yourfal.App subclass is pickled locally, then unpickled and instantiated on the remote runner in the environment you configured (either via pip requirements or a custom Docker container). All methods on the class, including setup(), your @fal.endpoint handlers, and teardown(), execute on the remote machine.
Symbols referenced by your app are handled in one of two ways. Small objects (closures, constants, simple data structures) are pickled and shipped as part of the payload. Importable packages that are installed in the remote environment are imported there rather than being serialized. This is why you often see imports inside methods rather than at the top of the file: it ensures the import happens in the remote environment where the package is installed.
CONFIG is a small dictionary that gets pickled and shipped to the runner. The diffusers import happens inside setup(), so it runs remotely where the package is installed via requirements. The StableDiffusionXLPipeline is loaded into GPU memory on the runner, not on your laptop.
The Serialization Boundary
The boundary between local and remote is the pickle serialization step. When fal prepares your app for deployment, it pickles the class and any objects it references. This has practical implications. Objects that pickle well (strings, numbers, dicts, lists, simple dataclasses) can be freely referenced from top-level code. Objects that do not pickle well (database connections, file handles, GPU tensors, large numpy arrays) should be created insidesetup() or endpoint methods, where they run on the remote machine.
If you need to pass secrets to your app, avoid putting them in top-level code where they would be pickled into the payload. Instead, use fal’s secrets management to store them securely and access them via environment variables on the runner.