This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: fastapi-python-313-nogil-concurrency-safety-standard

FastAPI Python 3.13 Free-Threaded Concurrency Safety Standard

Enforces thread-safe state handling and context isolation in FastAPI applications operating on Python 3.13 free-threaded (no-GIL) runtimes. Prevents race conditions, cross-request memory bleeding, and corrupted mutable singletons caused by true concurrent native thread execution across event loops and worker pools. Mandates explicit synchronization, immutable data transfer, and proper usage of contextvars over raw module-level or thread-local storage.

Prohibited Anti-Pattern: Unsynchronized Mutable Module Singletons and Unsafe Thread-Local State Bleed on No-GIL Runtimes

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI Python 3.13 Free-Threaded Concurrency Safety Standard - Enforces thread-safe state handling and context isolation in FastAPI applications operating on Python 3.13 free-threaded (no-GIL) runtimes. Prevents race conditions, cross-request memory bleeding, and corrupted mutable singletons caused by true concurrent native thread execution across event loops and worker pools. Mandates explicit synchronization, immutable data transfer, and proper usage of contextvars over raw module-level or thread-local storage.
globs: **/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-python-313-nogil-concurrency-safety-standard"
---

# FastAPI Python 3.13 Free-Threaded Concurrency Safety Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Unsynchronized Mutable Module Singletons and Unsafe Thread-Local State Bleed on No-GIL Runtimes

## System Constraints
You are a Principal Software Architect enforcing the FastAPI Python 3.13 Free-Threaded (No-GIL) Concurrency Safety Standard. Under Python 3.13 free-threading (PEP 703), native threads execute concurrently across CPU cores without the global interpreter lock. Operations previously assumed atomic due to GIL preemption boundaries (e.g., dict modifications, in-place list mutations, shared cache access) are now subject to true hardware-level race conditions. You must mandate strict thread-safe state management, reject mutable module-level state, enforce contextvars for request-scoped context, and demand thread-safe synchronization primitives.

## Strict Guidelines
- Engineers MUST ALWAYS isolate request-scoped state using `contextvars.ContextVar` rather than `threading.local()` or module-level shared dictionaries.
- Engineers MUST NOT rely on CPython's legacy GIL behavior for atomic dictionary updates, set operations, or list mutations in shared singletons.
- Shared mutable in-memory caches or state registries MUST synchronize concurrent mutations using reentrant locks (`threading.RLock`) or lock-free immutable data structures (e.g., swapping frozen dataclass snapshots with atomics).
- FastAPI dependencies with `yield` semantics holding shared resources MUST ensure cleanup runs inside strict try-finally blocks wrapped with proper synchronization barriers.
- Engineers MUST NOT share non-thread-safe third-party client instances (such as non-pooling HTTP sessions or raw database drivers) across concurrent threads; dependency injection MUST instantiate scoped clients or use thread-safe connection pools.
- CPU-bound tasks offloaded via `starlette.concurrency.run_in_threadpool` or `asyncio.to_thread` MUST operate strictly on decoupled, immutable arguments to prevent concurrent mutation of caller frames.

## Bad vs Good Implementations
### Module-Level In-Memory Counter and Request Context

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Under Python 3.13 free-threading, dictionary lookups and in-place updates across concurrent OS threads lead to data corruption and lost updates without the GIL. Furthermore, `threading.local` does not reliably track async execution contexts across task hops and worker pool execution.
```python
from fastapi import FastAPI, Request
import threading

app = FastAPI()

# Anti-pattern: Unsynchronized mutable module state and raw thread-local storage
# In Python 3.13t (no-GIL), concurrent requests corrupt dict internals and bleed thread state
METRICS_STORE: dict[str, int] = {}
_local_ctx = threading.local()

@app.middleware("http")
async def attach_trace_id(request: Request, call_next):
    _local_ctx.trace_id = request.headers.get("X-Trace-ID", "unknown")
    # Non-atomic increment without GIL protection creates lost updates across native cores
    METRICS_STORE["total_requests"] = METRICS_STORE.get("total_requests", 0) + 1
    return await call_next(request)

@app.get("/data")
def get_data():
    # threading.local can bleed or mismatch under asyncio worker threads
    return {"trace_id": getattr(_local_ctx, "trace_id", None), "requests": METRICS_STORE.get("total_requests", 0)}
```

