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

FastAPI Python 3.13 Free-Threaded (No-GIL) Thread-Safe State Isolation

Enforces strict thread-safe state isolation, read-only lifecycle state immutability, and explicit synchronization primitives for FastAPI services running on Python 3.13 free-threaded builds (PEP 703). Prevents silent data corruption, torn reads, and deadlocks caused by concurrent OS thread execution without the Global Interpreter Lock.

Prohibited Anti-Pattern: Unsynchronized Global Mutations and Dynamic app.state Modification in Free-Threaded Python 3.13

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI Python 3.13 Free-Threaded (No-GIL) Thread-Safe State Isolation - Enforces strict thread-safe state isolation, read-only lifecycle state immutability, and explicit synchronization primitives for FastAPI services running on Python 3.13 free-threaded builds (PEP 703). Prevents silent data corruption, torn reads, and deadlocks caused by concurrent OS thread execution without the Global Interpreter Lock.
globs: app/**/*.py, src/**/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-py313-nogil-threadsafe-state-isolation"
---

# FastAPI Python 3.13 Free-Threaded (No-GIL) Thread-Safe State Isolation

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unsynchronized Global Mutations and Dynamic app.state Modification in Free-Threaded Python 3.13

## System Constraints
You are a Principal Backend Architect enforcing strict thread safety and memory isolation standards for FastAPI services running on Python 3.13 free-threaded (No-GIL) runtimes. Under python3.13t, multi-threaded execution occurs in true parallel OS threads without GIL serialization. You must mandate immutable application state, explicit thread-level locks for shared resources, and request-scoped isolation.

## Strict Guidelines
- Engineers MUST treat `app.state` as strictly read-only after the lifespan startup phase has completed.
- Engineers MUST NOT mutate module-level dicts, lists, or class attributes across request handlers without explicit synchronization via `threading.Lock` or `threading.RLock`.
- Engineers MUST NOT rely on `asyncio.Lock` to synchronize state accessed across OS worker threads (e.g., FastAPI thread pools via `run_in_threadpool` or synchronous route definitions).
- Services MUST encapsulate dynamic shared resources (such as token buckets or in-memory caches) inside thread-safe concurrency containers with bounded locks or atomic exchange patterns.
- Engineers MUST use `contextvars.ContextVar` for request-scoped context tracking rather than global state or mutable middleware attributes.
- Data structures passed across execution boundaries SHOULD use immutable types (`typing.NamedTuple`, `@dataclass(frozen=True)`, or frozen Pydantic models).
- Middleware pipelines MUST NEVER attach mutable state instances to `request.scope` without ensuring deep copies or read-only access per worker thread.

## Bad vs Good Implementations
### Unsynchronized Shared State in Free-Threaded FastAPI

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: In Python 3.13 free-threaded mode (PEP 703), bytecode instructions are executed in parallel across OS threads without GIL serialization. Operations like `dict` updates and integer increments (`+= 1`) are not atomic, causing lost updates, corrupted memory structures, and race conditions when multiple worker threads execute concurrently.
```python
from fastapi import FastAPI, Request

app = FastAPI()

# Anti-Pattern: Shared mutable global state and dynamic app.state mutation.
# Under Python 3.13t (free-threaded), concurrent requests cause race conditions
# and torn reads during in-place dict and integer mutations.
GLOBAL_METRICS = {"request_count": 0}

@app.middleware("http")
async def tracking_middleware(request: Request, call_next):
    GLOBAL_METRICS["request_count"] += 1  # Race condition: non-atomic in No-GIL
    request.app.state.last_path = request.url.path  # Unsynchronized shared write
    return await call_next(request)

@app.get("/stats")
def get_stats(request: Request):
    # Synchronous def runs in anyio threadpool; reads state during concurrent writes
    return {
        "count": GLOBAL_METRICS["request_count"],
        "last_path": getattr(request.app.state, "last_path", None)
    }
```

