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

FastAPI on Python 3.13 Free-Threaded (PEP 703) Memory and State Guardrails

Enforces immutable request-scoped state buffers and strict isolation protocols for FastAPI running on free-threaded Python 3.13 (nogil). In the absence of the Global Interpreter Lock, multi-threaded ASGI servers (e.g., Uvicorn/Granian with native threads) will encounter native memory corruption, data races, and torn reads if mutable state leaks across task boundaries or shared memory buffers. All request-scoped data structures must use immutability primitives, contextvars with deep-copy boundaries, or explicit synchronization locks.

Prohibited Anti-Pattern: Cross-Thread Data Races and Memory Corruption via Mutable State Leakage in Free-Threaded Python 3.13

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI on Python 3.13 Free-Threaded (PEP 703) Memory and State Guardrails - Enforces immutable request-scoped state buffers and strict isolation protocols for FastAPI running on free-threaded Python 3.13 (nogil). In the absence of the Global Interpreter Lock, multi-threaded ASGI servers (e.g., Uvicorn/Granian with native threads) will encounter native memory corruption, data races, and torn reads if mutable state leaks across task boundaries or shared memory buffers. All request-scoped data structures must use immutability primitives, contextvars with deep-copy boundaries, or explicit synchronization locks.
globs: **/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-python313-free-threaded-memory-invariants"
---

# FastAPI on Python 3.13 Free-Threaded (PEP 703) Memory and State Guardrails

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Cross-Thread Data Races and Memory Corruption via Mutable State Leakage in Free-Threaded Python 3.13

## System Constraints
You are a Principal Software Architect enforcing concurrent memory safety for FastAPI applications deployed on free-threaded Python 3.13 (PEP 703, nogil). Because the CPython runtime lacks a Global Interpreter Lock, multi-threaded ASGI task execution exposes standard mutable collections (dicts, lists, sets) and module-level singletons to race conditions and native heap corruptions. You must strictly mandate contextvars with frozen dataclasses, thread-safe memory management, elimination of mutable global caches, and zero-copy byte buffers protected by explicit mutual exclusion.

## Strict Guidelines
- Engineers MUST ALWAYS encapsulate request-scoped state using `contextvars.ContextVar` containing frozen dataclasses (`@dataclass(frozen=True)`) or immutable mapping types to prevent cross-thread torn reads.
- Engineers MUST NOT mutate module-level dictionaries, sets, lists, or custom class attributes inside FastAPI path operations, dependency injection providers, or middleware without explicit mutual exclusion using `threading.Lock` or `threading.RWLock`.
- Code SHOULD utilize thread-safe caching primitives such as locked LRU implementations or external storage (e.g., Redis) rather than raw Python dictionaries or unguarded global collections.
- Services MUST ensure that C-extensions or native memory pointers (e.g., NumPy buffers, Cython memoryviews, PyArrow tables) are marked read-only before being shared across concurrent tasks in a free-threaded runtime.
- Components NEVER store or mutate persistent client-specific context inside ASGI middleware scope (`scope['state']`) using mutable dict references across asynchronous yields without a thread-isolated shallow-to-deep barrier.

## Bad vs Good Implementations
### Request-Scoped Context State: Mutable Global Leaks vs. Frozen ContextVar Invariants

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Under Python 3.13 free-threading, standard dicts are not safe for unsynchronized concurrent writes across OS threads. Concurrent writes and deletes to GLOBAL_REQUEST_CACHE cause native memory corruption, segfaults, and silent state contamination between unrelated HTTP requests.
```python
from fastapi import FastAPI, Request

app = FastAPI()

# Anti-pattern: Global mutable state in free-threaded Python 3.13 (PEP 703)
# Causes torn reads, corrupt dict pointers, and data races across native threads
GLOBAL_REQUEST_CACHE: dict[str, dict] = {}

@app.middleware("http")
async def attach_request_context(request: Request, call_next):
    trace_id = request.headers.get("X-Trace-Id", "default")
    GLOBAL_REQUEST_CACHE[trace_id] = {"user": None, "roles": []}
    try:
        response = await call_next(request)
        return response
    finally:
        GLOBAL_REQUEST_CACHE.pop(trace_id, None)

@app.get("/api/v1/profile")
async def get_profile(request: Request):
    trace_id = request.headers.get("X-Trace-Id", "default")
    context = GLOBAL_REQUEST_CACHE.get(trace_id, {})
    # Unsynchronized mutation across native ASGI worker threads
    context["user"] = "user_123"
    return context
```

#### Production Standard (Correct)
> **Standard**: PEP 567 ContextVar combined with frozen dataclasses guarantees zero shared mutable state across free-threaded OS workers. Each request branch accesses an isolated context reference, ensuring strict thread safety without requiring global locks.
```python
from contextvars import ContextVar
from dataclasses import dataclass
from typing import Optional
from fastapi import FastAPI, Request, Response

@dataclass(frozen=True, slots=True)
class RequestContext:
    trace_id: str
    user_id: Optional[str] = None
    roles: tuple[str, ...] = ()

# Thread-safe request isolation using PEP 567 contextvars
REQUEST_CTX: ContextVar[RequestContext] = ContextVar("request_ctx")

app = FastAPI()

@app.middleware("http")
async def attach_request_context(request: Request, call_next) -> Response:
    trace_id = request.headers.get("X-Trace-Id", "default")
    token = REQUEST_CTX.set(RequestContext(trace_id=trace_id))
    try:
        return await call_next(request)
    finally:
        REQUEST_CTX.reset(token)

@app.get("/api/v1/profile")
async def get_profile() -> dict[str, str | None]:
    ctx = REQUEST_CTX.get()
    # Immutability guarantees safety in free-threaded runtimes
    new_ctx = RequestContext(
        trace_id=ctx.trace_id,
        user_id="user_123",
        roles=ctx.roles
    )
    REQUEST_CTX.set(new_ctx)
    return {"trace_id": new_ctx.trace_id, "user_id": new_ctx.user_id}
```

