fastapi-senior-dev

Senior Python Backend Engineer skill for FastAPI. Use when scaffolding production-ready APIs, enforcing clean architecture, optimizing async patterns, or auditing FastAPI codebases.

18 stars

Best use case

fastapi-senior-dev is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Senior Python Backend Engineer skill for FastAPI. Use when scaffolding production-ready APIs, enforcing clean architecture, optimizing async patterns, or auditing FastAPI codebases.

Teams using fastapi-senior-dev should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/fastapi-senior-dev/SKILL.md --create-dirs "https://raw.githubusercontent.com/georgekhananaev/claude-skills-vault/main/.claude/skills/fastapi-senior-dev/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/fastapi-senior-dev/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How fastapi-senior-dev Compares

Feature / Agentfastapi-senior-devStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Senior Python Backend Engineer skill for FastAPI. Use when scaffolding production-ready APIs, enforcing clean architecture, optimizing async patterns, or auditing FastAPI codebases.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# FastAPI Senior Developer

Transform into a Senior Python Backend Engineer for production-ready FastAPI applications.

## When to Use

- Scaffolding new FastAPI projects
- Implementing clean architecture patterns
- Database integration (PostgreSQL, MongoDB)
- Authentication (OAuth2, JWT, OIDC)
- Microservices & event-driven patterns
- Performance optimization & async patterns
- Security hardening (OWASP compliance)

## Triggers

- `/fastapi-init` - Scaffold new project with clean architecture
- `/fastapi-structure` - Analyze & restructure existing project
- `/fastapi-audit` - Code review for patterns, performance, security

## Reference Files

Load appropriate references based on task context:

| Category | Reference | When to Load |
|----------|-----------|--------------|
| Database | `references/database-sqlalchemy.md` | PostgreSQL, async ORM, migrations |
| Database | `references/database-mongodb.md` | MongoDB with Beanie/Motor |
| Caching | `references/caching-redis.md` | Redis caching, sessions, pub/sub |
| Security | `references/security-auth.md` | OAuth2, JWT, OIDC, RBAC |
| Security | `references/security-owasp.md` | OWASP compliance, hardening |
| Observability | `references/observability.md` | Logging, metrics, tracing |
| Microservices | `references/microservices.md` | Celery, Kafka, event-driven |
| API Design | `references/api-lifecycle.md` | Versioning, deprecation, docs |
| Operations | `references/production-ops.md` | Health checks, K8s, deployment |

## Core Tenets

### 1. Thin Routes, Fat Services

Routes handle HTTP concerns only. Business logic lives in services.

```python
# WRONG: Logic in route
@router.post("/orders")
async def create_order(order: OrderCreate, db: AsyncSession = Depends(get_db)):
    if not await db.get(Product, order.product_id):
        raise HTTPException(404, "Product not found")
    # ... 50 more lines of business logic
    return order

# RIGHT: Thin route, fat service
@router.post("/orders", response_model=OrderResponse)
async def create_order(
    order: OrderCreate,
    service: OrderService = Depends(get_order_service)
) -> OrderResponse:
    return await service.create(order)
```

### 2. Configuration First

Use pydantic-settings as foundational concern. Split by domain.

```python
# core/config.py
from pydantic_settings import BaseSettings, SettingsConfigDict

class DatabaseSettings(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="DB_")

    host: str = "localhost"
    port: int = 5432
    name: str
    user: str
    password: str
    pool_size: int = 10
    max_overflow: int = 20

    @property
    def async_url(self) -> str:
        return f"postgresql+asyncpg://{self.user}:{self.password}@{self.host}:{self.port}/{self.name}"

class AuthSettings(BaseSettings):
    model_config = SettingsConfigDict(env_prefix="AUTH_")

    secret_key: str
    algorithm: str = "HS256"
    access_token_expire_minutes: int = 30
    refresh_token_expire_days: int = 7

class Settings(BaseSettings):
    debug: bool = False
    db: DatabaseSettings = DatabaseSettings()
    auth: AuthSettings = AuthSettings()

settings = Settings()
```

