This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: fastapi-0-115-async-lifespan-subapp-isolation

FastAPI 0.115+ Async Lifespan Sub-Application Scope Isolation Standard

Enforces strict ASGI lifespan context isolation between root FastAPI orchestrators and mounted sub-applications in FastAPI 0.115+. Prevents shared mutable state, connection handle leakage, and skipped sub-application lifespan teardown phases when mounting isolated services or multi-tenant sub-apps under a shared server process.

Prohibited Anti-Pattern: Mounting Sub-Applications with Root-Inherited State or Uninvoked Isolated Lifespans

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI 0.115+ Async Lifespan Sub-Application Scope Isolation Standard - Enforces strict ASGI lifespan context isolation between root FastAPI orchestrators and mounted sub-applications in FastAPI 0.115+. Prevents shared mutable state, connection handle leakage, and skipped sub-application lifespan teardown phases when mounting isolated services or multi-tenant sub-apps under a shared server process.
globs: **/app/**/*.py, **/api/**/*.py, **/main.py, **/routers/**/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-0-115-async-lifespan-subapp-isolation"
---

# FastAPI 0.115+ Async Lifespan Sub-Application Scope Isolation Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Mounting Sub-Applications with Root-Inherited State or Uninvoked Isolated Lifespans

## System Constraints
You are a Principal Software Architect enforcing FastAPI 0.115+ sub-application isolation and ASGI lifespan invariants. FastAPI mount operations do not automatically trigger child application lifespan contexts unless explicitly orchestrated or decoupled. You must prevent cross-tenant state leakage, global variable sharing via request.app.state across mount boundaries, unclosed database connection pools, and orphaned asynchronous resources resulting from implicit or improperly mounted sub-applications.

## Strict Guidelines
- Engineers MUST ALWAYS declare dedicated, asynccontextmanager-decorated lifespan generators for both root applications and mounted sub-applications, ensuring state is attached strictly to the respective local app.state.
- Engineers MUST NOT rely on Starlette/FastAPI's default `mount()` behavior to automatically trigger mounted sub-application lifespan managers without an explicit composite lifespan orchestrator or lifespan-aware proxy wrapper.
- Services MUST explicitly pass initialized tenant or domain resource managers into the sub-app's lifespan context or request dependencies rather than reading parent `app.state` globally.
- Code MUST use FastAPI 0.115+ typed state access patterns and ensure all database pools, HTTP client sessions, and cache clients instantiated within a sub-app's lifespan are gracefully closed in `finally` blocks during shutdown.
- Engineers MUST NEVER mutate the root application's `app.state` from within a mounted sub-application route or middleware.

## Bad vs Good Implementations
### Sub-Application Lifespan Orchestration and Isolated State Access

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Mounting a sub-app in FastAPI/Starlette does not execute the sub-app's lifespan context manager. Accessing sub_app.state.client raises an AttributeError at runtime or leads developers to mistakenly leak the root application's client across tenant sub-apps.
```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
import httpx

# Anti-pattern: Sub-app relies on root app lifespan or uninvoked sub-app lifespan.
# In FastAPI, mounting sub_app does not run sub_app's lifespan by default,
# leaving sub_app.state uninitialized or leaking shared root resources across tenants.
@asynccontextmanager
async def bad_subapp_lifespan(app: FastAPI):
    app.state.client = httpx.AsyncClient()
    yield
    await app.state.client.aclose()

sub_app = FastAPI(lifespan=bad_subapp_lifespan)
root_app = FastAPI()

# Sub-app lifespan is silently ignored by Starlette when mounted directly
root_app.mount("/tenant-a", sub_app)

@sub_app.get("/data")
async def get_data():
    # AttributeError or uninitialized state at runtime
    return await sub_app.state.client.get("https://api.internal/data")
```

