motor
Async Python driver for MongoDB — provides coroutine-based async API over pymongo for use with asyncio and Tornado. motor 3.x features: AsyncIOMotorClient for connection, AsyncIOMotorDatabase and AsyncIOMotorCollection for operations, same query API as pymongo (find/insert/update/delete/aggregate), async cursor with async for iteration, async change streams, async transactions, AsyncIOMotorGridFS, compatibility with FastAPI and Starlette, and motor.frameworks.tornado for Tornado framework.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
Async MongoDB driver. Same security considerations as pymongo. TLS: AsyncIOMotorClient(tls=True). NoSQL injection risk with user-controlled query filters. Store connection URL in environment variables. MongoDB ACL for collection-level permissions.
⚡ Reliability
Best When
FastAPI, Starlette, or asyncio applications needing MongoDB — motor is the official async MongoDB driver with identical API to pymongo.
Avoid When
Synchronous code (use pymongo), non-asyncio frameworks, or simple scripts.
Use Cases
- • Agent async MongoDB — from motor.motor_asyncio import AsyncIOMotorClient; client = AsyncIOMotorClient('mongodb://localhost:27017'); db = client['mydb']; async def insert_doc(data): result = await db.documents.insert_one(data); return result.inserted_id — async insert; agent uses MongoDB in async FastAPI or asyncio application
- • Agent async query — async def get_active_users(): cursor = db.users.find({'status': 'active'}, projection={'name': 1, 'email': 1}).sort('name', 1).limit(100); return [doc async for doc in cursor] — async iteration; agent queries MongoDB with async for loop on cursor; cursor methods (sort, limit, skip) are synchronous; await on terminal operations
- • Agent async aggregation — async def aggregate_data(): pipeline = [{'$match': {'active': True}}, {'$group': {'_id': '$category', 'total': {'$sum': '$amount'}}}]; cursor = db.sales.aggregate(pipeline); return await cursor.to_list(length=None) — async aggregation; agent runs analytics; to_list(None) materializes all results
- • Agent FastAPI integration — from fastapi import FastAPI; from motor.motor_asyncio import AsyncIOMotorClient; app = FastAPI(); @app.on_event('startup'); async def startup(): app.mongodb_client = AsyncIOMotorClient(settings.MONGODB_URL); app.mongodb = app.mongodb_client[settings.DB_NAME]; @app.get('/items'); async def list_items(db=Depends(get_db)): return await db.items.find({}).to_list(100) — FastAPI; standard motor+FastAPI pattern
- • Agent async change streams — async def watch_changes(): async with db.documents.watch() as stream: async for change in stream: await handle_change(change) — async watch; agent monitors MongoDB collection for real-time changes with async iteration; requires replica set
Not For
- • Synchronous code — use pymongo for synchronous applications; motor adds async overhead to sync code
- • Non-asyncio frameworks — motor supports asyncio and Tornado; for other async frameworks check compatibility
- • Simple scripts — pymongo is simpler for synchronous scripts; motor adds async boilerplate
Interface
Authentication
Same auth as pymongo: SCRAM-SHA-256, X.509, AWS IAM, via connection URL.
Pricing
motor is Apache 2.0 licensed. Free for all use.
Agent Metadata
Known Gotchas
- ⚠ AsyncIOMotorClient per event loop — motor client binds to the running event loop; in FastAPI: create client at startup event, not at module level; if event loop changes (testing), must recreate client; agent code: use app lifecycle events (startup/shutdown) to create and close client; store on app.state
- ⚠ cursor methods are synchronous, terminal operations async — cursor = db.col.find({}); cursor.sort('field', 1).limit(10) are synchronous modifier methods (no await); await cursor.to_list(100) or async for doc in cursor: are async terminal operations; agent code: chain sync modifiers before awaiting; next(cursor) is sync — use await cursor.next() or async for
- ⚠ to_list(length) requires explicit limit — cursor.to_list(length=None) fetches ALL documents (memory issue for large collections); cursor.to_list(length=100) fetches up to 100; agent code: always specify reasonable length; for large result sets: use async for doc in cursor: to stream; avoid to_list(None) without filter
- ⚠ Transactions require replica set — await session.start_transaction() requires MongoDB replica set or Atlas; local mongod single node: rs.initiate() first; agent code: test with MongoDB Atlas or local replica set; TransactionError if not replica set; sessions and transactions same API as pymongo
- ⚠ close() not awaitable in all versions — client.close() in motor 3.x is synchronous; call in shutdown handler without await; motor 2.x had different close behavior; agent FastAPI: @app.on_event('shutdown') def shutdown(): app.mongodb_client.close() — sync close
- ⚠ Collection names are attributes not methods — db['collection'] and db.collection both work; db.collection is attribute access; db['my-collection'] for hyphenated names (not valid Python identifier); agent code: use db['collection-name'] for names with hyphens or other special chars; db.users and db['users'] are identical
Alternatives
Full Evaluation Report
Comprehensive deep-dive: security analysis, reliability audit, agent experience review, cost modeling, competitive positioning, and improvement roadmap for motor.
AI-powered analysis · PDF + markdown · Delivered within 30 minutes
Package Brief
Quick verdict, integration guide, cost projections, gotchas with workarounds, and alternatives comparison.
Delivered within 10 minutes
Score Monitoring
Get alerted when this package's AF, security, or reliability scores change significantly. Stay ahead of regressions.
Continuous monitoring
Scores are editorial opinions as of 2026-03-06.