affaan-m/ECC

fastapi-patterns

FastAPI patterns for async APIs, dependency injection, Pydantic request and response models, OpenAPI docs, tests, security, and production readiness.

87CollectingNetwork access
See how to use itView GitHub source
npx skills add https://github.com/affaan-m/ECC --skill ".kiro/skills/fastapi-patterns"
Automated source guide

Source checked Jul 28, 2026·Refresh due Oct 26, 2026

Reorganized from the pinned upstream SKILL.md

Turn fastapi-patterns's source instructions into a guide you can follow

According to the pinned SKILL.md from affaan-m/ECC: Production-oriented patterns for FastAPI services.

npx skills add https://github.com/affaan-m/ECC --skill ".kiro/skills/fastapi-patterns"
Check the pinned source

Best fit

  • Building or reviewing a FastAPI app.
  • Splitting routers, schemas, dependencies, and database access.
  • Writing async endpoints that call a database or external service.

Bring this context

  • A concrete task that matches the documented purpose of fastapi-patterns.
  • The files, examples, or context the task depends on.
  • Your constraints, target environment, and definition of done.

Expected outputs

  • Application factory: configure middleware and routers once in createapp.
  • Schema split: UserCreate, UserUpdate, and UserResponse have different responsibilities.
  • Dependency override: tests override getdb directly.

Key source sections

Read fastapi-patterns through these 5 source sections

Sections are extracted automatically from the pinned SKILL.md and link back to the source.

01

When to Use

Building or reviewing a FastAPI app.

SKILL.md · When to Use
Building or reviewing a FastAPI app.Splitting routers, schemas, dependencies, and database access.Writing async endpoints that call a database or external service.
02

How It Works

Treat the FastAPI app as a thin HTTP layer over explicit dependencies and service code:

SKILL.md · How It Works
main.py owns app construction, middleware, exception handlers, and router registration.schemas/ owns Pydantic request and response models.dependencies.py owns database, auth, pagination, and request-scoped dependencies.
03

Project Layout

Review the “Project Layout” section in the pinned source before continuing.

SKILL.md · Project Layout
Review and apply the “Project Layout” source section.
04

Application Factory

Use a factory so tests and workers can build the app with controlled settings.

SKILL.md · Application Factory
Use a factory so tests and workers can build the app with controlled settings.Do not use alloworigins=[""] with allowcredentials=True; browsers reject that combination and Starlette disallows it for credentialed requests.
05

Pydantic Schemas

Keep request, update, and response models separate.

SKILL.md · Pydantic Schemas
Keep request, update, and response models separate.Response models must never include password hashes, access tokens, refresh tokens, or internal authorization state.

SkillSignal prompt templates

Provide the task, context, and acceptance criteria

These prompts were written by SkillSignal from the source structure; they are not upstream text.

Task-start prompt

Confirm source fit, inputs, and outputs before acting.

Use fastapi-patterns to help me with: [specific task]. Context: [files, data, or background]. Constraints: [environment, scope, and prohibited actions]. Before acting, check the pinned SKILL.md and explain which sections apply, what inputs are still missing, and what you will deliver.

Source-guided execution

Make the Agent explicitly follow the key extracted sections.

Apply the pinned fastapi-patterns source to [task]. Pay particular attention to these source sections: “When to Use”, “How It Works”, “Project Layout”, “Application Factory”, “Pydantic Schemas”. Preserve the important decision at each step. Mark facts not covered by the source as “needs confirmation” instead of inventing them. Then verify the result against my acceptance criteria: [criteria].

Result-review prompt

Check omissions, permissions, and source drift before delivery.

Review the current fastapi-patterns result: (1) does it satisfy the original task; (2) were any applicable steps or limits in the pinned SKILL.md missed; (3) did it perform any unauthorized file, command, network, or data action; and (4) which conclusions remain unverified? List issues first, then fix only what the source or user authorization supports.

Output checklist

Verify each item before delivery

The task matches the purpose documented in the SKILL.md.

The source section “When to Use” has been checked.

The source section “How It Works” has been checked.

The source section “Project Layout” has been checked.

The source section “Application Factory” has been checked.

Inputs, constraints, and acceptance criteria are explicit.

Unverified facts, compatibility, and outcome claims are clearly marked.