#### Production Standard (Correct)
> **Standard**: The root application lifespan explicitly orchestrates and nests the sub-application's lifespan context manager, ensuring isolated allocation, typed dependency injection, and deterministic closure of sub-application resources on shutdown.
```python
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from typing import TypedDict
from fastapi import FastAPI, Depends, Request
import httpx

class TenantState(TypedDict):
    http_client: httpx.AsyncClient

@asynccontextmanager
async def sub_app_lifespan(app: FastAPI) -> AsyncIterator[TenantState]:
    client = httpx.AsyncClient(timeout=10.0)
    try:
        yield {"http_client": client}
    finally:
        await client.aclose()

sub_app = FastAPI(lifespan=sub_app_lifespan)

@asynccontextmanager
async def root_lifespan(app: FastAPI) -> AsyncIterator[None]:
    # Explicitly manage and nest sub-application lifespans
    async with sub_app_lifespan(sub_app) as sub_state:
        sub_app.state.http_client = sub_state["http_client"]
        yield

root_app = FastAPI(lifespan=root_lifespan)
root_app.mount("/tenant-a", sub_app)

def get_tenant_client(request: Request) -> httpx.AsyncClient:
    return request.app.state.http_client

@sub_app.get("/data")
async def get_data(client: httpx.AsyncClient = Depends(get_tenant_client)):
    response = await client.get("https://api.internal/data")
    return response.json()
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: FastAPI 0.115+ Async Lifespan Sub-Application Scope Isolation Standard

FastAPI 0.115+ Async Lifespan Sub-Application Scope Isolation Standard defines an industrial-grade behavioral standard for backend engineering. Enforces strict ASGI lifespan context isolation between root FastAPI orchestrators and mounted sub-applications in FastAPI 0.115+. Prevents shared mutable state, connection handle leakage, and skipped sub-application lifespan teardown phases when mounting isolated services or multi-tenant sub-apps under a shared server process. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Mounting Sub-Applications with Root-Inherited State or Uninvoked Isolated Lifespans Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftMounting Sub-Applications with Root-Inherited State or Uninvoked Isolated LifespansCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS declare dedicated, asynccontextmanager-decorated lifespan generators for both root applications and mounted sub-applications, ensuring state is attached strictly to the respective local app.state.

Engineers MUST ALWAYS declare dedicated, asynccontextmanager-decorated lifespan generators for both root applications and mounted sub-applications, ensuring state is attached strictly to the respective local app.state.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST NOT rely on Starlette/FastAPI's default `mount()` behavior to automatically trigger mounted sub-application lifespan managers without an explicit composite lifespan orchestrator or lifespan-aware proxy wrapper.

Engineers MUST NOT rely on Starlette/FastAPI's default `mount()` behavior to automatically trigger mounted sub-application lifespan managers without an explicit composite lifespan orchestrator or lifespan-aware proxy wrapper.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Services MUST explicitly pass initialized tenant or domain resource managers into the sub-app's lifespan context or request dependencies rather than reading parent `app.state` globally.

Services MUST explicitly pass initialized tenant or domain resource managers into the sub-app's lifespan context or request dependencies rather than reading parent `app.state` globally.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Code MUST use FastAPI 0.115+ typed state access patterns and ensure all database pools, HTTP client sessions, and cache clients instantiated within a sub-app's lifespan are gracefully closed in `finally` blocks during shutdown.

Code MUST use FastAPI 0.115+ typed state access patterns and ensure all database pools, HTTP client sessions, and cache clients instantiated within a sub-app's lifespan are gracefully closed in `finally` blocks during shutdown.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Engineers MUST NEVER mutate the root application's `app.state` from within a mounted sub-application route or middleware.

Engineers MUST NEVER mutate the root application's `app.state` from within a mounted sub-application route or middleware.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is FastAPI 0.115+ Async Lifespan Sub-Application Scope Isolation Standard critical for AI coding assistants?

Enforces strict ASGI lifespan context isolation between root FastAPI orchestrators and mounted sub-applications in FastAPI 0.115+. Prevents shared mutable state, connection handle leakage, and skipped sub-application lifespan teardown phases when mounting isolated services or multi-tenant sub-apps under a shared server process. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Mounting Sub-Applications with Root-Inherited State or Uninvoked Isolated Lifespans) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

FastAPI