Motor Async Driver (Optional)
Introduction
Motor is the official async wrapper around PyMongo. It fits FastAPI async def routes and asyncio services without blocking the event loop. This optional chapter shows AsyncIOMotorClient, async CRUD, and when to pick Motor over sync PyMongo in a thread pool.
Prerequisites
- PyMongo Basics
- PyMongo With FastAPI
- FastAPI async database
pip install motor
Install
pip install "motor>=3.3"requirements.txt:
motor==3.6.0
pymongo[srv]==4.10.1Motor depends on PyMongo—keep versions compatible per Motor release notes.
AsyncIOMotorClient
motor_demo.py:
Code explanation:
awaiton every I/O call—same filter/update dicts as PyMongoAsyncIOMotorClientis not a context manager; callclose()on shutdown
FastAPI Lifespan With Motor
app/db/mongo.py:
app/main.py lifespan:
Async Route Example
Use async def only when the route awaits Motor (or other async I/O). CPU-heavy work still belongs in a thread pool.
Motor vs Sync PyMongo
| Approach | When |
|---|---|
Motor + async def | Many concurrent I/O-bound requests, single event loop |
PyMongo + def routes | Simpler stack, moderate traffic, sync FastAPI style — chapter 20 |
PyMongo in run_in_executor | Legacy sync code in async app without rewriting |
Tip
Default recommendation
Start with sync PyMongo and def routes unless profiling shows event-loop blocking. Motor adds async complexity; both are production-ready.
Transactions With Motor
async with await client.start_session() as session:
async with session.start_transaction():
await orders.insert_one({"total": 100}, session=session)
await inventory.update_one(
{"sku": "ABC"},
{"$inc": {"qty": -1}},
session=session,
)
await session.commit_transaction()Requires replica set — Schema Validation and Transactions.
FAQ
Beanie instead of Motor?
Beanie builds ODM models on Motor. Use it when you want Pydantic document classes; this track stays driver-level.
Can I mix Motor and PyMongo?
Share one cluster but avoid two clients per process unless you know why—prefer one AsyncIOMotorClient.
Motor with Flask?
Flask is sync-first; use PyMongo or run Motor inside an async worker (Quart, ASGI mount)—not typical Flask.
Does Motor support Change Streams?
Yes: await collection.watch() — same concepts as PyMongo watch().
Performance vs PyMongo?
Similar wire protocol; async helps concurrency, not single-query speed. Index and schema design matter more — Indexes.