Loading...
Loading...
Use when reviewing or writing new SQL/SQLAlchemy queries, especially in `backend/app/services/`, `backend/app/models/`, or migration files. Catches missing tenant filters, N+1 queries, async-session misuse, and missing indexes before they reach production. Trigger when the user says "review this query", "check for N+1", "is this query safe", or modifies repo-layer code.
npx skill4agent add ibrahim-newaeon/stratum-ai-final-updates-dec-2025 db-query-reviewtenant_idWHERE tenant_id = :tenant_id# ❌ Bad
await db.execute(select(Event).where(Event.id == event_id))
# ✅ Good
await db.execute(select(Event).where(Event.id == event_id, Event.tenant_id == tenant_id))tenancy-auditor# ❌ Bad — sync session in async function
def get_user(db: Session, id: int): ...
# ❌ Bad — session held across network call
async with async_session() as db:
user = await db.get(User, id)
result = await external_api.fetch(user.email) # session still open!
user.last_synced = result.at
await db.commit()
# ✅ Good — close session before network, open new one for write
async with async_session() as db:
user = await db.get(User, id)
result = await external_api.fetch(user.email)
async with async_session() as db:
user = await db.get(User, id)
user.last_synced = result.at
await db.commit()# ❌ Bad
segments = (await db.scalars(select(Segment))).all()
for s in segments:
members = (await db.scalars(select(Member).where(Member.segment_id == s.id))).all()
# ✅ Good — eager load
stmt = select(Segment).options(selectinload(Segment.members))
segments = (await db.scalars(stmt)).all()for x in result: query(x.related)selectinloadjoinedloadWHEREJOINORDER BY(tenant_id, status, created_at)grep -rn "Index\|index=True\|__table_args__" backend/app/models/<file>.py.limit(...)limitoffset.execution_options(stream_results=True)LIMIT/OFFSET# ❌ Catastrophic
await db.execute(delete(User))
# ✅ Good
await db.execute(delete(User).where(User.id == user_id, User.tenant_id == tenant_id))db.add(...)commit()db.execute(insert(Model).values([...]))bulk_insert_mappings# Inside psql connected to dev DB
EXPLAIN (ANALYZE, BUFFERS) <your-query>;Seq ScanBuffers: shared read=NRows Removed by FilterRowsmigration-auditor# Find all queries in the diff
git diff main...HEAD -- backend/app/ | grep -E '^\+' | grep -iE 'select\(|\.scalars\(|\.execute\(|insert\(|update\(|delete\('
# Find loops with queries inside (N+1 candidates)
git diff main...HEAD -- backend/app/ | grep -B 2 -A 5 -E '^\+[[:space:]]*for ' | grep -E 'await.*execute|await.*scalars'
# Find sessions held across awaits (async-session misuse)
grep -rn "async with .*session" backend/app/ | head| Pattern | Why it's risky |
|---|---|
| Almost always N+1 |
| Unbounded result set |
| Index can't be used unless there's a functional index |
| Postgres often can't use either |
| Same — kills index usage on |
| Sequential scan unless you have a trigram index |
| Subquery in SELECT clause | Often an N+1 in disguise |
migration-auditortenancy-auditormigration-auditorCONCURRENTLY