#### Production Standard (Correct)
> **Standard**: Uses `contextvars.ContextVar` for isolated, async-aware request context that safely handles task hops, and guards the shared mutable metric counter with an explicit `threading.Lock` to guarantee atomic operations across native threads on Python 3.13 free-threaded runtimes.
```python
from fastapi import FastAPI, Request
from contextvars import ContextVar
from dataclasses import dataclass
import threading

app = FastAPI()

request_trace_id: ContextVar[str] = ContextVar("request_trace_id", default="unknown")

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

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

    def get_total(self) -> int:
        with self._lock:
            return self._total_requests

metrics = ThreadSafeMetrics()

@app.middleware("http")
async def attach_trace_id(request: Request, call_next):
    token = request_trace_id.set(request.headers.get("X-Trace-ID", "unknown"))
    metrics.increment()
    try:
        return await call_next(request)
    finally:
        request_trace_id.reset(token)

@app.get("/data")
def get_data():
    return {"trace_id": request_trace_id.get(), "requests": metrics.get_total()}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: FastAPI Python 3.13 Free-Threaded Concurrency Safety Standard

FastAPI Python 3.13 Free-Threaded Concurrency Safety Standard defines an industrial-grade behavioral standard for backend engineering. Enforces thread-safe state handling and context isolation in FastAPI applications operating on Python 3.13 free-threaded (no-GIL) runtimes. Prevents race conditions, cross-request memory bleeding, and corrupted mutable singletons caused by true concurrent native thread execution across event loops and worker pools. Mandates explicit synchronization, immutable data transfer, and proper usage of contextvars over raw module-level or thread-local storage. 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 Mutable Module Singletons and Unsafe Thread-Local State Bleed on No-GIL Runtimes 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 Mutable Module Singletons and Unsafe Thread-Local State Bleed on No-GIL RuntimesCritical
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 request-scoped state using `contextvars.ContextVar` rather than `threading.local()` or module-level shared dictionaries.

Engineers MUST ALWAYS isolate request-scoped state using `contextvars.ContextVar` rather than `threading.local()` or module-level shared dictionaries.

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 CPython's legacy GIL behavior for atomic dictionary updates, set operations, or list mutations in shared singletons.

Engineers MUST NOT rely on CPython's legacy GIL behavior for atomic dictionary updates, set operations, or list mutations in shared singletons.

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

Shared mutable in-memory caches or state registries MUST synchronize concurrent mutations using reentrant locks (`threading.RLock`) or lock-free immutable data structures (e.g., swapping frozen dataclass snapshots with atomics).

Shared mutable in-memory caches or state registries MUST synchronize concurrent mutations using reentrant locks (`threading.RLock`) or lock-free immutable data structures (e.g., swapping frozen dataclass snapshots with atomics).

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

FastAPI dependencies with `yield` semantics holding shared resources MUST ensure cleanup runs inside strict try-finally blocks wrapped with proper synchronization barriers.

FastAPI dependencies with `yield` semantics holding shared resources MUST ensure cleanup runs inside strict try-finally blocks wrapped with proper synchronization barriers.

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 NOT share non-thread-safe third-party client instances (such as non-pooling HTTP sessions or raw database drivers) across concurrent threads

Engineers MUST NOT share non-thread-safe third-party client instances (such as non-pooling HTTP sessions or raw database drivers) across concurrent threads; dependency injection MUST instantiate scoped clients or use thread-safe connection pools.

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

CPU-bound tasks offloaded via `starlette.concurrency.run_in_threadpool` or `asyncio.to_thread` MUST operate strictly on decoupled, immutable arguments to prevent concurrent mutation of caller frames.

CPU-bound tasks offloaded via `starlette.concurrency.run_in_threadpool` or `asyncio.to_thread` MUST operate strictly on decoupled, immutable arguments to prevent concurrent mutation of caller frames.

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 Concurrency Safety Standard critical for AI coding assistants?

Enforces thread-safe state handling and context isolation in FastAPI applications operating on Python 3.13 free-threaded (no-GIL) runtimes. Prevents race conditions, cross-request memory bleeding, and corrupted mutable singletons caused by true concurrent native thread execution across event loops and worker pools. Mandates explicit synchronization, immutable data transfer, and proper usage of contextvars over raw module-level or thread-local storage. 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 Mutable Module Singletons and Unsafe Thread-Local State Bleed on No-GIL Runtimes) 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