Any file, command, network, or data action has been reviewed.

Choose a different workflow

When another Skill is the better fit

FAQ

What does fastapi-patterns do?

Production-oriented patterns for FastAPI services.

How do I start using fastapi-patterns?

The catalog detected this source-specific install command: npx skills add https://github.com/affaan-m/ECC --skill ".kiro/skills/fastapi-patterns". Inspect the command and pinned source before running it.

Which Agent platforms does it declare?

No dedicated Agent platform is declared in the pinned source record.

Repository stars
234,327
Repository forks
35,711
Quality
87/100
Source repository last pushed

Quality breakdown

Based on traceable docs and repository signals; stars are not treated as quality.

87/100
Documentation27/30
Specificity19/25
Maintenance20/20
Trust signals21/25

Compare before choosing

Related Agent Skills and source variants

These links are selected from shared tasks, functions, stacks, platforms, and same-name variants. Compare the source owner, documentation, permissions, and maintenance signals.

View original Skill.mdThis page is parsed directly from the repository SKILL.md without editorial rewriting. Collected: Jul 28, 2026 · about 3 min

FastAPI Patterns

Production-oriented patterns for FastAPI services.

When to Use

  • Building or reviewing a FastAPI app.
  • Splitting routers, schemas, dependencies, and database access.
  • Writing async endpoints that call a database or external service.
  • Adding authentication, authorization, OpenAPI docs, tests, or deployment settings.
  • Checking a FastAPI PR for copy-pasteable examples and production risks.

How It Works

Treat the FastAPI app as a thin HTTP layer over explicit dependencies and service code:

  • main.py owns app construction, middleware, exception handlers, and router registration.
  • schemas/ owns Pydantic request and response models.
  • dependencies.py owns database, auth, pagination, and request-scoped dependencies.
  • services/ or crud/ owns business and persistence operations.
  • tests/ overrides dependencies instead of opening production resources.

Prefer small routers and explicit response_model declarations. Keep raw ORM objects, secrets, and framework globals out of response schemas.

Project Layout

