This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: fastapi-python313-free-threaded-state-isolation

FastAPI 0.115+ Free-Threaded (Python 3.13t) State Isolation & Thread-Safety Standard

Guarantees strict request context encapsulation, thread isolation, and memory-safe shared state under Python 3.13 free-threaded (GIL-disabled, PEP 703) runtimes. Prevents severe race conditions, cross-request state leakage, and memory corruption caused by legacy assumptions of GIL-backed atomicity.

Prohibited Anti-Pattern: Relying on Implicit GIL Atomicity and Mutable Global Singletons in Free-Threaded Async Execution

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI 0.115+ Free-Threaded (Python 3.13t) State Isolation & Thread-Safety Standard - Guarantees strict request context encapsulation, thread isolation, and memory-safe shared state under Python 3.13 free-threaded (GIL-disabled, PEP 703) runtimes. Prevents severe race conditions, cross-request state leakage, and memory corruption caused by legacy assumptions of GIL-backed atomicity.
globs: app/**/*.py, src/**/*.py, api/**/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-python313-free-threaded-state-isolation"
---

# FastAPI 0.115+ Free-Threaded (Python 3.13t) State Isolation & Thread-Safety Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Relying on Implicit GIL Atomicity and Mutable Global Singletons in Free-Threaded Async Execution

## System Constraints
You are a Principal Software Architect enforcing FastAPI 0.115+ and Python 3.13 free-threaded runtime standards. When running under Python 3.13t without the Global Interpreter Lock (GIL), all implicit thread safety assumptions (such as atomic dictionary updates, GIL-shielded list mutations, or module-level caching) fail. You must mandate strict context-variable encapsulation via `contextvars`, explicit synchronization primitives (`threading.Lock`/`threading.RWLock`) on shared state, pure asynchronous boundary protection, and lifecycle-scoped dependency injection.

## Strict Guidelines
- Engineers MUST ALWAYS isolate per-request context using `contextvars.ContextVar` instead of module-level variables or legacy `threading.local`.
- Engineers MUST NOT rely on implicit Python GIL atomicity for standard collection mutations (e.g., `dict[k] = v`, `list.append()`, `set.add()`) across concurrent threads or threadpool workers.
- Engineers MUST ALWAYS guard shared cross-request mutable state with explicit thread-safe synchronization primitives (`threading.Lock`, `threading.RLock`) or use atomic concurrent data structures.
- Services MUST allocate application-wide resources (connection pools, HTTP clients) within the FastAPI `lifespan` context manager and attach them to `app.state`, never initializing mutable state at import time.
- Components NEVER store request-scoped data or user credentials in global singletons, class-level attributes, or unbounded in-memory caches.
- Code executing synchronous blocking I/O or CPU-bound tasks via `anyio.to_thread.run_sync` or FastAPI `run_in_threadpool` MUST ensure all passed arguments and accessed objects are strictly thread-safe and isolated.

## Bad vs Good Implementations
### Request Context and Cache Isolation in Python 3.13 Free-Threaded Mode

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using un-synchronized module-level mutable dicts in Python 3.13t causes data races and memory hazards. Without the GIL, concurrent bytecodes execute truly in parallel across OS threads, corrupting dict internals and cross-contaminating tenant context.
```python
from fastapi import FastAPI, Request

app = FastAPI()

# ANTI-PATTERN: Module-level mutable state assuming GIL protects atomic writes.
# In Python 3.13t (free-threaded), concurrent threads cause race conditions,
# torn reads/writes, and cross-tenant data leakage.
REQUEST_METRICS: dict[str, int] = {}
CURRENT_USER: dict[str, str] = {}

@app.middleware("http")
async def track_request_state(request: Request, call_next):
    tenant_id = request.headers.get("X-Tenant-ID", "unknown")
    # Race condition: mutating global dictionary without synchronization across threads
    REQUEST_METRICS[tenant_id] = REQUEST_METRICS.get(tenant_id, 0) + 1
    CURRENT_USER["active_tenant"] = tenant_id
    
    response = await call_next(request)
    return response

@app.get("/tenant-info")
async def get_tenant_info():
    # Leaks state across parallel requests on free-threaded multi-core runtime
    return {"current_tenant": CURRENT_USER.get("active_tenant")}
```

