Learn Python with Talk Python's 270 hours of courses

Meet Beanie: A MongoDB ODM + Pydantic

Episode #349, published Sat, Jan 22, 2022, recorded Thu, Nov 18, 2021

This podcast episode you're listening to right now was delivered to you, in part, by MongoDB and Python powering our web apps and production processes. But if you're using pymongo, the native driver from MongoDB to talk to the server, you're doing it wrong. Basing your app on a foundation of exchanging raw dictionaries is a castle of sand. BTW, see the joke at the end of the show about this.

You should be using an ODM. This time we're talking about Beanie which is one of the exciting, new MongoDB Object Document Mappers which is based on Pydantic and is async-native. Join me as I discuss this project with its creator: Roman Right.

Watch this episode on YouTube
Play on YouTube
Watch the live stream version

Episode Deep Dive

Guest Introduction and Background

Roman Wright is a seasoned Python developer and creator of Beanie, an async-native ODM (Object Document Mapper) for MongoDB built on top of Pydantic. He has extensive experience with Django, FastAPI, and modern Python tooling. During this episode, Roman shares how he came to write Beanie—initially just to fill a need for an async ODM—and how working on production applications with Beanie helps him refine and evolve the library.

What to Know If You're New to Python

If you're newer to Python and want to follow along with the conversations about async, data modeling, and frameworks mentioned in the show, here are a few quick points:

  • Make sure you have a basic grasp of Python classes and importing libraries.
  • Know that “async” (asynchronous) code lets your program handle multiple tasks without waiting for them to finish in order.
  • Understanding type hints (Python typing) can help when working with libraries like Pydantic.
  • MongoDB interacts nicely with Python, but typically you’ll want an ODM (Object Document Mapper) like Beanie to handle data models and queries more cleanly.

Talk Python Runs on Beanie & MongoDB

Did you know that the very site you’re on—talkpython.fm—is powered by Beanie and MongoDB? We’ve found this stack to be both extremely performant and a joy to develop on, and it truly showcases how well Beanie integrates into a real-world production environment.

Key Points and Takeaways

  1. Beanie + Pydantic for MongoDB Beanie stands out by combining Pydantic’s data validation and parsing with MongoDB’s async driver, Motor. This enables a well-structured, type-safe approach, rather than just sending raw Python dictionaries to the database. You still get powerful features from PyMongo and Motor but wrapped in a more Pythonic, validated model layer.
  2. ODM vs. “Raw Dictionaries” Relying on raw dictionaries exchanged with MongoDB can lead to chaos—less type safety and little structure. An ODM like Beanie automatically enforces consistency and validates data, preventing subtle bugs and data mismatches. This ensures your application’s data layer is far less fragile.
  3. Async and Await for High Performance Beanie builds directly on MongoDB’s official async driver, Motor, allowing truly non-blocking database operations in frameworks like FastAPI and async Flask. Async can significantly improve scalability, especially for I/O-bound tasks.
    • Links and Tools:
      • FastAPI
      • Flask (with async considerations)
      • Unsync (mentioned for integrating async + sync)
  4. Field Defaults and Event-Based Actions Beanie allows you to set default values through Pydantic’s default_factory, handy for timestamps and other fields. Beyond that, you can automate more complex logic (like updating updated_at or validating data) with Beanie’s event-based actions, which run before or after certain actions (e.g., insert, replace).
  5. Atomic Updates and Partial Saves Rather than updating entire documents, Beanie supports MongoDB’s in-place operations ($set, $inc, $addToSet, etc.). Additionally, “save changes” can track what was modified in memory and apply only those changes to the database. This approach is both more efficient and safer for concurrency.
  6. Relationships and Prefetching Although MongoDB is document-oriented, Beanie 1.17+ has introduced a way to set up “links” that represent references (one-to-one or one-to-many) between documents. You can choose to fetch all related data in one shot with prefetch, avoiding the N+1 query problem. This is done under the hood with MongoDB’s aggregation “lookup” pipeline.
  7. Indexing for Performance MongoDB indexing is essential for speed, and Beanie allows you to declare indexes directly in your model definitions. You can specify ascending, descending, text, sparse, or unique constraints to match your application’s needs. Proper indexing can reduce query times dramatically.
  8. Aggregation and Custom Output Models Beanie supports MongoDB’s flexible Aggregation Framework. You can pass a pipeline or even specify an “output” Pydantic model for the aggregated result. This allows advanced data transformations (like grouping, summing, or averaging) directly in the database.
  9. Caching Mechanisms A newly added feature in Beanie is a caching layer that can store query results in memory, reducing redundant database hits. You can set expiration times on cached data, making it well-suited to data that rarely changes or to repeated queries within a short window.
    • Tools:
      • Local Python dictionary caching (built-in)
      • Redis or other backends (planned for the future)
  10. Revisions and Optimistic Concurrency To handle concurrent writes gracefully, Beanie can track document revisions. If a document in memory is out of date when you try to save it, you’ll get an error rather than silently overwriting changes. This is known as optimistic concurrency control and helps avoid data conflicts.
  • Concepts:
    • Revision tokens stored with each document
    • Conflict error if revision doesn’t match
  1. Beyond Pydantic: Future Plans While Pydantic is powerful, it can be heavy for certain large or performance-sensitive scenarios. Roman hinted at possible support for native Python data classes in the future, cutting down on overhead while preserving much of Beanie’s simplicity.
  2. PyCharm, YARL, and Other Tools Roman shared that he uses PyCharm (thanks to a JetBrains license for open source) and that he often relies on the YARL library for easy URL building (like a Pathlib for URLs). Many Python devs also toggle between editors like VS Code for quick scripts.