### 3. Project Organization

Choose architecture based on project size. Be consistent.

**Vertical Slice (Recommended for most projects)**
```
src/
├── users/
│   ├── router.py
│   ├── service.py
│   ├── schemas.py
│   ├── models.py
│   └── dependencies.py
├── orders/
│   ├── router.py
│   ├── service.py
│   └── ...
└── core/
    ├── config.py
    ├── database.py
    └── security.py
```

**Layered Architecture (Large teams, strict boundaries)**
```
src/
├── api/
│   ├── routes/
│   ├── deps/
│   └── schemas/
├── services/
├── repositories/
├── models/
│   ├── domain/
│   └── db/
└── core/
```

### 4. Service Layer Pattern (Not Repository)

Use services with direct ORM access. Avoid unnecessary repository abstraction.

```python
# services/user_service.py
class UserService:
    def __init__(self, db: AsyncSession, cache: Redis):
        self.db = db
        self.cache = cache

    async def get_by_id(self, user_id: int) -> User | None:
        # Check cache first
        cached = await self.cache.get(f"user:{user_id}")
        if cached:
            return User.model_validate_json(cached)

        # Direct ORM query - no repository needed
        result = await self.db.execute(
            select(UserModel)
            .options(selectinload(UserModel.profile))
            .where(UserModel.id == user_id)
        )
        user_model = result.scalar_one_or_none()

        if user_model:
            user = User.model_validate(user_model)
            await self.cache.setex(f"user:{user_id}", 300, user.model_dump_json())
            return user
        return None
```

### 5. Advanced Dependency Injection

Chain dependencies for validation and composition.

```python
# deps/common.py
async def get_db() -> AsyncGenerator[AsyncSession, None]:
    async with async_session() as session:
        try:
            yield session
            await session.commit()
        except Exception:
            await session.rollback()
            raise

# deps/users.py
async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: AsyncSession = Depends(get_db)
) -> User:
    payload = verify_token(token)
    user = await db.get(UserModel, payload["sub"])
    if not user:
        raise HTTPException(401, "User not found")
    return user

async def get_current_active_user(
    user: User = Depends(get_current_user)
) -> User:
    if not user.is_active:
        raise HTTPException(403, "Inactive user")
    return user

# deps/resources.py
async def valid_post_id(
    post_id: int,
    db: AsyncSession = Depends(get_db)
) -> Post:
    post = await db.get(PostModel, post_id)
    if not post:
        raise HTTPException(404, "Post not found")
    return post

async def valid_owned_post(
    post: Post = Depends(valid_post_id),
    user: User = Depends(get_current_user)
) -> Post:
    if post.owner_id != user.id:
        raise HTTPException(403, "Not your post")
    return post

# Usage in routes
@router.put("/posts/{post_id}")
async def update_post(
    data: PostUpdate,
    post: Post = Depends(valid_owned_post)  # Validates existence + ownership
) -> PostResponse:
    ...
```

## Async Patterns

### Do

```python
# Async DB with proper session handling
async def get_user(db: AsyncSession, user_id: int) -> User | None:
    result = await db.execute(select(User).where(User.id == user_id))
    return result.scalar_one_or_none()

# Concurrent independent calls
async def get_dashboard_data(user_id: int) -> DashboardData:
    user, orders, notifications = await asyncio.gather(
        user_service.get(user_id),
        order_service.list_recent(user_id),
        notification_service.get_unread(user_id),
        return_exceptions=True
    )
    return DashboardData(user=user, orders=orders, notifications=notifications)

# Background tasks for non-blocking operations
@router.post("/users")
async def create_user(user: UserCreate, background: BackgroundTasks):
    db_user = await user_service.create(user)
    background.add_task(send_welcome_email, db_user.email)
    background.add_task(analytics.track, "user_created", db_user.id)
    return db_user
```

### Don't

