
Sqlalchemy 2 0
- 2 installs
- 404 repo stars
- Updated August 5, 2026
- aiskillstore/marketplace
sqlalchemy-2-0 is a Claude skill that provides SQLAlchemy 2.0+ async ORM patterns for type-safe models, CRUD, relationships, and queries in Python.
About
sqlalchemy-2-0 is a reference skill for building database backends with the SQLAlchemy 2.0+ async ORM. It provides patterns for type-safe models using Mapped annotations, async CRUD operations, one-to-many and many-to-many relationships, eager relationship loading, and pagination. A developer uses it when building an API or data service with async database access in Python.
- Reference for SQLAlchemy 2.0+ async ORM with type-safe models
- Covers CRUD, relationships, eager loading, and pagination patterns
- Uses async_sessionmaker and Mapped type annotations
Sqlalchemy 2 0 by the numbers
- 2 all-time installs (skills.sh)
- Ranked #743 of 911 Databases skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
sqlalchemy-2-0 capabilities & compatibility
- Capabilities
- database modeling · api development · orm queries
- Works with
- postgres
- Use cases
- database · api development
What sqlalchemy-2-0 says it does
Modern async ORM with type-safe models and efficient queries
Building database backends, APIs, data services with async support
#### Annotated Type-Safe Models (Recommended)
npx skills add https://github.com/aiskillstore/marketplace --skill sqlalchemy-2-0Add your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 404 |
| Last updated | August 5, 2026 |
| Repository | aiskillstore/marketplace ↗ |
What it does
Build an async, type-safe database backend in Python using SQLAlchemy 2.0+ ORM patterns.
Who is it for?
Python developers building async database backends, APIs, or data services with SQLAlchemy.
When should I use this skill?
When building database backends, APIs, or data services that need async SQLAlchemy support.
What you get
Correct async SQLAlchemy 2.0 models, sessions, relationships, and queries are written for the backend.
- Async SQLAlchemy models
- CRUD functions
- Relationship and query patterns
Files
SQLAlchemy 2.0+ Skill
Quick Start
Basic Setup
from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine, AsyncSession
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
import asyncio
# Base class for models
class Base(AsyncAttrs, DeclarativeBase):
pass
# Async engine
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
# Session factory
async_session = async_sessionmaker(engine, expire_on_commit=False)
# Example model
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50))
email: Mapped[str] = mapped_column(String(100))Basic CRUD Operations
async def create_user(name: str, email: str) -> User:
async with async_session() as session:
async with session.begin():
user = User(name=name, email=email)
session.add(user)
await session.flush() # Get the ID
return user
async def get_user(user_id: int) -> User | None:
async with async_session() as session:
result = await session.execute(select(User).where(User.id == user_id))
return result.scalar_one_or_none()
async def update_user_email(user_id: int, new_email: str) -> bool:
async with async_session() as session:
result = await session.execute(
update(User).where(User.id == user_id).values(email=new_email)
)
await session.commit()
return result.rowcount > 0Common Patterns
Models
Annotated Type-Safe Models (Recommended)
from typing_extensions import Annotated
from typing import List, Optional
# Reusable column types
intpk = Annotated[int, mapped_column(primary_key=True)]
str50 = Annotated[str, mapped_column(String(50))]
created_at = Annotated[datetime, mapped_column(insert_default=func.now())]
class Post(Base):
__tablename__ = "posts"
id: Mapped[intpk]
title: Mapped[str50]
content: Mapped[str] = mapped_column(Text)
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
created: Mapped[created_at]
# Relationships
author: Mapped["User"] = relationship(back_populates="posts")
tags: Mapped[List["Tag"]] = relationship(secondary="post_tags")Classic Style Models
class Post(Base):
__tablename__ = "posts"
id = mapped_column(Integer, primary_key=True)
title = mapped_column(String(50))
content = mapped_column(Text)
author_id = mapped_column(ForeignKey("users.id"))
author = relationship("User", back_populates="posts")Relationships
One-to-Many
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
posts: Mapped[List["Post"]] = relationship(
back_populates="author",
cascade="all, delete-orphan"
)
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
author: Mapped["User"] = relationship(back_populates="posts")Many-to-Many
association_table = Table(
"post_tags",
Base.metadata,
Column("post_id", ForeignKey("posts.id"), primary_key=True),
Column("tag_id", ForeignKey("tags.id"), primary_key=True)
)
class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
tags: Mapped[List["Tag"]] = relationship(
secondary=association_table,
back_populates="posts"
)
class Tag(Base):
__tablename__ = "tags"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50), unique=True)
posts: Mapped[List["Post"]] = relationship(
secondary=association_table,
back_populates="tags"
)Queries
Basic Select
from sqlalchemy import select, and_, or_
# Get all users
async def get_all_users():
async with async_session() as session:
result = await session.execute(select(User))
return result.scalars().all()
# Filter with conditions
async def get_users_by_name(name: str):
async with async_session() as session:
stmt = select(User).where(User.name.ilike(f"%{name}%"))
result = await session.execute(stmt)
return result.scalars().all()
# Complex conditions
async def search_users(name: str = None, email: str = None):
async with async_session() as session:
conditions = []
if name:
conditions.append(User.name.ilike(f"%{name}%"))
if email:
conditions.append(User.email.ilike(f"%{email}%"))
if conditions:
stmt = select(User).where(and_(*conditions))
else:
stmt = select(User)
result = await session.execute(stmt)
return result.scalars().all()Relationship Loading
from sqlalchemy.orm import selectinload, joinedload
# Eager load relationships
async def get_posts_with_author():
async with async_session() as session:
stmt = select(Post).options(selectinload(Post.author))
result = await session.execute(stmt)
return result.scalars().all()
# Joined loading for single relationships
async def get_post_with_tags(post_id: int):
async with async_session() as session:
stmt = select(Post).options(
joinedload(Post.author),
selectinload(Post.tags)
).where(Post.id == post_id)
result = await session.execute(stmt)
return result.scalar_one_or_none()Pagination
async def get_posts_paginated(page: int, size: int):
async with async_session() as session:
offset = (page - 1) * size
stmt = select(Post).offset(offset).limit(size).order_by(Post.created.desc())
result = await session.execute(stmt)
return result.scalars().all()Aggregations
from sqlalchemy import func
async def get_user_post_count():
async with async_session() as session:
stmt = (
select(User.name, func.count(Post.id).label("post_count"))
.join(Post)
.group_by(User.id, User.name)
.order_by(func.count(Post.id).desc())
)
result = await session.execute(stmt)
return result.all()Sessions Management
Context Manager Pattern
async def create_post(title: str, content: str, author_id: int):
async with async_session() as session:
async with session.begin():
post = Post(title=title, content=content, author_id=author_id)
session.add(post)
return postDependency Injection (FastAPI)
from fastapi import Depends
async def get_db_session():
async with async_session() as session:
try:
yield session
finally:
await session.close()
async def create_user_endpoint(
user_data: UserCreate,
session: AsyncSession = Depends(get_db_session)
):
user = User(**user_data.dict())
session.add(user)
await session.commit()
await session.refresh(user)
return userScoped Sessions
from sqlalchemy.ext.asyncio import async_scoped_session
import asyncio
# Create scoped session
async_session_scope = async_scoped_session(
async_sessionmaker(engine, expire_on_commit=False),
scopefunc=asyncio.current_task
)
# Use in application
async def some_function():
session = async_session_scope()
# Use session normally
await session.commit()Advanced Patterns
Write-Only Relationships (Memory Efficient)
from sqlalchemy.orm import WriteOnlyMapped
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
posts: WriteOnlyMapped["Post"] = relationship()
async def get_user_posts(user_id: int):
async with async_session() as session:
user = await session.get(User, user_id)
if user:
# Explicit select for collection
stmt = select(Post).where(Post.author_id == user_id)
result = await session.execute(stmt)
return result.scalars().all()
return []Custom Session Classes
class AsyncSessionWithDefaults(AsyncSession):
async def execute_with_defaults(self, statement, **kwargs):
# Add default options
return await self.execute(statement, **kwargs)
# Use custom session
async_session = async_sessionmaker(
engine,
class_=AsyncSessionWithDefaults,
expire_on_commit=False
)Connection Routing
class RoutingSession(Session):
def get_bind(self, mapper=None, clause=None, **kw):
if mapper and issubclass(mapper.class_, ReadOnlyModel):
return read_engine
return write_engine
class AsyncRoutingSession(AsyncSession):
sync_session_class = RoutingSessionRaw SQL
from sqlalchemy import text
async def run_raw_sql():
async with async_session() as session:
result = await session.execute(text("SELECT COUNT(*) FROM users"))
count = result.scalar()
return count
async def run_parameterized_query(user_id: int):
async with async_session() as session:
stmt = text("SELECT * FROM posts WHERE author_id = :user_id")
result = await session.execute(stmt, {"user_id": user_id})
return result.fetchall()Performance Tips
1. Use selectinload for collections: More efficient than lazy loading 2. Batch operations: Use add_all() for bulk inserts 3. Connection pooling: Configure pool size based on load 4. Index columns: Add indexes for frequently queried columns 5. Use streaming: For large result sets, use stream()
# Streaming large results
async def process_all_users():
async with async_session() as session:
result = await session.stream(select(User))
async for user in result.scalars():
# Process user without loading all into memory
await process_user(user)Requirements
uv add sqlalchemy[asyncio] # Core SQLAlchemy
uv add asyncpg # PostgreSQL async driver
# or
uv add aiosqlite # SQLite async driver
# or
uv add aiomysql # MySQL async driverDatabase URLs
- PostgreSQL:
postgresql+asyncpg://user:pass@localhost/db - SQLite:
sqlite+aiosqlite:///database.db - MySQL:
mysql+aiomysql://user:pass@localhost/db
Migration Integration
Use Alembic for database migrations:
# Generate migration
uv run alembic revision --autogenerate -m "Add users table"
# Apply migrations
uv run alembic upgrade head{
"skill": {
"name": "SQLAlchemy 2.0+",
"description": "Modern async ORM with type-safe models and efficient queries for building database backends, APIs, and data services with async support.",
"summary": "Build type-safe async database operations with SQLAlchemy 2.0 ORM patterns and examples.",
"icon": "🗄️",
"version": "1.0.0",
"author": "bossjones",
"license": "MIT",
"category": "data",
"tags": ["sqlalchemy", "orm", "async", "database", "python"],
"supported_tools": ["claude", "codex", "claude-code"]
},
"security_audit": {
"risk_level": "safe",
"is_blocked": false,
"safe_to_publish": true,
"summary": "This skill is a markdown documentation file containing SQLAlchemy 2.0 ORM examples. The static analyzer flagged 55 potential issues, but all are false positives. The scanner misinterpreted markdown code block backticks as shell execution, ORDER BY descending sorts (.desc()) as weak crypto, and standard SQL queries as reconnaissance. This is documentation-only content with no executable code.",
"static_findings_evaluation": [
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:13",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 13 contains the opening ```python markdown code fence. Backticks in markdown denote code blocks, not shell execution. This is standard documentation syntax."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:35",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 35 contains the closing ``` markdown code fence. Backticks in markdown denote code blocks, not shell execution."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:39",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 39 contains the opening ```python markdown code fence for a new code block containing Python async function examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:60",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 60 contains the closing ``` markdown code fence. Backticks in markdown denote code blocks."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:68",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 68 contains the opening ```python markdown code fence for annotated type-safe model examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:89",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 89 contains the closing ``` markdown code fence for the annotated models code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:93",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 93 contains the opening ```python markdown code fence for classic style model examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:103",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 103 contains the closing ``` markdown code fence."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:109",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 109 contains the opening ```python markdown code fence for one-to-many relationship examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:125",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 125 contains the closing ``` markdown code fence for the relationships code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:129",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 129 contains the opening ```python markdown code fence for many-to-many relationship examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:155",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 155 contains the closing ``` markdown code fence for the many-to-many code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:161",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 161 contains the opening ```python markdown code fence for query examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:193",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 193 contains the closing ``` markdown code fence for the basic select queries code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:197",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 197 contains the opening ```python markdown code fence for relationship loading examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:216",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 216 contains the closing ``` markdown code fence for the relationship loading code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:220",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 220 contains the opening ```python markdown code fence for pagination examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:227",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 227 contains the closing ``` markdown code fence for the pagination code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:231",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 231 contains the opening ```python markdown code fence for aggregation examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:244",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 244 contains the closing ``` markdown code fence for the aggregations code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:250",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 250 contains the opening ```python markdown code fence for context manager pattern examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:257",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 257 contains the closing ``` markdown code fence."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:261",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 261 contains the opening ```python markdown code fence for FastAPI dependency injection examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:280",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 280 contains the closing ``` markdown code fence for the dependency injection code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:284",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 284 contains the opening ```python markdown code fence for scoped sessions examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:299",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 299 contains the closing ``` markdown code fence for the scoped sessions code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:305",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 305 contains the opening ```python markdown code fence for write-only relationship examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:323",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 323 contains the closing ``` markdown code fence for the write-only relationships code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:327",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 327 contains the opening ```python markdown code fence for custom session class examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:339",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 339 contains the closing ``` markdown code fence for the custom sessions code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:343",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 343 contains the opening ```python markdown code fence for connection routing examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:352",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 352 contains the closing ``` markdown code fence for the connection routing code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:356",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 356 contains the opening ```python markdown code fence for raw SQL examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:370",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 370 contains the closing ``` markdown code fence for the raw SQL code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:375",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 375 contains the opening ```python markdown code fence for streaming large results examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:378",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 378 contains text within the streaming code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:380",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 380 contains text within the streaming code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:388",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 388 contains the closing ``` markdown code fence for the streaming code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:392",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 392 contains the opening ```bash markdown code fence for requirements installation."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:399",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 399 contains the closing ``` markdown code fence for the requirements code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:403",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 403 contains text listing database URL formats, not executable code."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:404",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 404 contains the opening ```python markdown code fence for migration integration examples."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:405",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 405 contains text within the migration code block."
},
{
"finding": "external_commands: Ruby/shell backtick execution at SKILL.md:411",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 411 contains the opening ```python markdown code fence for Alembic migration examples."
},
{
"finding": "sensitive: SQLite database file at SKILL.md:404",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 404 documents the SQLite connection string format: sqlite+aiosqlite:///database.db. This is standard documentation about database configuration, not sensitive data exposure."
},
{
"finding": "blocker: Weak cryptographic algorithm at SKILL.md:3",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 3 is the YAML frontmatter description field containing plain text about ORM features. No cryptographic algorithm is present."
},
{
"finding": "blocker: Weak cryptographic algorithm at SKILL.md:224",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 224 contains .order_by(Post.created.desc()) which is a SQL ORDER BY clause using DESC (descending) for sorting query results. This is not cryptographic code."
},
{
"finding": "blocker: Weak cryptographic algorithm at SKILL.md:240",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 240 contains .order_by(func.count(Post.id).desc()) which is a SQL ORDER BY clause using DESC (descending) to sort aggregation results. Not cryptographic code."
},
{
"finding": "blocker: System reconnaissance at SKILL.md:50",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 50 contains await session.execute(select(User).where(User.id == user_id)) which is a standard database SELECT query with WHERE clause. Normal ORM operation, not reconnaissance."
},
{
"finding": "blocker: System reconnaissance at SKILL.md:56",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 56 contains update(User).where(User.id == user_id).values(email=new_email) which is a standard SQL UPDATE query. Normal database operation."
},
{
"finding": "blocker: System reconnaissance at SKILL.md:97",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 97 contains mapped_column(Integer, primary_key=True) which defines a database column. Normal ORM model definition."
},
{
"finding": "blocker: System reconnaissance at SKILL.md:100",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 100 contains mapped_column(ForeignKey(\"users.id\")) which defines a foreign key relationship. Normal ORM model definition."
},
{
"finding": "blocker: System reconnaissance at SKILL.md:213",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 213 contains .where(Post.id == post_id) which is a standard SQL WHERE clause. Normal query filtering."
},
{
"finding": "blocker: System reconnaissance at SKILL.md:319",
"verdict": "false_positive",
"confidence": "high",
"reasoning": "Line 319 contains .where(Post.author_id == user_id) which is a standard SQL WHERE clause for filtering posts by author. Normal query."
}
],
"risk_factor_evidence": [],
"critical_findings": [],
"high_findings": [],
"medium_findings": [],
"low_findings": [],
"dangerous_patterns": [],
"files_scanned": 1,
"total_lines": 418
},
"content": {
"user_title": "Build async database operations with SQLAlchemy 2.0",
"value_statement": "This skill provides ready-to-use SQLAlchemy 2.0+ patterns for async database operations. It includes type-safe models, CRUD operations, relationships, and performance optimizations for building robust data services.",
"seo_keywords": [
"sqlalchemy",
"sqlalchemy 2.0",
"async orm",
"python database",
"type-safe models",
"async python",
"claude code",
"claude",
"codex",
"fastapi database"
],
"actual_capabilities": [
"Create async engine and session configuration for PostgreSQL, SQLite, and MySQL",
"Define type-safe SQLAlchemy models with annotated column types",
"Implement CRUD operations with async/await patterns",
"Configure one-to-many and many-to-many relationships with cascade options",
"Use selectinload and joinedload for efficient relationship loading",
"Integrate with FastAPI using dependency injection for session management"
],
"limitations": [
"Does not include database migration setup (see Alembic skill for migrations)",
"Does not provide connection pooling configuration examples",
"Does not cover raw SQL migration strategies or schema management",
"Does not include transaction retry logic or error handling patterns"
],
"use_cases": [
{
"target_user": "Backend Python developers",
"title": "Build async API backends",
"description": "Create FastAPI endpoints with async SQLAlchemy sessions for high-concurrency web services."
},
{
"target_user": "Data engineers",
"title": "Design type-safe data models",
"description": "Define validated ORM models with annotated columns for consistent database schemas."
},
{
"target_user": "Full-stack developers",
"title": "Optimize database queries",
"description": "Use eager loading and streaming patterns to reduce N+1 queries and memory usage."
}
],
"prompt_templates": [
{
"title": "Basic model setup",
"scenario": "Setting up async SQLAlchemy",
"prompt": "Show me how to create an async SQLAlchemy 2.0 engine and session factory for PostgreSQL with a User model that has id, name, and email fields."
},
{
"title": "Relationship queries",
"scenario": "Fetching related data",
"prompt": "Write a function that fetches a User with all their Posts loaded, using selectinload to avoid N+1 queries."
},
{
"title": "FastAPI integration",
"scenario": "Adding database to API",
"prompt": "Create a FastAPI dependency that provides an async SQLAlchemy session, properly handling cleanup with try/finally."
},
{
"title": "Custom session routing",
"scenario": "Read-write splitting",
"prompt": "Implement a custom AsyncRoutingSession that routes read-only models to a read replica database."
}
],
"output_examples": [
{
"input": "Create a User model with posts relationship and a function to get all users",
"output": [
"User model with posts relationship defined using List[Post] with cascade delete",
"get_all_users() async function using session.execute(select(User))",
"Result parsing with scalars().all() for efficient object loading"
]
}
],
"best_practices": [
"Use expire_on_commit=False to avoid unnecessary reloads after commits",
"Prefer selectinload over lazy loading for collections to prevent N+1 queries",
"Always close sessions properly using async with context managers"
],
"anti_patterns": [
"Avoid lazy loading in async contexts as it can cause connection leaks",
"Do not use sync sessions with async engines as this blocks the event loop",
"Avoid committing transactions inside nested context managers without proper scoping"
],
"faq": [
{
"question": "What databases support async SQLAlchemy?",
"answer": "PostgreSQL with asyncpg, SQLite with aiosqlite, and MySQL with aiomysql are fully supported async drivers."
},
{
"question": "How do I prevent N+1 queries with relationships?",
"answer": "Use selectinload() or joinedload() in your query options to eagerly load related data in a single query."
},
{
"question": "What is the difference between classic and annotated models?",
"answer": "Annotated models use Python type hints with mapped_column for better IDE support and type checking."
},
{
"question": "How do I handle sessions in FastAPI dependencies?",
"answer": "Create an async generator function that yields the session and closes it in a finally block."
},
{
"question": "Can I use raw SQL with async SQLAlchemy?",
"answer": "Yes, use sqlalchemy.text() to execute raw SQL with proper parameterized queries for security."
},
{
"question": "How do I stream large result sets?",
"answer": "Use session.stream(select(Model)) and iterate with async for to process records without loading all into memory."
}
]
}
}
{
"schema_version": "2.0",
"meta": {
"generated_at": "2026-01-16T20:02:07.263Z",
"slug": "bossjones-sqlalchemy-2-0",
"source_url": "https://github.com/bossjones/logging-lab/tree/main/.claude/skills/sqlalchemy",
"source_ref": "main",
"model": "claude",
"analysis_version": "3.0.0",
"source_type": "community",
"content_hash": "c8b436213c9152c2e7cb957325592863f433eeb168dc660e0013be6246f6b2e2",
"tree_hash": "3ab706662904682f20cd7f3c45f51f552e718aab59a6de6d669a27b807a8bbdd"
},
"skill": {
"name": "sqlalchemy-2-0",
"description": "Modern async ORM with type-safe models and efficient queries",
"summary": "Modern async ORM with type-safe models and efficient queries",
"icon": "🗄️",
"version": "1.0.0",
"author": "bossjones",
"license": "MIT",
"category": "data",
"tags": [
"sqlalchemy",
"orm",
"async",
"database",
"python"
],
"supported_tools": [
"claude",
"codex",
"claude-code"
],
"risk_factors": [
"external_commands",
"network",
"filesystem"
]
},
"security_audit": {
"risk_level": "safe",
"is_blocked": false,
"safe_to_publish": true,
"summary": "This skill is documentation-only content containing SQLAlchemy 2.0 ORM examples. All 131 static findings are false positives. The scanner misinterpreted markdown code fences as shell commands, SQL ORDER BY .desc() (descending sort) as weak crypto, and standard database queries as reconnaissance. No executable code, network calls, or credential access exists.",
"risk_factor_evidence": [
{
"factor": "external_commands",
"evidence": [
{
"file": "evaluation.json",
"line_start": 24,
"line_end": 30
},
{
"file": "evaluation.json",
"line_start": 30,
"line_end": 36
},
{
"file": "evaluation.json",
"line_start": 36,
"line_end": 42
},
{
"file": "evaluation.json",
"line_start": 42,
"line_end": 48
},
{
"file": "evaluation.json",
"line_start": 48,
"line_end": 54
},
{
"file": "evaluation.json",
"line_start": 54,
"line_end": 60
},
{
"file": "evaluation.json",
"line_start": 60,
"line_end": 66
},
{
"file": "evaluation.json",
"line_start": 66,
"line_end": 72
},
{
"file": "evaluation.json",
"line_start": 72,
"line_end": 78
},
{
"file": "evaluation.json",
"line_start": 78,
"line_end": 84
},
{
"file": "evaluation.json",
"line_start": 84,
"line_end": 90
},
{
"file": "evaluation.json",
"line_start": 90,
"line_end": 96
},
{
"file": "evaluation.json",
"line_start": 96,
"line_end": 102
},
{
"file": "evaluation.json",
"line_start": 102,
"line_end": 108
},
{
"file": "evaluation.json",
"line_start": 108,
"line_end": 114
},
{
"file": "evaluation.json",
"line_start": 114,
"line_end": 120
},
{
"file": "evaluation.json",
"line_start": 120,
"line_end": 126
},
{
"file": "evaluation.json",
"line_start": 126,
"line_end": 132
},
{
"file": "evaluation.json",
"line_start": 132,
"line_end": 138
},
{
"file": "evaluation.json",
"line_start": 138,
"line_end": 144
},
{
"file": "evaluation.json",
"line_start": 144,
"line_end": 150
},
{
"file": "evaluation.json",
"line_start": 150,
"line_end": 156
},
{
"file": "evaluation.json",
"line_start": 156,
"line_end": 162
},
{
"file": "evaluation.json",
"line_start": 162,
"line_end": 168
},
{
"file": "evaluation.json",
"line_start": 168,
"line_end": 174
},
{
"file": "evaluation.json",
"line_start": 174,
"line_end": 180
},
{
"file": "evaluation.json",
"line_start": 180,
"line_end": 186
},
{
"file": "evaluation.json",
"line_start": 186,
"line_end": 192
},
{
"file": "evaluation.json",
"line_start": 192,
"line_end": 198
},
{
"file": "evaluation.json",
"line_start": 198,
"line_end": 204
},
{
"file": "evaluation.json",
"line_start": 204,
"line_end": 210
},
{
"file": "evaluation.json",
"line_start": 210,
"line_end": 216
},
{
"file": "evaluation.json",
"line_start": 216,
"line_end": 222
},
{
"file": "evaluation.json",
"line_start": 222,
"line_end": 228
},
{
"file": "evaluation.json",
"line_start": 228,
"line_end": 246
},
{
"file": "evaluation.json",
"line_start": 246,
"line_end": 252
},
{
"file": "evaluation.json",
"line_start": 252,
"line_end": 258
},
{
"file": "evaluation.json",
"line_start": 258,
"line_end": 270
},
{
"file": "evaluation.json",
"line_start": 270,
"line_end": 282
},
{
"file": "SKILL.md",
"line_start": 13,
"line_end": 35
},
{
"file": "SKILL.md",
"line_start": 35,
"line_end": 39
},
{
"file": "SKILL.md",
"line_start": 39,
"line_end": 60
},
{
"file": "SKILL.md",
"line_start": 60,
"line_end": 68
},
{
"file": "SKILL.md",
"line_start": 68,
"line_end": 89
},
{
"file": "SKILL.md",
"line_start": 89,
"line_end": 93
},
{
"file": "SKILL.md",
"line_start": 93,
"line_end": 103
},
{
"file": "SKILL.md",
"line_start": 103,
"line_end": 109
},
{
"file": "SKILL.md",
"line_start": 109,
"line_end": 125
},
{
"file": "SKILL.md",
"line_start": 125,
"line_end": 129
},
{
"file": "SKILL.md",
"line_start": 129,
"line_end": 155
},
{
"file": "SKILL.md",
"line_start": 155,
"line_end": 161
},
{
"file": "SKILL.md",
"line_start": 161,
"line_end": 193
},
{
"file": "SKILL.md",
"line_start": 193,
"line_end": 197
},
{
"file": "SKILL.md",
"line_start": 197,
"line_end": 216
},
{
"file": "SKILL.md",
"line_start": 216,
"line_end": 220
},
{
"file": "SKILL.md",
"line_start": 220,
"line_end": 227
},
{
"file": "SKILL.md",
"line_start": 227,
"line_end": 231
},
{
"file": "SKILL.md",
"line_start": 231,
"line_end": 244
},
{
"file": "SKILL.md",
"line_start": 244,
"line_end": 250
},
{
"file": "SKILL.md",
"line_start": 250,
"line_end": 257
},
{
"file": "SKILL.md",
"line_start": 257,
"line_end": 261
},
{
"file": "SKILL.md",
"line_start": 261,
"line_end": 280
},
{
"file": "SKILL.md",
"line_start": 280,
"line_end": 284
},
{
"file": "SKILL.md",
"line_start": 284,
"line_end": 299
},
{
"file": "SKILL.md",
"line_start": 299,
"line_end": 305
},
{
"file": "SKILL.md",
"line_start": 305,
"line_end": 323
},
{
"file": "SKILL.md",
"line_start": 323,
"line_end": 327
},
{
"file": "SKILL.md",
"line_start": 327,
"line_end": 339
},
{
"file": "SKILL.md",
"line_start": 339,
"line_end": 343
},
{
"file": "SKILL.md",
"line_start": 343,
"line_end": 352
},
{
"file": "SKILL.md",
"line_start": 352,
"line_end": 356
},
{
"file": "SKILL.md",
"line_start": 356,
"line_end": 370
},
{
"file": "SKILL.md",
"line_start": 370,
"line_end": 375
},
{
"file": "SKILL.md",
"line_start": 375,
"line_end": 378
},
{
"file": "SKILL.md",
"line_start": 378,
"line_end": 380
},
{
"file": "SKILL.md",
"line_start": 380,
"line_end": 388
},
{
"file": "SKILL.md",
"line_start": 388,
"line_end": 392
},
{
"file": "SKILL.md",
"line_start": 392,
"line_end": 399
},
{
"file": "SKILL.md",
"line_start": 399,
"line_end": 403
},
{
"file": "SKILL.md",
"line_start": 403,
"line_end": 404
},
{
"file": "SKILL.md",
"line_start": 404,
"line_end": 405
},
{
"file": "SKILL.md",
"line_start": 405,
"line_end": 411
},
{
"file": "SKILL.md",
"line_start": 411,
"line_end": 417
}
]
},
{
"factor": "network",
"evidence": [
{
"file": "skill-report.json",
"line_start": 6,
"line_end": 6
}
]
},
{
"factor": "filesystem",
"evidence": [
{
"file": "skill-report.json",
"line_start": 6,
"line_end": 6
}
]
}
],
"critical_findings": [],
"high_findings": [],
"medium_findings": [],
"low_findings": [],
"dangerous_patterns": [],
"files_scanned": 3,
"total_lines": 1292,
"audit_model": "claude",
"audited_at": "2026-01-16T20:02:07.263Z"
},
"content": {
"user_title": "Build async database operations with SQLAlchemy 2.0",
"value_statement": "This skill provides ready-to-use SQLAlchemy 2.0+ patterns for async database operations. It includes type-safe models, CRUD operations, relationships, and performance optimizations for building robust data services.",
"seo_keywords": [
"sqlalchemy",
"sqlalchemy 2.0",
"async orm",
"python database",
"type-safe models",
"async python",
"claude code",
"claude",
"codex",
"fastapi database"
],
"actual_capabilities": [
"Create async engine and session configuration for PostgreSQL, SQLite, and MySQL",
"Define type-safe SQLAlchemy models with annotated column types",
"Implement CRUD operations with async/await patterns",
"Configure one-to-many and many-to-many relationships with cascade options",
"Use selectinload and joinedload for efficient relationship loading",
"Integrate with FastAPI using dependency injection for session management"
],
"limitations": [
"Does not include database migration setup (see Alembic skill for migrations)",
"Does not provide connection pooling configuration examples",
"Does not cover raw SQL migration strategies or schema management",
"Does not include transaction retry logic or error handling patterns"
],
"use_cases": [
{
"target_user": "Backend Python developers",
"title": "Build async API backends",
"description": "Create FastAPI endpoints with async SQLAlchemy sessions for high-concurrency web services."
},
{
"target_user": "Data engineers",
"title": "Design type-safe data models",
"description": "Define validated ORM models with annotated columns for consistent database schemas."
},
{
"target_user": "Full-stack developers",
"title": "Optimize database queries",
"description": "Use eager loading and streaming patterns to reduce N+1 queries and memory usage."
}
],
"prompt_templates": [
{
"title": "Basic model setup",
"scenario": "Setting up async SQLAlchemy",
"prompt": "Show me how to create an async SQLAlchemy 2.0 engine and session factory for PostgreSQL with a User model that has id, name, and email fields."
},
{
"title": "Relationship queries",
"scenario": "Fetching related data",
"prompt": "Write a function that fetches a User with all their Posts loaded, using selectinload to avoid N+1 queries."
},
{
"title": "FastAPI integration",
"scenario": "Adding database to API",
"prompt": "Create a FastAPI dependency that provides an async SQLAlchemy session, properly handling cleanup with try/finally."
},
{
"title": "Custom session routing",
"scenario": "Read-write splitting",
"prompt": "Implement a custom AsyncRoutingSession that routes read-only models to a read replica database."
}
],
"output_examples": [
{
"input": "Create a User model with posts relationship and a function to get all users",
"output": [
"User model with posts relationship defined using List[Post] with cascade delete",
"get_all_users() async function using session.execute(select(User))",
"Result parsing with scalars().all() for efficient object loading"
]
},
{
"input": "Set up async SQLAlchemy for PostgreSQL with type-safe annotated columns",
"output": [
"Async engine created with postgresql+asyncpg://user:pass@localhost/db",
"async_sessionmaker configured with expire_on_commit=False",
"User model using Annotated[int, mapped_column(primary_key=True)] pattern"
]
}
],
"best_practices": [
"Use expire_on_commit=False to avoid unnecessary reloads after commits",
"Prefer selectinload over lazy loading for collections to prevent N+1 queries",
"Always close sessions properly using async with context managers"
],
"anti_patterns": [
"Avoid lazy loading in async contexts as it can cause connection leaks",
"Do not use sync sessions with async engines as this blocks the event loop",
"Avoid committing transactions inside nested context managers without proper scoping"
],
"faq": [
{
"question": "What databases support async SQLAlchemy?",
"answer": "PostgreSQL with asyncpg, SQLite with aiosqlite, and MySQL with aiomysql are fully supported async drivers."
},
{
"question": "How do I prevent N+1 queries with relationships?",
"answer": "Use selectinload() or joinedload() in your query options to eagerly load related data in a single query."
},
{
"question": "What is the difference between classic and annotated models?",
"answer": "Annotated models use Python type hints with mapped_column for better IDE support and type checking."
},
{
"question": "How do I handle sessions in FastAPI dependencies?",
"answer": "Create an async generator function that yields the session and closes it in a finally block."
},
{
"question": "Can I use raw SQL with async SQLAlchemy?",
"answer": "Yes, use sqlalchemy.text() to execute raw SQL with proper parameterized queries for security."
},
{
"question": "How do I stream large result sets?",
"answer": "Use session.stream(select(Model)) and iterate with async for to process records without loading all into memory."
}
]
},
"file_structure": [
{
"name": "evaluation.json",
"type": "file",
"path": "evaluation.json",
"lines": 470
},
{
"name": "SKILL.md",
"type": "file",
"path": "SKILL.md",
"lines": 418
}
]
}
Related skills
FAQ
Which model style does sqlalchemy-2-0 recommend?
It recommends annotated type-safe models using Mapped and mapped_column with reusable Annotated column types.
Does it use async sessions?
Yes, it uses create_async_engine and async_sessionmaker with async with session blocks.