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

Install

bash
pip install "motor>=3.3"

requirements.txt:

text
motor==3.6.0
pymongo[srv]==4.10.1

Motor depends on PyMongo—keep versions compatible per Motor release notes.

AsyncIOMotorClient

motor_demo.py:

Code explanation:

  • await on every I/O call—same filter/update dicts as PyMongo
  • AsyncIOMotorClient is not a context manager; call close() 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

ApproachWhen
Motor + async defMany concurrent I/O-bound requests, single event loop
PyMongo + def routesSimpler stack, moderate traffic, sync FastAPI style — chapter 20
PyMongo in run_in_executorLegacy 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

python
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.