app/
|-- main.py
|-- config.py
|-- dependencies.py
|-- exceptions.py
|-- api/
|   `-- routes/
|       |-- users.py
|       `-- health.py
|-- core/
|   |-- security.py
|   `-- middleware.py
|-- db/
|   |-- session.py
|   `-- crud.py
|-- models/
|-- schemas/
`-- tests/

Application Factory

Use a factory so tests and workers can build the app with controlled settings.

from contextlib import asynccontextmanager

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from app.api.routes import health, users
from app.config import settings
from app.db.session import close_db, init_db
from app.exceptions import register_exception_handlers


@asynccontextmanager
async def lifespan(app: FastAPI):
    await init_db()
    yield
    await close_db()


def create_app() -> FastAPI:
    app = FastAPI(
        title=settings.api_title,
        version=settings.api_version,
        lifespan=lifespan,
    )

    app.add_middleware(
        CORSMiddleware,
        allow_origins=settings.cors_origins,
        allow_credentials=bool(settings.cors_origins),
        allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE"],
        allow_headers=["Authorization", "Content-Type"],
    )

    register_exception_handlers(app)
    app.include_router(health.router, prefix="/health", tags=["health"])
    app.include_router(users.router, prefix="/api/v1/users", tags=["users"])
    return app


app = create_app()

Do not use allow_origins=["*"] with allow_credentials=True; browsers reject that combination and Starlette disallows it for credentialed requests.

Pydantic Schemas

Keep request, update, and response models separate.

from datetime import datetime
from typing import Annotated
from uuid import UUID

from pydantic import BaseModel, ConfigDict, EmailStr, Field


class UserBase(BaseModel):
    email: EmailStr
    full_name: Annotated[str, Field(min_length=1, max_length=100)]


class UserCreate(UserBase):
    password: Annotated[str, Field(min_length=12, max_length=128)]


class UserUpdate(BaseModel):
    email: EmailStr | None = None
    full_name: Annotated[str | None, Field(min_length=1, max_length=100)] = None


class UserResponse(UserBase):
    model_config = ConfigDict(from_attributes=True)

    id: UUID
    created_at: datetime
    updated_at: datetime

Response models must never include password hashes, access tokens, refresh tokens, or internal authorization state.

Dependencies

Use dependency injection for request-scoped resources.

from collections.abc import AsyncIterator
from uuid import UUID

from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.security import decode_token
from app.db.session import session_factory
from app.models.user import User


oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")


async def get_db() -> AsyncIterator[AsyncSession]:
    async with session_factory() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise


async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: AsyncSession = Depends(get_db),
) -> User:
    payload = decode_token(token)
    user_id = UUID(payload["sub"])
    user = await db.get(User, user_id)
    if user is None:
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid token")
    return user

Avoid creating sessions, clients, or credentials inline inside route handlers.

Async Endpoints

Keep route handlers async when they perform I/O, and use async libraries inside them.

from fastapi import APIRouter, Depends, Query
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.dependencies import get_current_user, get_db
from app.models.user import User
from app.schemas.user import UserResponse


router = APIRouter()


@router.get("/", response_model=list[UserResponse])
async def list_users(
    limit: int = Query(default=50, ge=1, le=100),
    offset: int = Query(default=0, ge=0),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(get_current_user),
):
    result = await db.execute(
        select(User).order_by(User.created_at.desc()).limit(limit).offset(offset)
    )
    return result.scalars().all()

Use httpx.AsyncClient for external HTTP calls from async handlers. Do not call requests in an async route.

Error Handling

Centralize domain exceptions and keep response shapes stable.

from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse


class ApiError(Exception):
    def __init__(self, status_code: int, code: str, message: str):
        self.status_code = status_code
        self.code = code
        self.message = message


def register_exception_handlers(app: FastAPI) -> None:
    @app.exception_handler(ApiError)
    async def api_error_handler(request: Request, exc: ApiError):
        return JSONResponse(
            status_code=exc.status_code,
            content={"error": {"code": exc.code, "message": exc.message}},
        )

OpenAPI Customization

Assign the custom OpenAPI callable to app.openapi; do not just call the function once.

from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi


def install_openapi(app: FastAPI) -> None:
    def custom_openapi():
        if app.openapi_schema:
            return app.openapi_schema
        app.openapi_schema = get_openapi(
            title="Service API",
            version="1.0.0",
            routes=app.routes,
        )
        return app.openapi_schema

    app.openapi = custom_openapi

Testing

Override the dependency used by Depends, not an internal helper that route handlers never reference.

import pytest
from httpx import ASGITransport, AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from app.dependencies import get_db
from app.main import create_app


@pytest.fixture
async def client(test_session: AsyncSession):
    app = create_app()

    async def override_get_db():
        yield test_session

    app.dependency_overrides[get_db] = override_get_db
    async with AsyncClient(
        transport=ASGITransport(app=app),
        base_url="http://test",
    ) as test_client:
        yield test_client
    app.dependency_overrides.clear()

Security Checklist

  • Hash passwords with argon2-cffi, bcrypt, or a current passlib-compatible hasher.
  • Validate JWT issuer, audience, expiry, and signing algorithm.
  • Keep CORS origins environment-specific.
  • Put rate limits on auth and write-heavy endpoints.
  • Use Pydantic models for all request bodies.
  • Use ORM parameter binding or SQLAlchemy Core expressions; never build SQL with f-strings.
  • Redact tokens, authorization headers, cookies, and passwords from logs.
  • Run dependency audit tooling in CI.

Performance Checklist

  • Configure database connection pooling explicitly.
  • Add pagination to list endpoints.
  • Watch for N+1 queries and use eager loading intentionally.
  • Use async HTTP/database clients in async paths.
  • Add compression only after checking payload size and CPU tradeoffs.
  • Cache stable expensive reads behind explicit invalidation.

Examples

Use these examples as patterns, not as project-wide templates:

  • Application factory: configure middleware and routers once in create_app.
  • Schema split: UserCreate, UserUpdate, and UserResponse have different responsibilities.
  • Dependency override: tests override get_db directly.
  • OpenAPI customization: assign app.openapi = custom_openapi.

See Also

  • Agent: fastapi-reviewer
  • Command: /fastapi-review
  • Skill: python-patterns
  • Skill: python-testing
  • Skill: api-design
Source repo
affaan-m/ECC
Skill path
.kiro/skills/fastapi-patterns/SKILL.md
Commit SHA
4e973d3eaf92
Repository license
MIT
Data collected