Apps depending on other environments
The depends_on parameter allows you to specify that one app depends on another app (or task environment). When you deploy an app with depends_on, Flyte ensures that all dependencies are deployed first.
Basic usage
Use depends_on to specify a list of environments that this app depends on:
app1_env = flyte.app.AppEnvironment(name="backend-api", ...)
app2_env = flyte.app.AppEnvironment(
name="frontend-app",
depends_on=[app1_env], # Ensure backend-api is deployed first
# ...
)When you deploy app2_env, Flyte will:
- First deploy
app1_env(if not already deployed) - Then deploy
app2_env - Make sure
app1_envis available beforeapp2_envstarts
Example: App calling another app
Here’s a complete example where one FastAPI app calls another:
"""Example of one app calling another app."""
import httpx
from fastapi import FastAPI
import pathlib
import flyte
from flyte.app.extras import FastAPIAppEnvironment
image = flyte.Image.from_debian_base(python_version=(3, 12)).with_pip_packages(
"fastapi", "uvicorn", "httpx"
)
app1 = FastAPI(
title="App 1",
description="A FastAPI app that runs some computations",
)
env1 = FastAPIAppEnvironment(
name="app1-is-called-by-app2",
app=app1,
image=image,
resources=flyte.Resources(cpu=1, memory="512Mi"),
requires_auth=False,
)
app2 = FastAPI(
title="App 2",
description="A FastAPI app that proxies requests to another FastAPI app",
)
env2 = FastAPIAppEnvironment(
name="app2-calls-app1",
app=app2,
image=image,
resources=flyte.Resources(cpu=1, memory="512Mi"),
requires_auth=False,
depends_on=[env1], # Depends on backend-api
)
@app1.get("/greeting/{name}")
async def greeting(name: str) -> str:
return f"Hello, {name}!"
@app2.get("/app1-endpoint")
async def get_app1_endpoint() -> str:
return env1.endpoint # Access the backend endpoint
@app2.get("/greeting/{name}")
async def greeting_proxy(name: str):
"""Proxy that calls the backend app."""
async with httpx.AsyncClient() as client:
response = await client.get(f"{env1.endpoint}/greeting/{name}")
response.raise_for_status()
return response.json()
if __name__ == "__main__":
flyte.init_from_config(root_dir=pathlib.Path(__file__).parent)
deployments = flyte.deploy(env2)
print(f"Deployed FastAPI app: {deployments[0].env_repr()}")
When you deploy env2, Flyte will:
- Deploy
env1first (backend-api) - Wait for
env1to be ready - Deploy
env2(frontend-api) env2can then accessenv1.endpointto make requests
Dependency chain
You can create chains of dependencies:
app1_env = flyte.app.AppEnvironment(name="service-1", ...)
app2_env = flyte.app.AppEnvironment(name="service-2", depends_on=[app1_env], ...)
app3_env = flyte.app.AppEnvironment(name="service-3", depends_on=[app2_env], ...)
# Deploying app3_env will deploy in order: app1_env -> app2_env -> app3_envMultiple dependencies
An app can depend on multiple environments:
backend_env = flyte.app.AppEnvironment(name="backend", ...)
database_env = flyte.app.AppEnvironment(name="database", ...)
api_env = flyte.app.AppEnvironment(
name="api",
depends_on=[backend_env, database_env], # Depends on both
# ...
)When deploying api_env, both backend_env and database_env will be deployed first (they may be deployed in parallel if they don’t depend on each other).
Using AppEndpoint for dependency URLs
When one app depends on another, you can use AppEndpoint to get the URL:
backend_env = flyte.app.AppEnvironment(name="backend-api", ...)
frontend_env = flyte.app.AppEnvironment(
name="frontend-app",
depends_on=[backend_env],
inputs=[
flyte.app.Input(
name="backend_url",
value=flyte.app.AppEndpoint(app_name="backend-api"),
),
],
# ...
)The backend_url input will be automatically set to the backend app’s endpoint URL.
You can get this value in your app code using flyte.app.get_input("backend_url").
Deployment behavior
When deploying with flyte.deploy():
# Deploy the app (dependencies are automatically deployed)
deployments = flyte.deploy(env2)
# All dependencies are included in the deployment plan
for deployment in deployments:
print(f"Deployed: {deployment.env.name}")Flyte will:
- Build a deployment plan that includes all dependencies
- Deploy dependencies in the correct order
- Ensure dependencies are ready before deploying dependent apps
Task environment dependencies
You can also depend on task environments:
task_env = flyte.TaskEnvironment(name="training-env", ...)
serving_env = flyte.app.AppEnvironment(
name="serving-app",
depends_on=[task_env], # Can depend on task environments too
# ...
)This ensures the task environment is available when the app is deployed (useful if the app needs to call tasks in that environment).
Best practices
- Explicit dependencies: Always use
depends_onto make app dependencies explicit - Circular dependencies: Avoid circular dependencies (app A depends on B, B depends on A)
- Dependency order: Design your dependency graph to be a DAG (Directed Acyclic Graph)
- Endpoint access: Use
AppEndpointto pass dependency URLs as inputs - Document dependencies: Make sure your app documentation explains its dependencies
Example: A/B testing with dependencies
Here’s an example of an A/B testing setup where a root app depends on two variant apps:
app_a = FastAPI(title="Variant A")
app_b = FastAPI(title="Variant B")
root_app = FastAPI(title="Root App")
env_a = FastAPIAppEnvironment(name="app-a-variant", app=app_a, ...)
env_b = FastAPIAppEnvironment(name="app-b-variant", app=app_b, ...)
env_root = FastAPIAppEnvironment(
name="root-ab-testing-app",
app=root_app,
depends_on=[env_a, env_b], # Depends on both variants
# ...
)The root app can route traffic to either variant A or B based on A/B testing logic, and both variants will be deployed before the root app starts.
Limitations
- Circular dependencies are not supported
- Dependencies must be in the same project/domain
- Dependency deployment order is deterministic but dependencies at the same level may deploy in parallel