advanced-alchemy
Auto-activate for alembic/, alembic.ini, advanced_alchemy imports, SQLAlchemyAsyncRepositoryService, SQLAlchemyAsyncConfig, UUIDAuditBase, repository_type, service_class, or web framework Advanced Alchemy extensions. Use when working with Advanced Alchemy ORM models, repositories
What it does
Advanced Alchemy
Match-Your-Framework — read first
advanced-alchemy ships first-party extensions for five web frameworks. If your project uses one of these, jump directly to the matching integration guide and skip the others:
- Litestar —
SQLAlchemyPluginwith full DI, session store, CLI. The rest of this SKILL.md covers Litestar by default; also seereferences/litestar_plugin.md. - FastAPI →
references/fastapi-integration.md—AdvancedAlchemy(config=..., app=app),Depends(alchemy.provide_session())DI,provide_service()/provide_filters(), Alembic CLI viaassign_cli_group. - Flask →
references/flask-integration.md—AdvancedAlchemy(config=..., app=app)orinit_app()factory, pull-basedalchemy.get_sync_session(), async-via-portal. - Sanic →
references/sanic-integration.md—AdvancedAlchemy(sqlalchemy_config=..., sanic_app=app)(note:sqlalchemy_config=kwarg, notconfig=), sanic-ext DI,request.ctxsessions. - Starlette →
references/starlette-integration.md—AdvancedAlchemy(config=..., app=app),request.statesession access, lifespan wrapping.
Shared topics that apply to every framework live in references/commit-modes.md (commit_mode="manual" / "autocommit" / "autocommit_include_redirect") and references/multi-database.md (bind-key pattern). Read the framework guide first, then those for depth.
The rest of this SKILL.md covers framework-agnostic topics: base classes, repositories, services, filters, custom types, caching, replicas, operations, and Alembic migrations.
Overview
Advanced Alchemy is NOT a raw ORM — it is a service/repository layer built on top of SQLAlchemy 2.0+ with opinionated base classes, audit mixins, and deep framework integrations (Litestar, FastAPI, Flask, Sanic). It provides:
- Base models with automatic
id,created_at,updated_atfields - Repository pattern for type-safe async CRUD
- Service layer with lifecycle hooks (
to_model_on_create,to_model_on_update) - Framework plugins for automatic session/transaction management
- Custom types:
EncryptedString,FileObject,DateTimeUTC,GUID - Alembic integration for migrations via CLI
Quick Reference
Base Classes
| Base Class | PK Type | Audit Columns | When to Use |
|---|---|---|---|
UUIDAuditBase | UUID v4 | created_at, updated_at | Default choice for most models |
UUIDBase | UUID v4 | None | Lookup tables, tags, no audit needed |
UUIDv7AuditBase | UUID v7 | created_at, updated_at | Time-sortable IDs (preferred over v6) |
BigIntAuditBase | BigInt auto-increment | created_at, updated_at | Legacy systems, integer PKs |
NanoidAuditBase | Nanoid string | created_at, updated_at | URL-friendly short IDs |
DeclarativeBase | None (define yourself) | None | Full schema control |
Repository Pattern
| Repository | Purpose |
|---|---|
SQLAlchemyAsyncRepository[Model] | Standard async CRUD |
SQLAlchemyAsyncSlugRepository[Model] | CRUD + automatic slug generation |
SQLAlchemyAsyncQueryRepository | Complex read-only queries (no model_type) |
Service Layer
| Service | Purpose |
|---|---|
SQLAlchemyAsyncRepositoryService[Model] | Full CRUD with lifecycle hooks |
SQLAlchemyAsyncRepositoryReadService[Model] | Read-only (list, get, count, exists) |
Key lifecycle hooks: to_model_on_create, to_model_on_update, to_model_on_upsert.
Custom Types
| Type | Purpose | Notes |
|---|---|---|
FileObject | Object storage with lifecycle hooks | Tracks file state across session; auto-deletes on row delete via StoredObject tracker |
PasswordHash | Hashed password storage | Supports Argon2, Passlib, and Pwdlib backends; hashes on assignment |
EncryptedString | Transparent AES encryption at rest | Requires ENCRYPTION_KEY in config |
UUID6 / UUID7 | Time-sortable UUID variants | UUID7 preferred — monotonic ordering with millisecond timestamp prefix |
DateTimeUTC | Timezone-aware UTC datetime | Stores as UTC; raises on naive datetimes |
Repository Service Layer
SQLAlchemyAsyncRepositoryService is the primary service base class. Key behaviors:
- Dict-to-model conversion: pass raw
dicttocreate(),update(),upsert()— the service converts viato_model_on_create/to_model_on_updatelifecycle hooks before persistence - Bulk operations:
add_many(data),update_many(data),delete_many(filters)— batched in a single transaction; prefer over calling single-row methods in a loop - Lifecycle hooks:
to_model_on_create,to_model_on_update,to_model_on_upsert— override to transform input data, hash passwords, normalize strings, etc.
Mixins
| Mixin | Fields Added | When to Use |
|---|---|---|
AuditMixin | created_at, updated_at, created_by, updated_by | Any model needing a full audit trail (who + when) |
SlugMixin | slug (auto-generated) | URL-friendly identifiers derived from another field |
UniqueMixin | get_or_create class method | Idempotent inserts for lookup/reference tables |
SentinelMixin | _sentinel version column | Optimistic locking; raises ConflictError on stale writes |
Litestar Integration
Use SQLAlchemyPlugin (composite of SQLAlchemyInitPlugin + SQLAlchemySerializationPlugin) for full integration:
SQLAlchemyPlugin: registers session provider, transaction middleware, and ORM type encoders in one callSQLAlchemyDTO: generates Litestar DTOs directly from ORM models withinclude/excludefield control- Type encoders: automatic serialization of
datetime,UUID,Decimal,Enum, and custom column types - Exception handling:
RepositoryError,ConflictError, andNotFoundErrormap to HTTP 409/404 via built-in exception handlers — register withapp.exception_handlers
Code Style
__slots__on non-model classes,Mapped[]typing for all columnsT | Nonefor optional fields (PEP 604 unions, neverOptional[T])- Full type annotations on all function signatures
- Inner
Repoclass pattern inside service definitions - Prefer
advanced_alchemy.*imports; avoid deprecatedlitestar.plugins.sqlalchemypaths from __future__ import annotationsrule — Advanced Alchemy model modules avoidfrom __future__ import annotationsbecause SQLAlchemy 2.0Mapped[...]columns are introspected at class-creation time. Consumer application modules (handlers, services, tests) MAY and typically SHOULD use it — canonical Litestar apps use it in 100+ files.
Workflow
Step 1: Define the Model
Choose the appropriate base class from the quick reference table. Use UUIDAuditBase unless you have a specific reason not to. Define columns with Mapped[] typing.
Step 2: Create the Repository
Create a repository class with model_type set to your model. Use SQLAlchemyAsyncRepository for standard CRUD, SQLAlchemyAsyncSlugRepository if the model uses SlugKey.
Step 3: Build the Service
Create a service class with an inner Repo class. Set match_fields for upsert logic. Add lifecycle hooks (to_model_on_create, to_model_on_update) for business logic transformations.
Step 4: Wire into Framework
Use the framework plugin (Litestar, FastAPI, Flask, Sanic) to inject sessions and register the service as a dependency.
Step 5: Generate Migration
Run alembic revision --autogenerate -m "description" to create the migration, then review and apply with alembic upgrade head.
Guardrails
- Always use the service layer for business logic — never put validation, hashing, or transformation logic directly in route handlers or repositories
- Repositories are for data access only — no business rules, no side effects beyond database operations
- Never bypass the service layer to call repository methods directly from handlers
- Always set
match_fieldson services that useupsert()to avoid duplicate-key errors - Use
schema_dump()to convert DTOs (Pydantic/msgspec/attrs) before passing to service methods - Prefer
UUIDAuditBaseas default base class — only deviate when you have a concrete reason - Use
advanced_alchemy.*imports — the oldlitestar.plugins.sqlalchemypaths are deprecated - Model modules avoid
from __future__ import annotations— SQLAlchemy 2.0 needs the realMapped[...]type at class-creation time. Consumer modules (handlers, services, tests) MAY use it.
Validation Checkpoint
Before delivering code, verify:
- Model inherits from an Advanced Alchemy base class (not raw
DeclarativeBasefrom SQLAlchemy) - All columns use
Mapped[]type annotations - Service has an inner
Repoclass withmodel_typeset - Business logic lives in service lifecycle hooks, not in route handlers
- Imports come from
advanced_alchemy.*, not deprecated paths - Model module does NOT use
from __future__ import annotations(consumer modules may)
Example
A complete Tag entity with model, repository, and service:
"""Tag domain — model, repository, and service."""
from advanced_alchemy.base import UUIDAuditBase
from advanced_alchemy.repository import SQLAlchemyAsyncRepository
from advanced_alchemy.service import SQLAlchemyAsyncRepositoryService
from sqlalchemy.orm import Mapped, mapped_column
class Tag(UUIDAuditBase):
"""Tag model with audit trail."""
__tablename__ = "tag"
name: Mapped[str] = mapped_column(unique=True)
description: Mapped[str | None] = mapped_column(default=None)
class TagRepository(SQLAlchemyAsyncRepository[Tag]):
"""Data access for tags."""
model_type = Tag
class TagService(SQLAlchemyAsyncRepositoryService[Tag]):
"""Business logic for tags."""
class Repo(SQLAlchemyAsyncRepository[Tag]):
model_type = Tag
repository_type = Repo
match_fields = ["name"]
async def to_model_on_create(self, data):
"""Normalize tag name before creation."""
if isinstance(data, dict) and "name" in data:
data["name"] = data["name"].strip().lower()
return data
</example>
References Index
Choosing between
advanced-alchemyandsqlspec:advanced-alchemy(this skill) gives you an opinionated ORM service layer withUUIDAuditBase, lifecycle hooks, repository / service / Alembic integration, andOffsetPagination[T]out of the box — pick it when you want a complete CRUD surface with attribute-style row access and you're happy inside the SQLAlchemy ecosystem.sqlspecgives you direct SQL control, 15+ driver adapters (asyncpg, oracledb, DuckDB, BigQuery, SQLite, and more), Arrow-native result streams for analytics, and a builder API when you need it — pick it when you want explicit SQL, heterogeneous database backends, or Arrow integration. Both skills integrate with Litestar via first-party plugins; see../sqlspec/SKILL.mdfor the raw-SQL / multi-adapter path.
For detailed guides and code examples, refer to the following documents in references/:
- Models Base classes, mixins, special types, relationships, PII tracking, and deferred loading.
- Repositories Async repository variants, configuration, slug repos, and query repos.
- Services Service layer, lifecycle hooks, composite services, filtering, and pagination.
- Litestar Plugin SQLAlchemy plugin config, DTOs, dependency injection, and session management.
- Migrations Alembic integration, CLI commands, metadata registry, and multi-database support.
- Types Complete catalog of custom column types: EncryptedString, FileObject, DateTimeUTC, GUID, PasswordHash, ColorType, and more.
- Base Classes Declarative base classes, UUID/BigInt/Nanoid variants, audit mixins, SlugKey, UniqueMixin, metadata registry, and custom base creation.
- Filters Filter system, pagination, SearchFilter, CollectionFilter, BeforeAfter, OrderBy, LimitOffset, and frontend integration patterns.
- Framework Integrations FastAPI, Flask, Starlette, and Sanic plugin setup, session management, and feature comparison across frameworks.
- Caching Dogpile.cache integration, CacheConfig, CacheManager API, automatic cache invalidation via session events, version-based list cache keys, singleflight stampede protection, and serialization.
- Read Replicas Read/write routing, RoutingConfig, engine groups, RoundRobinSelector/RandomSelector, sticky-after-write consistency, context managers for explicit routing, and RoutingAsyncSessionMaker.
- Storage (obstore) FileObject and StoredObject types, ObstoreBackend and FSSpecBackend configuration (S3, GCS, Azure, local), StorageRegistry, presigned URL generation, automatic file lifecycle via session tracker, and Pydantic integration.
- Operations, Listeners, Serialization
OnConflictUpsert/MergeStatementdialect-aware upsert building blocks, session event listeners (FileObject, cache invalidation,touch_updated_timestamp), and the msgspec-firstencode_json/decode_jsonused across the library.
Official References
- https://advanced-alchemy.litestar.dev/latest/
- https://advanced-alchemy.litestar.dev/latest/usage/services.html
- https://advanced-alchemy.litestar.dev/latest/usage/cli.html
- https://advanced-alchemy.litestar.dev/latest/usage/modeling/types.html
- https://advanced-alchemy.litestar.dev/latest/reference/types.html
- https://advanced-alchemy.litestar.dev/latest/changelog.html
- https://docs.litestar.dev/2/release-notes/changelog.html
- https://docs.sqlalchemy.org/en/20/orm/quickstart.html
Shared Styleguide Baseline
- Use shared styleguides for generic language/framework rules to reduce duplication in this skill.
- General Principles
- Python
- Litestar
- Keep this skill focused on tool-specific workflows, edge cases, and integration details.
Capabilities
Install
Quality
deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 7 github stars · SKILL.md body (14,789 chars)