#### Production Standard (Correct)
> **Standard**: Free-threaded execution invariants are upheld: `AppConfig` is frozen and read-only, lifecycle state is immutable post-startup, and mutable runtime statistics are guarded by explicit OS-level synchronization (`threading.Lock`), ensuring thread safety under Python 3.13t without relying on the GIL.
```python
from contextlib import asynccontextmanager
from dataclasses import dataclass
import threading
from typing import AsyncIterator, Mapping
from fastapi import FastAPI, Depends

@dataclass(frozen=True, slots=True)
class AppConfig:
    api_version: str
    environment: str

class ThreadSafeMetrics:
    def __init__(self) -> None:
        self._lock = threading.Lock()
        self._request_count: int = 0

    def increment(self) -> int:
        with self._lock:
            self._request_count += 1
            return self._request_count

    def get_count(self) -> int:
        with self._lock:
            return self._request_count

@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncIterator[Mapping[str, object]]:
    # State initialized once in lifespan startup before incoming traffic
    metrics = ThreadSafeMetrics()
    config = AppConfig(api_version="v1.0.0", environment="production")
    yield {"metrics": metrics, "config": config}

app = FastAPI(lifespan=lifespan)

def get_metrics() -> ThreadSafeMetrics:
    return app.state.metrics

@app.get("/stats")
def get_stats(metrics: ThreadSafeMetrics = Depends(get_metrics)):
    # Safe concurrent execution across free-threaded worker pools
    current_count = metrics.increment()
    return {"count": current_count, "version": app.state.config.api_version}
```

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 Python 3.13 Free-Threaded (No-GIL) Thread-Safe State Isolation

FastAPI Python 3.13 Free-Threaded (No-GIL) Thread-Safe State Isolation defines an industrial-grade behavioral standard for backend engineering. Enforces strict thread-safe state isolation, read-only lifecycle state immutability, and explicit synchronization primitives for FastAPI services running on Python 3.13 free-threaded builds (PEP 703). Prevents silent data corruption, torn reads, and deadlocks caused by concurrent OS thread execution without the Global Interpreter Lock. 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: Unsynchronized Global Mutations and Dynamic app.state Modification 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 DriftUnsynchronized Global Mutations and Dynamic app.state Modification 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 treat `app.state` as strictly read-only after the lifespan startup phase has completed.

Engineers MUST treat `app.state` as strictly read-only after the lifespan startup phase has completed.

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 dicts, lists, or class attributes across request handlers without explicit synchronization via `threading.Lock` or `threading.RLock`.

Engineers MUST NOT mutate module-level dicts, lists, or class attributes across request handlers without explicit synchronization via `threading.Lock` or `threading.RLock`.

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 NOT rely on `asyncio.Lock` to synchronize state accessed across OS worker threads (e.g., FastAPI thread pools via `run_in_threadpool` or synchronous route definitions).

Engineers MUST NOT rely on `asyncio.Lock` to synchronize state accessed across OS worker threads (e.g., FastAPI thread pools via `run_in_threadpool` or synchronous route definitions).

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 encapsulate dynamic shared resources (such as token buckets or in-memory caches) inside thread-safe concurrency containers with bounded locks or atomic exchange patterns.

Services MUST encapsulate dynamic shared resources (such as token buckets or in-memory caches) inside thread-safe concurrency containers with bounded locks or atomic exchange patterns.

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 use `contextvars.ContextVar` for request-scoped context tracking rather than global state or mutable middleware attributes.

Engineers MUST use `contextvars.ContextVar` for request-scoped context tracking rather than global state or mutable middleware attributes.

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

Data structures passed across execution boundaries SHOULD use immutable types (`typing.NamedTuple`, `@dataclass(frozen=True)`, or frozen Pydantic models).

Data structures passed across execution boundaries SHOULD use immutable types (`typing.NamedTuple`, `@dataclass(frozen=True)`, or frozen Pydantic models).

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

Middleware pipelines MUST NEVER attach mutable state instances to `request.scope` without ensuring deep copies or read-only access per worker thread.

Middleware pipelines MUST NEVER attach mutable state instances to `request.scope` without ensuring deep copies or read-only access per worker thread.

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 Python 3.13 Free-Threaded (No-GIL) Thread-Safe State Isolation critical for AI coding assistants?

Enforces strict thread-safe state isolation, read-only lifecycle state immutability, and explicit synchronization primitives for FastAPI services running on Python 3.13 free-threaded builds (PEP 703). Prevents silent data corruption, torn reads, and deadlocks caused by concurrent OS thread execution without the Global Interpreter Lock. 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 (Unsynchronized Global Mutations and Dynamic app.state Modification 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