{
  "id": "python-fastapi",
  "name": "FastAPI service APIs",
  "use_cases": [
    "Typed JSON APIs",
    "Integration services",
    "HTTP endpoints for model or worker products"
  ],
  "choose_when": [
    "API contracts and Python integrations matter more than built-in product/admin UI",
    "A separate frontend or service boundary already exists"
  ],
  "avoid_when": [
    "The team mostly needs accounts, admin, forms and CRUD that Django supplies",
    "Blocking or CPU-intensive jobs would be run inside request event loops"
  ],
  "tools": [
    {
      "job": "Packaging and environments",
      "default": "uv + pyproject.toml + committed uv.lock",
      "alternatives": [
        "Preserve an existing maintained packaging workflow"
      ],
      "reason": "One project entry point for dependencies, Python selection, execution and reproducible sync.",
      "limits": "Pin a compatible Python minor and resolve actual package versions at implementation; do not hand-edit uv.lock. Keep environments and caches in a local development workspace.",
      "source_urls": [
        "https://docs.astral.sh/uv/guides/projects/"
      ]
    },
    {
      "job": "Lint and format",
      "default": "Ruff",
      "alternatives": [
        "Preserve existing configured formatter/linter"
      ],
      "reason": "Fast lint and formatting feedback with one configuration.",
      "limits": "Ruff does not replace static typing, tests, authorization checks or runtime validation.",
      "source_urls": [
        "https://docs.astral.sh/ruff/installation/"
      ]
    },
    {
      "job": "Static typing",
      "default": "mypy",
      "alternatives": [
        "ty after project-specific compatibility trial"
      ],
      "reason": "Explicit checks on application boundaries with a conservative established checker.",
      "limits": "Configure strictness and third-party stubs; unchecked Any and untyped functions reduce coverage. No checker performance comparison was run.",
      "source_urls": [
        "https://mypy.readthedocs.io/en/stable/getting_started.html",
        "https://docs.astral.sh/ty/type-checking/"
      ]
    },
    {
      "job": "Testing",
      "default": "pytest + HTTPX / FastAPI TestClient",
      "alternatives": [
        "Async client tests for async application lifecycles"
      ],
      "reason": "Test contract failures, auth and integration boundaries.",
      "limits": "Run startup/shutdown lifespan when relevant; include PostgreSQL and external-service fault tests.",
      "source_urls": [
        "https://docs.pytest.org/en/stable/getting-started.html",
        "https://fastapi.tiangolo.com/deployment/docker/"
      ]
    },
    {
      "job": "Database and migrations",
      "default": "PostgreSQL + SQLAlchemy + Psycopg + Alembic",
      "alternatives": [
        "SQLite for local single-user work; no DB for stateless services"
      ],
      "reason": "Explicit transactions and versioned relational changes.",
      "limits": "Session per thread / AsyncSession per task. Review generated migrations, especially renames and data changes; a passing migration check does not prove production lock safety.",
      "source_urls": [
        "https://docs.sqlalchemy.org/en/21/orm/session_basics.html",
        "https://alembic.sqlalchemy.org/en/latest/autogenerate.html"
      ]
    },
    {
      "job": "Validation",
      "default": "Pydantic request/response models; strict validation where coercion is unsafe",
      "alternatives": [
        "Explicit domain validation functions"
      ],
      "reason": "Typed schemas clarify external contracts and generated documentation.",
      "limits": "Coercion is configurable; schema validity is not authorization or business correctness. Avoid returning unrestricted ORM objects.",
      "source_urls": [
        "https://pydantic.dev/docs/validation/latest/concepts/strict_mode/"
      ]
    },
    {
      "job": "Authentication",
      "default": "Existing OIDC provider; validate access tokens and authorization in dependencies",
      "alternatives": [
        "Authlib for browser OIDC client flow",
        "First-party session authentication if architecture requires it"
      ],
      "reason": "Keep identity lifecycle with its owner while enforcing permissions at the API.",
      "limits": "Choose and verify token-validation integration at implementation. FastAPI's JWT tutorial is not a complete identity system; issuer, audience, expiry and permissions need tests.",
      "source_urls": [
        "https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/",
        "https://docs.authlib.org/en/v1.7.0/oauth2/client/web/index.html"
      ]
    },
    {
      "job": "Jobs",
      "default": "Separate Celery workers for queued jobs",
      "alternatives": [
        "Temporal for restart-safe multi-step workflows",
        "BackgroundTasks for small best-effort post-response work"
      ],
      "reason": "Separate request latency from heavy or retried work.",
      "limits": "BackgroundTasks does not establish durable execution. Make job effects idempotent and set retry/deadline limits.",
      "source_urls": [
        "https://fastapi.tiangolo.com/tutorial/background-tasks/",
        "https://docs.celeryq.dev/en/stable/userguide/tasks.html",
        "https://docs.temporal.io/develop/python"
      ]
    },
    {
      "job": "Long-running durable agents",
      "default": "Temporal Python SDK when recovery across restarts is required",
      "alternatives": [
        "Celery for independent queued jobs; direct function for bounded work"
      ],
      "reason": "Persisted workflow orchestration and separate worker processes suit retries, pauses and human waits.",
      "limits": "Adds a service and operational cost. Keep external I/O in activities, make side effects idempotent, test replay and cancellation; no end-to-end integration was run.",
      "source_urls": [
        "https://docs.temporal.io/develop/python",
        "https://docs.celeryq.dev/en/stable/userguide/tasks.html"
      ]
    },
    {
      "job": "Serving and deployment",
      "default": "FastAPI standard CLI / Uvicorn in a container",
      "alternatives": [
        "Managed ASGI platform"
      ],
      "reason": "Official deployment path with explicit process and container choices.",
      "limits": "Build from a supported base rather than deprecated framework images; choose process count to match deployment/memory, and run schema migration once per release.",
      "source_urls": [
        "https://fastapi.tiangolo.com/deployment/docker/",
        "https://docs.astral.sh/uv/guides/integration/docker/",
        "https://fastapi.tiangolo.com/async/"
      ]
    },
    {
      "job": "Application logging",
      "default": "Python logging with configured handlers",
      "alternatives": [
        "Preserve an existing compatible project choice"
      ],
      "reason": "Shared standard logging captures application and dependency diagnostics",
      "limits": "Configure logging at entry point, redact credentials and add request/job IDs, duration and failure context. Persist logs on the execution platform; metrics/tracing backend is a separate operational choice.",
      "source_urls": [
        "https://docs.python.org/3/library/logging.html"
      ]
    },
    {
      "job": "Bounded external-call retries",
      "default": "Tenacity only for retryable transient failures",
      "alternatives": [
        "Provider SDK retry policy when sufficient"
      ],
      "reason": "Explicit stop/wait/filter rules support controlled retries",
      "limits": "Install tenacity; set attempt/deadline limits, jitter and exception filters. The bare decorator retries forever without delay; do not stack retries with SDK/worker retries or repeat non-idempotent effects without keys.",
      "source_urls": [
        "https://tenacity.readthedocs.io/en/latest/"
      ]
    },
    {
      "job": "Uploads",
      "default": "FastAPI UploadFile",
      "alternatives": [
        "Preserve an existing compatible project choice"
      ],
      "reason": "Spooling file interface avoids eagerly materializing all content in application memory",
      "limits": "Install python-multipart; enforce request/file limits and authorization, stream to durable storage and clean partial writes. Multipart parsing does not establish file safety.",
      "source_urls": [
        "https://fastapi.tiangolo.com/tutorial/request-files/"
      ]
    },
    {
      "job": "Realtime transport",
      "default": "FastAPI WebSocket endpoints",
      "alternatives": [
        "Preserve an existing compatible project choice"
      ],
      "reason": "Native ASGI endpoint support fits connected API clients",
      "limits": "Authorize handshake/messages; bound per-client queues, handle disconnect and share state through an external service for replicas. In-memory tutorial connection lists are not multi-process state.",
      "source_urls": [
        "https://fastapi.tiangolo.com/advanced/websockets/"
      ]
    },
    {
      "job": "Object storage",
      "default": "Boto3 S3 client when durable objects are required",
      "alternatives": [
        "Preserve an existing compatible project choice"
      ],
      "reason": "Official SDK supports file transfer to S3",
      "limits": "Install boto3 only for S3-backed work; use platform credentials, private keys and bounded transfers. Boto3 is synchronous: keep blocking transfers out of an async event loop; verify alternative provider compatibility.",
      "source_urls": [
        "https://docs.aws.amazon.com/boto3/latest/guide/s3-uploading-files.html"
      ]
    }
  ],
  "setup_steps": [
    "In a new local source directory: uv init; pin a compatible Python minor; uv add 'fastapi[standard]' sqlalchemy 'psycopg[binary]' alembic pydantic-settings",
    "uv add --dev ruff mypy pytest httpx",
    "Create an importable app package with app/main.py exporting app = FastAPI(), request/response models and a health endpoint.",
    "uv run alembic init migrations; configure environment-based connection URL and target_metadata. Implement per-request/task sessions and domain transaction boundaries.",
    "uv run alembic revision --autogenerate -m 'initial schema'; manually review, then uv run alembic upgrade head against the development DB.",
    "Configure the selected identity provider and token verification; implement tenant/object authorization before adding protected endpoints.",
    "Develop with uv run fastapi dev app/main.py. Package a release with uv sync --locked --no-dev and an explicit production start command; add workers separately when needed."
  ],
  "verification_commands": [
    "uv sync --locked",
    "uv run ruff check .",
    "uv run ruff format --check .",
    "uv run mypy app",
    "uv run pytest",
    "uv run alembic check",
    "uv run alembic current"
  ],
  "open_questions": [
    "Which identity provider, token validation and tenant authorization model apply?",
    "Does workload justify async database access, or is synchronous I/O simpler?",
    "Which host/replica model, upload storage, realtime and worker guarantees apply?"
  ],
  "evidence_status": "documentation-reviewed",
  "sources": [
    {
      "url": "https://docs.astral.sh/uv/guides/projects/",
      "title": "uv projects",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.astral.sh/ruff/installation/",
      "title": "Ruff installation",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://mypy.readthedocs.io/en/stable/getting_started.html",
      "title": "mypy getting started",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.astral.sh/ty/type-checking/",
      "title": "ty type checking",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.pytest.org/en/stable/getting-started.html",
      "title": "pytest getting started",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://fastapi.tiangolo.com/deployment/docker/",
      "title": "FastAPI containers",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.sqlalchemy.org/en/21/orm/session_basics.html",
      "title": "SQLAlchemy session basics",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://alembic.sqlalchemy.org/en/latest/autogenerate.html",
      "title": "Alembic autogeneration",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://pydantic.dev/docs/validation/latest/concepts/strict_mode/",
      "title": "Pydantic strict mode",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/",
      "title": "FastAPI JWT tutorial",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.authlib.org/en/v1.7.0/oauth2/client/web/index.html",
      "title": "Authlib OAuth web clients",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://fastapi.tiangolo.com/tutorial/background-tasks/",
      "title": "FastAPI background tasks",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.celeryq.dev/en/stable/userguide/tasks.html",
      "title": "Celery tasks",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.temporal.io/develop/python",
      "title": "Temporal Python SDK",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.astral.sh/uv/guides/integration/docker/",
      "title": "uv Docker",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://fastapi.tiangolo.com/async/",
      "title": "FastAPI concurrency",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.python.org/3/library/logging.html",
      "title": "Python logging",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://tenacity.readthedocs.io/en/latest/",
      "title": "Tenacity documentation",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://fastapi.tiangolo.com/tutorial/request-files/",
      "title": "FastAPI request files",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://fastapi.tiangolo.com/advanced/websockets/",
      "title": "FastAPI WebSockets",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.aws.amazon.com/boto3/latest/guide/s3-uploading-files.html",
      "title": "Boto3 uploads",
      "checked_date": "2026-10-10"
    }
  ],
  "title": "FastAPI",
  "language": "Python",
  "group": "APIs & services",
  "kind": [
    "api"
  ],
  "ui": "none",
  "host": "server",
  "summary": "Typed Python APIs alongside Python integrations, data or AI libraries.",
  "shape": "FastAPI · Pydantic · SQLAlchemy · Alembic",
  "tradeoff": "Authentication, migrations and durable jobs are separate integration decisions.",
  "research_file": "python.json",
  "reviewed": "2026-10-10",
  "best_practices": [
    "Validate tokens and permissions in dependencies; Pydantic validation does not establish authorization.",
    "Keep blocking calls out of async request handling and configure database connection lifetimes.",
    "Commit and rehearse Alembic migrations. Use isolated databases for integration tests.",
    "Move durable work to operated workers; an in-process background task cannot guarantee recovery."
  ],
  "research_freshness": {
    "core_guidance_checked_on": "2026-10-13",
    "sources": [
      "https://fastapi.tiangolo.com/tutorial/"
    ],
    "scope": "Core framework roles, current setup/agent documentation and cited-source availability rechecked; not a reimplementation or exhaustive semantic audit of every third-party dependency."
  },
  "guide_url": "/stacks/python-fastapi/",
  "markdown_url": "/stacks/python-fastapi/guide.md",
  "json_url": "/stacks/python-fastapi/record.json",
  "architecture_and_migration": {
    "id": "python-fastapi",
    "version_scope": "Current FastAPI online guides fetched 11 October 2026; these pages do not pin an application package release. SQLAlchemy 2.0 documentation, Alembic 1.20.0 documentation and Celery 5.6.3 reviewed. Pin actual Python/FastAPI/Pydantic/Starlette/database-driver versions before implementation.",
    "operating_model": "FastAPI exposes Python type-annotated HTTP operations and dependency boundaries. It supports synchronous and async handlers; the choice depends on whether called libraries support await. Recommendation: keep request models distinct from persistence operations and explicitly select identity, durable jobs, database migrations and distributed messaging instead of assuming the API framework provides an integrated monolith.",
    "architecture": [
      "Use async handlers with awaitable I/O, or normal def handlers for blocking libraries as the guide explains. Recommendation: keep CPU-heavy or durable work behind a deliberate worker boundary; adding async syntax does not change its durability or CPU execution model.",
      "SQLAlchemy Sessions are mutable transaction state and cannot be shared across concurrent tasks/threads. Recommendation: scope a Session to its operation, keep the engine/pool separate and use reviewed Alembic revisions for schema evolution.",
      "FastAPI lifespan manages startup/shutdown resources. Multiple worker processes are a deployment choice; recommendation: treat in-memory connections/caches as worker-local and keep one external scheduler and migration owner."
    ],
    "developer_workflow": [
      "For a configured application, adapt fastapi run --workers 4 main.py or uvicorn main:app --workers 4 from the deployment guide; replace module and worker count for the actual host/container topology. The example is a recipe, not a capacity recommendation.",
      "For a configured SQLAlchemy/Alembic application, use alembic revision -m \"Add a column\", review upgrade/downgrade operations, then alembic upgrade head in a disposable database; alembic current and alembic history show recorded state.",
      "Use FastAPI TestClient and pytest for HTTP contract tests. Recommendation: add real database/worker tests for transaction and retry boundaries, plus WebSocket tests across the intended multi-process topology.",
      "Recommendation: initialize shared process resources through the lifespan context and create independent database sessions for concurrent operations. Validate selected sync/async client usage and cleanup on shutdown before rollout."
    ],
    "avoid": [
      "Avoid using BackgroundTasks as a durable queue replacement: it executes work associated with the application process, while the guide recommends larger worker tools such as Celery for work that belongs in multiple processes/servers. Recommendation: qualify crash/retry behavior explicitly.",
      "Avoid copying the tutorial’s in-memory WebSocket connection list into a multi-worker product; the docs explicitly say it works only in one running process.",
      "Avoid sharing one SQLAlchemy Session among requests/tasks or moving blocking library calls unchanged inside async handlers; the documented concurrency boundaries differ.",
      "Avoid treating a JWT tutorial as a complete identity migration. Recommendation: retain existing identity authority until issuer, account mapping, validation, expiry and revocation are designed. Starlette SessionMiddleware signs readable cookie contents; signing is not confidentiality."
    ],
    "transitions": [
      {
        "capability": "data",
        "existing_contract": "Inventory schema, primary IDs, SQL value/constraint semantics and existing transaction ownership. The old application may use an ORM with callbacks absent from the target service.",
        "coexistence": "Recommendation: keep one writer and migration runner; start with read-only target endpoints or a bounded domain operation. Preserve additive schema and qualify ORM/session behavior before transferring writes.",
        "target": "SQLAlchemy 2.0 Sessions scoped to operations, with reviewed Alembic upgrade/downgrade revisions and the selected PostgreSQL driver. Recommendation: keep transaction and external delivery boundaries explicit.",
        "benefits": [
          {
            "benefit": "Recommendation: explicit sessions and migrations expose the persistence boundary to review.",
            "prerequisites": "Qualified schema mapping, operation-scoped sessions and one writer owner.",
            "tradeoffs": "FastAPI does not remove ORM/migration choices; deleting data cannot be undone by traffic rollback."
          }
        ],
        "checks": [
          "Create through each allowed writer and read through both runtimes; compare IDs, timestamps/null values and constraint failures.",
          "Run concurrent requests with separate sessions and fail one transaction; no other request’s changes or Session state may leak.",
          "Apply a reviewed revision to a disposable restored database and verify both deployed versions still read new writes."
        ],
        "rollback": "Recommendation: restore the old writer while preserving backward-readable schema; use downgrade only for a rehearsed reversible change and reconcile accepted new data.",
        "sources": [
          "https://fastapi.tiangolo.com/tutorial/sql-databases/",
          "https://docs.sqlalchemy.org/en/20/orm/session_basics.html",
          "https://alembic.sqlalchemy.org/en/latest/tutorial.html"
        ],
        "id": "data-1"
      },
      {
        "capability": "jobs",
        "existing_contract": "Record old task name/class, serialized arguments, broker, retries/acknowledgements, schedule ownership and every backlog state. BackgroundTasks and a broker-backed worker are different execution contracts.",
        "coexistence": "Recommendation: retain old consumers and isolate new categories behind a versioned task interface. Use configured Celery or another separately qualified persistent system when restart recovery matters; keep one schedule owner and a recoverable domain-to-broker handoff.",
        "target": "An explicitly selected durable worker/broker composition with business idempotency. Small best-effort same-process tasks may use BackgroundTasks only when their documented process boundary fits the requirement.",
        "benefits": [
          {
            "benefit": "Recommendation: durable work can move independently of the HTTP service.",
            "prerequisites": "Selected broker/worker configuration, tested payloads and explicit idempotency/recovery policy.",
            "tradeoffs": "The broker and worker add operated components; returning HTTP success before enqueue acceptance must have a deliberate contract."
          }
        ],
        "checks": [
          "Enqueue while the worker is stopped, restart it and verify the intended completion/failure result.",
          "Crash after an external effect before acknowledgement and verify retry is safe; test broker outage during a domain write.",
          "Reconcile delayed/retry/failed/running tasks and verify the old and new schedulers never both produce the category."
        ],
        "rollback": "Recommendation: stop new task production, retain consumers for accepted payload versions and reconcile external effects before restoring old routing.",
        "sources": [
          "https://fastapi.tiangolo.com/tutorial/background-tasks/",
          "https://docs.celeryq.dev/en/stable/userguide/tasks.html",
          "https://docs.celeryq.dev/en/stable/userguide/periodic-tasks.html",
          "https://docs.celeryq.dev/en/stable/getting-started/first-steps-with-celery.html"
        ],
        "id": "jobs-1"
      },
      {
        "capability": "identity",
        "existing_contract": "Capture the source identity authority, token/cookie format, issuer/audience rules, account IDs, expiration and revocation. The FastAPI OAuth2/JWT guide is a concrete example, not proof of compatibility with existing sessions.",
        "coexistence": "Recommendation: retain the existing identity authority through qualified token verification or session exchange. Move resource authorization with the domain operation, and keep cookie scope/CSRF behavior explicit when using browser cookies.",
        "target": "Selected OAuth2/token or browser-session implementation with deliberate account mapping and authorization. If using Starlette SessionMiddleware, cookie data is signed and readable; use https_only and appropriate scope settings for the selected deployment.",
        "benefits": [
          {
            "benefit": "Recommendation: a shared identity authority can preserve access across service boundaries.",
            "prerequisites": "Qualified token/session validation and common revocation policy.",
            "tradeoffs": "Bearer expiry and server-side revocation are distinct design choices; readable signed cookies must not contain secrets."
          }
        ],
        "checks": [
          "Accept a valid source credential and reject modified/expired credentials and a valid credential for another tenant’s protected record.",
          "Logout/revoke and confirm both old/new paths follow the agreed policy, including an existing WebSocket connection.",
          "Inspect the selected cookie contents and transport flags; no secret should be exposed by a signed-but-readable session."
        ],
        "rollback": "Recommendation: preserve account mapping and old credential/exchange support without reversing revocations; return routing only when validation remains compatible.",
        "sources": [
          "https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/",
          "https://starlette.dev/middleware/",
          "https://fastapi.tiangolo.com/advanced/websockets/"
        ],
        "id": "identity-1"
      },
      {
        "capability": "realtime",
        "existing_contract": "Capture the old client protocol, message envelope, connection authentication, subscription scopes and recovery requirements. FastAPI provides WebSocket handlers; its in-memory chat example is explicitly single-process.",
        "coexistence": "Recommendation: retain the old endpoint for old clients, bridge versioned domain events and route a stable user/room cohort including reconnects. Keep fanout in a separately qualified shared system when multiple worker processes must reach the same recipients.",
        "target": "FastAPI WebSocket handlers with explicit shared fanout and persisted domain-state/cursor recovery when required. No specific broker/client combination is integration-qualified by this research.",
        "benefits": [
          {
            "benefit": "Recommendation: an API service can take ownership of a realtime boundary incrementally.",
            "prerequisites": "Matching message/client protocol, subscription authorization and a tested multi-worker fanout implementation.",
            "tradeoffs": "Connection lists remain worker-local; selecting a shared broker does not itself provide catch-up or protocol compatibility."
          }
        ],
        "checks": [
          "Connect clients to different workers, commit one domain event and verify all authorized recipients converge.",
          "Restart the worker containing a connection, reconnect and recover missed state; test a revoked identity attempting to rejoin."
        ],
        "rollback": "Recommendation: preserve old endpoint/message compatibility through reconnects; return the cohort and reconcile current domain state instead of reissuing effects.",
        "sources": [
          "https://fastapi.tiangolo.com/advanced/websockets/",
          "https://fastapi.tiangolo.com/deployment/server-workers/"
        ],
        "id": "realtime-1"
      },
      {
        "capability": "cache",
        "existing_contract": "List reconstructible values and representation/TTL/invalidation separately from identities, jobs, counters and locks. Multiple application workers have distinct in-memory resource ownership.",
        "coexistence": "Recommendation: keep the existing shared store for coordination; use versioned keys for new representations. Move only disposable values to local caching when per-worker staleness and rebuilding are explicitly accepted.",
        "target": "A selected shared cache accessed with a qualified client such as redis-py, or an explicitly bounded local cache. Recommendation: match sync/async client usage to the handler and manage process resource lifetime deliberately.",
        "benefits": [
          {
            "benefit": "Recommendation: cache choices can evolve without transferring domain ownership.",
            "prerequisites": "Reconstructible values, explicit invalidation and a complete list of shared-store uses.",
            "tradeoffs": "Local values diverge across workers; removing Redis requires separately retiring sessions/queues/coordination, not merely replacing cached reads."
          }
        ],
        "checks": [
          "Warm two workers, update the source and verify required invalidation/staleness across both.",
          "Restart one worker or evict its dedicated cache and verify reconstruction without losing identity or queued work.",
          "Make the shared cache unavailable and verify the agreed failure/fallback behavior rather than silently accepting stale authorization."
        ],
        "rollback": "Recommendation: restore old key/backend routing and repopulate from domain data; preserve shared coordination ownership throughout.",
        "sources": [
          "https://redis.io/docs/latest/develop/clients/redis-py/",
          "https://fastapi.tiangolo.com/deployment/server-workers/",
          "https://fastapi.tiangolo.com/advanced/events/"
        ],
        "id": "cache-1"
      },
      {
        "capability": "operations",
        "existing_contract": "Inventory API workers, startup resources, database migration runner, durable workers, external scheduler and shared fanout/cache. Worker replication and lifespan resources are not a singleton schedule mechanism.",
        "coexistence": "Recommendation: keep one schema runner and logical schedule owner while both services operate. Initialize per-process resources deliberately and transfer traffic by a stable domain/user cohort.",
        "target": "An explicit FastAPI/Uvicorn process/container deployment, lifespan cleanup, separate durable workers and monitored dependency boundaries. Recommendation: record actual worker count and deployment settings instead of inheriting tutorial values.",
        "benefits": [
          {
            "benefit": "Recommendation: process/resource ownership makes multi-worker behavior reviewable.",
            "prerequisites": "Named migration/schedule owners, configured shutdown and tested dependency failure behavior.",
            "tradeoffs": "More workers multiply process-local resources; successful HTTP startup cannot qualify broker, identity or restore behavior."
          }
        ],
        "checks": [
          "Start the intended multi-worker deployment against disposable restored data; exercise authenticated HTTP, one task and cross-worker realtime delivery.",
          "Terminate a worker during active work, verify shutdown/restart behavior and confirm no extra scheduler or migration runner starts."
        ],
        "rollback": "Recommendation: preserve the old release and compatible schema, transfer role ownership before restoring traffic, and reconcile work accepted by the new service.",
        "sources": [
          "https://fastapi.tiangolo.com/advanced/events/",
          "https://fastapi.tiangolo.com/deployment/server-workers/",
          "https://alembic.sqlalchemy.org/en/latest/tutorial.html",
          "https://docs.celeryq.dev/en/stable/userguide/periodic-tasks.html"
        ],
        "id": "operations-1"
      }
    ],
    "sources": [
      {
        "url": "https://fastapi.tiangolo.com/async/",
        "title": "FastAPI Concurrency",
        "claim": "Choice of async handlers versus normal def for awaitable/blocking libraries."
      },
      {
        "url": "https://fastapi.tiangolo.com/tutorial/sql-databases/",
        "title": "FastAPI SQL Databases",
        "claim": "Request-scoped database dependency examples and external SQL library choice."
      },
      {
        "url": "https://docs.sqlalchemy.org/en/20/orm/session_basics.html",
        "title": "SQLAlchemy Session Basics",
        "claim": "Mutable transaction/session lifecycle and prohibition on sharing across concurrent threads/tasks."
      },
      {
        "url": "https://alembic.sqlalchemy.org/en/latest/tutorial.html",
        "title": "Alembic Tutorial",
        "claim": "Revision, upgrade/downgrade, current/history commands and schema revision ownership."
      },
      {
        "url": "https://fastapi.tiangolo.com/tutorial/background-tasks/",
        "title": "FastAPI Background Tasks",
        "claim": "Same-process task examples and separate Celery/queue recommendation for larger execution boundaries."
      },
      {
        "url": "https://docs.celeryq.dev/en/stable/userguide/tasks.html",
        "title": "Celery Tasks",
        "claim": "Task serialization, retry/acknowledgement and idempotency concerns."
      },
      {
        "url": "https://docs.celeryq.dev/en/stable/userguide/periodic-tasks.html",
        "title": "Celery Periodic Tasks",
        "claim": "Only one scheduler per schedule to prevent duplicate production."
      },
      {
        "url": "https://docs.celeryq.dev/en/stable/getting-started/first-steps-with-celery.html",
        "title": "Celery First Steps",
        "claim": "Broker, worker and optional result backend are separate roles."
      },
      {
        "url": "https://fastapi.tiangolo.com/tutorial/security/oauth2-jwt/",
        "title": "FastAPI OAuth2/JWT example",
        "claim": "Token/password validation and expiry example, not cross-framework session interoperability."
      },
      {
        "url": "https://starlette.dev/middleware/",
        "title": "Starlette Middleware",
        "claim": "Signed readable sessions, session cookie configuration and secure transport option."
      },
      {
        "url": "https://fastapi.tiangolo.com/advanced/websockets/",
        "title": "FastAPI WebSockets",
        "claim": "Handler authentication/dependencies and explicit single-process limitation of in-memory connection list."
      },
      {
        "url": "https://fastapi.tiangolo.com/advanced/events/",
        "title": "FastAPI Lifespan",
        "claim": "Startup/shutdown resource ownership through lifespan."
      },
      {
        "url": "https://fastapi.tiangolo.com/deployment/server-workers/",
        "title": "FastAPI Server Workers",
        "claim": "FastAPI/Uvicorn worker commands and deployment process topology choices."
      },
      {
        "url": "https://fastapi.tiangolo.com/tutorial/testing/",
        "title": "FastAPI Testing",
        "claim": "TestClient and pytest request checks."
      },
      {
        "url": "https://redis.io/docs/latest/develop/clients/redis-py/",
        "title": "Redis redis-py guide",
        "claim": "Maintained Python client for Redis with sync/async documentation links."
      }
    ],
    "reviewed_at": "2026-10-11",
    "evidence": "documentation-reviewed"
  },
  "rewrite_url": "/rewrite/guide.md",
  "migration_contracts_url": "/rewrite/contracts.json",
  "agent_workflow": [
    "Read README, dependency manifests, lockfiles, runtime pins and the maintained project workflow before changing anything. Preserve an existing stack unless reconsidering it is part of the request.",
    "Use this guide to select tools by requirement. Resolve compatible versions from official and installed-version documentation; record the actual lockfile and runtime versions.",
    "Create a plan for schema changes, identity, authorization, external effects and deployment. A library choice does not complete its integration.",
    "Run relevant checks after configuration. Exercise the real interface, failure paths and packaged artifact on the intended target. Report commands, versions, results and untested behavior.",
    "On failure, retain the command and diagnostic, fix the failing prerequisite and resume there. Do not regenerate over existing work or suppress failures to make a check green."
  ],
  "selection": {
    "native_ui": false,
    "static_hosting": false,
    "offline_client_candidate": false
  },
  "coverage_note": "Tools are curated starting points for this application role. Exact versions, integrations and offline behavior require project-specific qualification."
}