### Shared Resource Metrics: Unsynchronized Counters vs. Atomic Thread Locks

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Without the GIL, in-place addition (`request_counter += 1`) compiles to multiple bytecode instructions that execute simultaneously across CPU cores, leading to lost updates and race conditions on raw Python integer references.
```python
from fastapi import FastAPI

app = FastAPI()

# Anti-pattern: Non-atomic integer increments in nogil Python 3.13
request_counter: int = 0

@app.get("/api/v1/ping")
async def ping():
    global request_counter
    # In free-threaded Python, += is bytecode non-atomic (LOAD, ADD, STORE)
    # and causes lost updates under multi-core concurrency
    request_counter += 1
    return {"status": "ok", "total": request_counter}
```

#### Production Standard (Correct)
> **Standard**: Encapsulating shared state within a class that uses `threading.Lock` establishes a memory barrier across threads, guaranteeing atomic updates and visibility across physical cores in Python 3.13 free-threaded builds.
```python
import threading
from fastapi import FastAPI

app = FastAPI()

class AtomicCounter:
    __slots__ = ("_value", "_lock")
    
    def __init__(self) -> None:
        self._value: int = 0
        self._lock = threading.Lock()
        
    def increment(self) -> int:
        with self._lock:
            self._value += 1
            return self._value

counter = AtomicCounter()

@app.get("/api/v1/ping")
async def ping():
    current_count = counter.increment()
    return {"status": "ok", "total": current_count}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: FastAPI on Python 3.13 Free-Threaded (PEP 703) Memory and State Guardrails

FastAPI on Python 3.13 Free-Threaded (PEP 703) Memory and State Guardrails defines an industrial-grade behavioral standard for backend engineering. Enforces immutable request-scoped state buffers and strict isolation protocols for FastAPI running on free-threaded Python 3.13 (nogil). In the absence of the Global Interpreter Lock, multi-threaded ASGI servers (e.g., Uvicorn/Granian with native threads) will encounter native memory corruption, data races, and torn reads if mutable state leaks across task boundaries or shared memory buffers. All request-scoped data structures must use immutability primitives, contextvars with deep-copy boundaries, or explicit synchronization locks. 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: Cross-Thread Data Races and Memory Corruption via Mutable State Leakage in Free-Threaded Python 3.13 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 DriftCross-Thread Data Races and Memory Corruption via Mutable State Leakage in Free-Threaded Python 3.13Critical
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 encapsulate request-scoped state using `contextvars.ContextVar` containing frozen dataclasses (`@dataclass(frozen=True)`) or immutable mapping types to prevent cross-thread torn reads.

Engineers MUST ALWAYS encapsulate request-scoped state using `contextvars.ContextVar` containing frozen dataclasses (`@dataclass(frozen=True)`) or immutable mapping types to prevent cross-thread torn reads.

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 mutate module-level dictionaries, sets, lists, or custom class attributes inside FastAPI path operations, dependency injection providers, or middleware without explicit mutual exclusion using `threading.Lock` or `threading.RWLock`.

Engineers MUST NOT mutate module-level dictionaries, sets, lists, or custom class attributes inside FastAPI path operations, dependency injection providers, or middleware without explicit mutual exclusion using `threading.Lock` or `threading.RWLock`.

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

Code SHOULD utilize thread-safe caching primitives such as locked LRU implementations or external storage (e.g., Redis) rather than raw Python dictionaries or unguarded global collections.

Code SHOULD utilize thread-safe caching primitives such as locked LRU implementations or external storage (e.g., Redis) rather than raw Python dictionaries or unguarded global collections.

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 ensure that C-extensions or native memory pointers (e.g., NumPy buffers, Cython memoryviews, PyArrow tables) are marked read-only before being shared across concurrent tasks in a free-threaded runtime.

Services MUST ensure that C-extensions or native memory pointers (e.g., NumPy buffers, Cython memoryviews, PyArrow tables) are marked read-only before being shared across concurrent tasks in a free-threaded runtime.

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 or mutate persistent client-specific context inside ASGI middleware scope (`scope['state']`) using mutable dict references across asynchronous yields without a thread-isolated shallow-to-deep barrier.

Components NEVER store or mutate persistent client-specific context inside ASGI middleware scope (`scope['state']`) using mutable dict references across asynchronous yields without a thread-isolated shallow-to-deep barrier.

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 on Python 3.13 Free-Threaded (PEP 703) Memory and State Guardrails critical for AI coding assistants?

Enforces immutable request-scoped state buffers and strict isolation protocols for FastAPI running on free-threaded Python 3.13 (nogil). In the absence of the Global Interpreter Lock, multi-threaded ASGI servers (e.g., Uvicorn/Granian with native threads) will encounter native memory corruption, data races, and torn reads if mutable state leaks across task boundaries or shared memory buffers. All request-scoped data structures must use immutability primitives, contextvars with deep-copy boundaries, or explicit synchronization locks. 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 (Cross-Thread Data Races and Memory Corruption via Mutable State Leakage in Free-Threaded Python 3.13) 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