Interesting Quotes and Stories

  • “If you're using PyMongo…you're doing it wrong. Basing your app on a foundation of exchanging raw dictionaries is a castle built on sand.”
  • “I started with Django, so I wasn't a Python developer as much as a Django developer—later I learned Python too.”
  • “We didn’t plan on relationships, but after seeing a demand, we built them—so much of Beanie’s evolution is driven by user requests.”

Key Definitions and Terms

  • ODM (Object Document Mapper): A library that maps database documents (MongoDB) to Python objects, enforcing schema and providing query methods.
  • Pydantic: A Python library for data validation using type hints, turning them into powerful conversion and validation rules.
  • Motor: An official async Python driver for MongoDB, letting you use async and await for truly non-blocking database calls.
  • N+1 Query Problem: Common inefficiency where one parent record leads to many individual queries for child data, hurting performance.
  • Event-Based Actions: Hooks in Beanie that run code before or after insert, update, or validation events.
  • Optimistic Concurrency (Revisions): A way to avoid overwriting changes by having a version or revision on each record to detect out-of-date saves.

Learning Resources

Looking to dive deeper into MongoDB, Python, and async development? Check out these courses:

Overall Takeaway

Beanie exemplifies how far modern Python has come for data-driven applications, blending async execution, Pydantic validation, and MongoDB’s non-relational freedom. By orchestrating advanced features like atomic updates, relationships, caching, and concurrency handling, Beanie takes you beyond raw dictionary chaos into a structured, efficient data model. Roman’s story underscores the power of community-driven, iterative open source development, and his experience proves that tight feedback loops in production lead to libraries that are both robust and developer-friendly.

Links from the show

Roman on Twitter: @roman_the_right
Beanie ODM: github.com
Tutorial: roman-right.github.io
Beanie Relations, Cache, Actions and more!🎉🚀: dev.to/romanright
Unsync: asherman.io
ResponseModel: fastapi.tiangolo.com
Weather Talk Python API docs: weather.talkpython.fm
JetBrains fleet: jetbrains.com
yarl: github.com
Joke: twitter.com/stoltzmaniac
Loading Document Objects to Beanie Dynamically: dev.pythonbynight.com

Michael's YouTube videos
Parsing data with Pydantic: youtube.com
Counting the number of times items appear: youtube.com
Do you even need loops in Python?: youtube.com
Stream Deck + PyCharm - Enhancing Python Developer Productivity: youtube.com
Watch this episode on YouTube: youtube.com
Episode transcripts: talkpython.fm

--- Stay in touch with us ---
Subscribe to Talk Python on YouTube: youtube.com
Talk Python on Bluesky: @talkpython.fm at bsky.app
Talk Python on Mastodon: talkpython
Michael on Bluesky: @mkennedy.codes at bsky.app
Michael on Mastodon: mkennedy

Talk Python's Mastodon Michael Kennedy's Mastodon