How to Use Motor with FastAPI for Async MongoDB Access
Use
AsyncIOMotorClient from the motor.motor_asyncio package to connect MongoDB asynchronously in FastAPI. Initialize the client on startup and close it on shutdown, then use async functions to perform database operations within your FastAPI routes.Syntax
To use Motor with FastAPI, you first import AsyncIOMotorClient from motor.motor_asyncio. Then create a client instance connected to your MongoDB URI. Use FastAPI's startup and shutdown events to manage the connection lifecycle. Access the database and collections asynchronously using Motor's async methods.
AsyncIOMotorClient: Async MongoDB client.app.on_event('startup'): Connect client on app start.app.on_event('shutdown'): Close client on app stop.- Async route functions use
awaitto query MongoDB.
python
from fastapi import FastAPI from motor.motor_asyncio import AsyncIOMotorClient app = FastAPI() @app.on_event("startup") async def startup_db_client(): app.mongodb_client = AsyncIOMotorClient("mongodb://localhost:27017") app.mongodb = app.mongodb_client.mydatabase @app.on_event("shutdown") async def shutdown_db_client(): app.mongodb_client.close()
Example
This example shows a FastAPI app connecting to MongoDB asynchronously using Motor. It defines a route to insert a document and another to fetch documents from a collection.
python
from fastapi import FastAPI from motor.motor_asyncio import AsyncIOMotorClient from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str description: str @app.on_event("startup") async def startup_db_client(): app.mongodb_client = AsyncIOMotorClient("mongodb://localhost:27017") app.mongodb = app.mongodb_client.testdb @app.on_event("shutdown") async def shutdown_db_client(): app.mongodb_client.close() @app.post("/items/") async def create_item(item: Item): document = item.dict() result = await app.mongodb.items.insert_one(document) return {"id": str(result.inserted_id)} @app.get("/items/") async def read_items(): items = [] cursor = app.mongodb.items.find() async for document in cursor: document["_id"] = str(document["_id"]) items.append(document) return items
Output
POST /items/ with JSON {"name": "Pen", "description": "Blue ink pen"} returns {"id": "<some_object_id>"}
GET /items/ returns list of inserted items with their ids as strings
Common Pitfalls
Common mistakes when using Motor with FastAPI include:
- Not awaiting async database calls, causing unexpected behavior.
- Creating a new
AsyncIOMotorClientinstance per request instead of once on startup. - Not closing the client on shutdown, which can lead to resource leaks.
- Forgetting to convert MongoDB
ObjectIdto string before returning JSON responses.
python
from fastapi import FastAPI from motor.motor_asyncio import AsyncIOMotorClient app = FastAPI() # Wrong: Creating client inside route (inefficient) @app.get("/wrong") async def wrong_way(): client = AsyncIOMotorClient("mongodb://localhost:27017") db = client.testdb item = await db.items.find_one() client.close() return item # Right: Create client once on startup @app.on_event("startup") async def startup_db_client(): app.mongodb_client = AsyncIOMotorClient("mongodb://localhost:27017") app.mongodb = app.mongodb_client.testdb @app.on_event("shutdown") async def shutdown_db_client(): app.mongodb_client.close()
Quick Reference
Tips for using Motor with FastAPI:
- Use
AsyncIOMotorClientfor async MongoDB access. - Initialize the client once on app startup.
- Close the client on app shutdown to free resources.
- Always
awaitMotor async calls. - Convert
ObjectIdto string before returning JSON.
Key Takeaways
Initialize AsyncIOMotorClient once during FastAPI startup and close it on shutdown.
Use async functions and await Motor calls to interact with MongoDB.
Convert MongoDB ObjectId to string before sending JSON responses.
Avoid creating a new AsyncIOMotorClient per request to prevent performance issues.
Use FastAPI event handlers to manage database connection lifecycle cleanly.