0
0
FastapiHow-ToBeginner · 4 min read

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 await to 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 AsyncIOMotorClient instance per request instead of once on startup.
  • Not closing the client on shutdown, which can lead to resource leaks.
  • Forgetting to convert MongoDB ObjectId to 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 AsyncIOMotorClient for async MongoDB access.
  • Initialize the client once on app startup.
  • Close the client on app shutdown to free resources.
  • Always await Motor async calls.
  • Convert ObjectId to 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.