```python
# WRONG: Blocking calls in async context
time.sleep(5)           # Use: await asyncio.sleep(5)
requests.get(url)       # Use: async with httpx.AsyncClient() as client
open("file").read()     # Use: aiofiles.open()

# WRONG: Sequential when parallel is possible
user = await get_user(id)
orders = await get_orders(id)  # Use asyncio.gather()

# WRONG: Sync dependencies in async routes
def get_db():  # Should be: async def get_db()
    return SessionLocal()
```

## Pydantic V2 Patterns

```python
from pydantic import BaseModel, ConfigDict, Field, field_validator
from datetime import datetime

class BaseSchema(BaseModel):
    """Base for all schemas with common config."""
    model_config = ConfigDict(
        from_attributes=True,
        str_strip_whitespace=True,
        validate_assignment=True,
    )

class UserCreate(BaseSchema):
    email: str = Field(..., min_length=5, max_length=255)
    password: str = Field(..., min_length=8)

    @field_validator("email")
    @classmethod
    def normalize_email(cls, v: str) -> str:
        return v.lower().strip()

class UserUpdate(BaseSchema):
    model_config = ConfigDict(extra="forbid")

    name: str | None = None
    avatar_url: str | None = None

class UserResponse(BaseSchema):
    id: int
    email: str
    name: str | None
    created_at: datetime
    # Never expose: password, is_admin, internal fields

class UserInDB(UserResponse):
    hashed_password: str  # Internal use only
```

## Error Handling

```python
# core/exceptions.py
from fastapi import Request
from fastapi.responses import JSONResponse

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

class NotFoundError(AppException):
    def __init__(self, resource: str, identifier: Any):
        super().__init__(
            message=f"{resource} with id '{identifier}' not found",
            code="NOT_FOUND",
            status_code=404
        )

class AuthorizationError(AppException):
    def __init__(self, message: str = "Not authorized"):
        super().__init__(message=message, code="FORBIDDEN", status_code=403)

# Register handler
@app.exception_handler(AppException)
async def app_exception_handler(request: Request, exc: AppException):
    return JSONResponse(
        status_code=exc.status_code,
        content={
            "error": {
                "code": exc.code,
                "message": exc.message,
            }
        }
    )

# Production: Hide stack traces
@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
    logger.exception("Unhandled exception", exc_info=exc)
    return JSONResponse(
        status_code=500,
        content={"error": {"code": "INTERNAL_ERROR", "message": "Internal server error"}}
    )
```

## Security Essentials

See `references/security-auth.md` and `references/security-owasp.md` for complete patterns.

### Quick Checklist

- [ ] Use **PyJWT** (not python-jose) for JWT handling
- [ ] **Auth Code + PKCE** for SPAs/Mobile (not password flow)
- [ ] Short-lived access tokens (15-30 min)
- [ ] Refresh tokens in HttpOnly cookies
- [ ] Rate limiting on auth endpoints
- [ ] Request body size limits
- [ ] pydantic-settings for secrets (never hardcode)
- [ ] Log sanitization (filter password, token, authorization)

## Anti-Patterns

| Don't | Do |
|-------|-----|
| Business logic in routes | Move to services |
| DB queries in routes | Use service layer |
| `requests` in async code | Use `httpx.AsyncClient` |
| `time.sleep()` | Use `asyncio.sleep()` |
| Hardcoded config | Use pydantic-settings |
| Return dict from routes | Return Pydantic models |
| Skip type hints | Type everything |
| Global scoped_session | Request-scoped via Depends |
| Repository pattern overkill | Service + direct ORM |
| python-jose for JWT | Use PyJWT |

## Scripts

- `scripts/scaffold_structure.py` - Generate clean architecture folders
- `scripts/generate_migration.py` - Alembic wrapper for async migrations

## Assets

- `assets/docker-compose.yml` - Postgres + Redis + API stack
- `assets/Dockerfile` - Multi-stage production build

## Audit Checklist

When running `/fastapi-audit`, check:

1. **Architecture**
   - [ ] Thin routes, fat services
   - [ ] Consistent project structure
   - [ ] No circular imports

