Skip to main content
Articles/async-context-manager/async-dependency-lifecycles-in-fastapi-when-generators-go-wrong
Scenario Article

**Async Dependency Lifecycles in FastAPI: When Generators Go Wrong**

Gotcha: Unclosed Async Generators

Abstract Algorithms•Sep 15, 2026
💡 Executive Summary

⚠️ Async generator deps can leak resources if not closed; use asynccontextmanager + Depends for clean, per‑request lifecycles.

🎯 System Scenario & Requirements

System Goal

⚠️ Async generator deps can leak resources if not closed; use asynccontextmanager + Depends for clean, per‑request lifecycles.

Actors & Components

  • Application or API tier
  • Core service under design
  • Operator or SRE observer

Functional Requirements

  • TLDR: ⚠️ Async generator deps can leak resources if not closed; use asynccontextmanager + Depends for clean, per‑request lifecycles.
  • In a FastAPI app, it’s tempting to write a dependency that yields a DB session via an async generator: If the dependency is used in many routes, the Session objects pile up because FastAPI only closes the generator when…
  • Forgetting that block means connections stay open, eventually exhausting the pool.

Constraints & Assumptions

  • Constraints are derived from the rebuilt scenario stages.

⚡ Execution Stages & Decision Trace

1

Stage 1 — The Solution: `asynccontextmanager` + `Depends`

Action / Decision:

Wrap the generator in asynccontextmanager from contextlib .

Component Behavior:

FastAPI automatically calls the cleanup when the request finishes: FastAPI injects the yielded session and ensures the finally block runs even if the endpoint raises.

Observable Output: This pattern scales: each request gets its own session, and resources are freed promptly.
Read Full Stage in Deep Dive ↓
📖

Deep Dive

Detailed Architectural Analysis

Scenario context


⚠️ Async generator deps can leak resources if not closed; use asynccontextmanager + Depends for clean, per‑request lifecycles.

In a FastAPI app, it’s tempting to write a dependency that yields a DB session via an async generator:

If the dependency is used in many routes, the Session objects pile up because FastAPI only closes the generator when the request ends and the generator’s finally blo…

This walkthrough focuses on Gotcha: Unclosed Async Generators.

Before making a design choice, clarify:

  • In a FastAPI app, it’s tempting to write a dependency that yields a DB session via an async generator: If the dependency is used in many routes, the Session objects pile up because FastAPI only closes the generator when…
  • Forgetting that block means connections stay open, eventually exhausting the pool.

Concepts in play: python-concurrency-nogil, caching

Stage 1 — The Solution: asynccontextmanager + Depends

  • Wrap the generator in asynccontextmanager from contextlib .
  • FastAPI automatically calls the cleanup when the request finishes: FastAPI injects the yielded session and ensures the finally block runs even if the endpoint raises.
  • This pattern scales: each request gets its own session, and resources are freed promptly.
from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI

app = FastAPI()

@asynccontextmanager
async def get_session():
    session = Session()
    try:
        yield session
    finally:
        await session.close()   # guaranteed cleanup

@app.get("/items")
async def read_items(session: Session = Depends(get_session)):
    return await session.execute("SELECT * FROM items")

Observable outcome: This pattern scales: each request gets its own session, and resources are freed promptly.

Stage 2 — Trade‑offs & Best Practices

  • Quick checklist - Use asynccontextmanager for any async resource (DB, HTTP client, file).
    • Explicitly await cleanup in the finally block.
    • Avoid caching async generators unless you manage lifecycle yourself.
    • Monitor connection pool metrics; a sudden spike indicates a leak.

Observable outcome: - Monitor connection pool metrics; a sudden spike indicates a leak.

End-to-end outcome

In a FastAPI app, it’s tempting to write a dependency that yields a DB session via an async generator: If the dependency is used in many routes, the Session objects pile up because FastAPI only closes the generator when the request ends and the generator’s finally block runs.

Alternatives considered

The source focuses on one primary design. A second architecture is not compared, so no alternative is invented here.

Failure and degraded modes

The source does not isolate a separate failure mode. Limits that matter for the scenario are called out in the stage decisions above.

✅

Key learnings

  • Wrap the generator in asynccontextmanager from contextlib .
  • Quick checklist - Use asynccontextmanager for any async resource (DB, HTTP client, file).

Share this case study

Discuss architecture trade-offs and lessons with your team.

Share:XLinkedInReddit