#### Production Standard (Correct)
> **Standard**: Utilizes `ContextVar` to provide strict thread and async-task isolation without cross-thread pollution. Protects shared aggregated metrics using an explicit `threading.Lock` and attaches dependencies to `app.state` via the lifespan protocol, ensuring deterministic execution in Python 3.13 free-threaded runtimes.
```python
from contextlib import asynccontextmanager
from contextvars import ContextVar
from dataclasses import dataclass, field
import threading
from typing import AsyncGenerator
from fastapi import FastAPI, Depends, Request

# Enforce thread-local context isolation via contextvars
request_tenant_context: ContextVar[str] = ContextVar("request_tenant_context", default="unknown")

@dataclass
class ThreadSafeMetrics:
    _lock: threading.Lock = field(default_factory=threading.Lock)
    _counts: dict[str, int] = field(default_factory=dict)

    def increment(self, key: str) -> None:
        with self._lock:
            self._counts[key] = self._counts.get(key, 0) + 1

    def get_snapshot(self) -> dict[str, int]:
        with self._lock:
            return self._counts.copy()

@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    # Lifecycle-scoped state isolation
    app.state.metrics = ThreadSafeMetrics()
    yield

app = FastAPI(lifespan=lifespan)

@app.middleware("http")
async def track_request_state(request: Request, call_next):
    tenant_id = request.headers.get("X-Tenant-ID", "unknown")
    token = request_tenant_context.set(tenant_id)
    request.app.state.metrics.increment(tenant_id)
    try:
        return await call_next(request)
    finally:
        request_tenant_context.reset(token)

def get_current_tenant() -> str:
    return request_tenant_context.get()

@app.get("/tenant-info")
async def get_tenant_info(current_tenant: str = Depends(get_current_tenant)):
    return {"current_tenant": current_tenant}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: FastAPI 0.115+ Free-Threaded (Python 3.13t) State Isolation & Thread-Safety Standard

FastAPI 0.115+ Free-Threaded (Python 3.13t) State Isolation & Thread-Safety Standard defines an industrial-grade behavioral standard for backend engineering. Guarantees strict request context encapsulation, thread isolation, and memory-safe shared state under Python 3.13 free-threaded (GIL-disabled, PEP 703) runtimes. Prevents severe race conditions, cross-request state leakage, and memory corruption caused by legacy assumptions of GIL-backed atomicity. 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: Relying on Implicit GIL Atomicity and Mutable Global Singletons in Free-Threaded Async Execution 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 DriftRelying on Implicit GIL Atomicity and Mutable Global Singletons in Free-Threaded Async ExecutionCritical
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 isolate per-request context using `contextvars.ContextVar` instead of module-level variables or legacy `threading.local`.

Engineers MUST ALWAYS isolate per-request context using `contextvars.ContextVar` instead of module-level variables or legacy `threading.local`.

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 implicit Python GIL atomicity for standard collection mutations (e.g., `dict[k] = v`, `list.append()`, `set.add()`) across concurrent threads or threadpool workers.

Engineers MUST NOT rely on implicit Python GIL atomicity for standard collection mutations (e.g., `dict[k] = v`, `list.append()`, `set.add()`) across concurrent threads or threadpool workers.

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

Engineers MUST ALWAYS guard shared cross-request mutable state with explicit thread-safe synchronization primitives (`threading.Lock`, `threading.RLock`) or use atomic concurrent data structures.

Engineers MUST ALWAYS guard shared cross-request mutable state with explicit thread-safe synchronization primitives (`threading.Lock`, `threading.RLock`) or use atomic concurrent data structures.

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

Services MUST allocate application-wide resources (connection pools, HTTP clients) within the FastAPI `lifespan` context manager and attach them to `app.state`, never initializing mutable state at import time.

Services MUST allocate application-wide resources (connection pools, HTTP clients) within the FastAPI `lifespan` context manager and attach them to `app.state`, never initializing mutable state at import time.

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

Components NEVER store request-scoped data or user credentials in global singletons, class-level attributes, or unbounded in-memory caches.

Components NEVER store request-scoped data or user credentials in global singletons, class-level attributes, or unbounded in-memory caches.

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.
6

Code executing synchronous blocking I/O or CPU-bound tasks via `anyio.to_thread.run_sync` or FastAPI `run_in_threadpool` MUST ensure all passed arguments and accessed objects are strictly thread-safe and isolated.

Code executing synchronous blocking I/O or CPU-bound tasks via `anyio.to_thread.run_sync` or FastAPI `run_in_threadpool` MUST ensure all passed arguments and accessed objects are strictly thread-safe and isolated.

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+ Free-Threaded (Python 3.13t) State Isolation & Thread-Safety Standard critical for AI coding assistants?

Guarantees strict request context encapsulation, thread isolation, and memory-safe shared state under Python 3.13 free-threaded (GIL-disabled, PEP 703) runtimes. Prevents severe race conditions, cross-request state leakage, and memory corruption caused by legacy assumptions of GIL-backed atomicity. 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 (Relying on Implicit GIL Atomicity and Mutable Global Singletons in Free-Threaded Async Execution) 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