2. **Async**
   - [ ] No blocking calls in async code
   - [ ] Proper session handling
   - [ ] Concurrent calls where possible

3. **Security** (load `references/security-owasp.md`)
   - [ ] Auth patterns correct
   - [ ] Input validation complete
   - [ ] No hardcoded secrets

4. **Database** (load `references/database-sqlalchemy.md`)
   - [ ] Connection pooling configured
   - [ ] N+1 queries prevented
   - [ ] Migrations reversible

5. **Observability** (load `references/observability.md`)
   - [ ] Structured logging
   - [ ] Health checks present
   - [ ] Metrics exposed

Related Skills

senior-backend

18
from georgekhananaev/claude-skills-vault

This skill should be used when the user asks to "design REST APIs", "optimize database queries", "implement authentication", "build microservices", "review backend code", "set up GraphQL", "handle database migrations", or "load test APIs". Use for Node.js/Express/Fastify development, PostgreSQL optimization, API security, and backend architecture patterns.

nextjs-senior-dev

18
from georgekhananaev/claude-skills-vault

Senior Next.js 15+/16 Engineer skill for App Router. Use when scaffolding production apps, enforcing RSC patterns, auditing codebases, or optimizing performance.

webapp-testing

18
from georgekhananaev/claude-skills-vault

Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.

web-quality

18
from georgekhananaev/claude-skills-vault

Web quality optimization skills based on Google Lighthouse guidelines and Core Web Vitals. Use when asked to audit web quality, optimize performance, improve accessibility, fix SEO, apply best practices, or analyze Core Web Vitals (LCP, INP, CLS).

vercel-react-native-skills

18
from georgekhananaev/claude-skills-vault

React Native and Expo best practices for building performant mobile apps. Use when building React Native components, optimizing list performance, implementing animations, or working with native modules. Triggers on tasks involving React Native, Expo, mobile performance, or native platform APIs.

upgrade-packages-js

18
from georgekhananaev/claude-skills-vault

Safely upgrade JavaScript packages with breaking change detection, migration guidance, and automated code migrations (npm/pnpm/yarn). Cross-platform with git safety branch enforcement.

uiux-toolkit

18
from georgekhananaev/claude-skills-vault

Comprehensive UX/UI evaluation meta-skill combining design theory and UX methodology. Use when conducting UI/UX audits, visual design reviews, accessibility compliance (WCAG 2.2), user flow analysis, responsive testing, interaction design evaluation, or design system audits. Evaluates using Nielsen's heuristics, Gestalt principles, typography theory, color theory, and modern methodologies (OOUX, JTBD, Cognitive Walkthrough).

ui-ux-pro-max

18
from georgekhananaev/claude-skills-vault

UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 9 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient. Integrations: shadcn/ui MCP for component search and examples.

trailofbits-security

18
from georgekhananaev/claude-skills-vault

Security-focused static analysis and code auditing skills from Trail of Bits. Includes CodeQL deep analysis, Semgrep scanning, and SARIF result processing. Use when performing security audits, running static analysis, scanning for vulnerabilities, or processing scan results.

token-optimizer

18
from georgekhananaev/claude-skills-vault

Reduce token count in prompts, docs, and prose. Covers prompt compression (40-60% savings), doc formatting, TOON data serialization, and Strunk's prose clarity rules. Use when compressing prompts, optimizing docs for LLM context, or writing clear technical prose.

testing-automation-expert

18
from georgekhananaev/claude-skills-vault

Production-grade testing strategies for robust, maintainable systems. Covers unit/integration/E2E testing, contract testing, accessibility, mutation testing, and CI/CD patterns. Supports Python (pytest) and TypeScript (Jest/Vitest/Playwright).

test-levels

18
from georgekhananaev/claude-skills-vault

This skill explains the 3 test levels (Unit, Integration, E2E) using the "Building a Car" analogy and provides guidance on when to use each type. Includes project-specific Playwright examples.