@@ -18,20 +18,31 @@ Migrate to {+driver-async+}
1818.. meta::
1919 :keywords: motor, async, refactor, migration, asynchronous
2020
21- .. include:: /includes/pymongo-async-experimental.rst
22-
2321Overview
2422--------
2523
26- The {+driver-async+} driver is a unification of {+driver-short+} and the `Motor
24+ The {+driver-async+} API is a unification of {+driver-short+} and the `Motor
2725library <https://www.mongodb.com/docs/drivers/motor/>`__. In this guide, you can
2826identify the changes you must make to migrate an application from {+driver-short+} or
29- Motor to the {+driver-async+} driver.
27+ Motor to the {+driver-async+} API.
28+
29+ Motivation
30+ ~~~~~~~~~~
31+
32+ The {+driver-async+} API is designed to be a replacement for the Motor
33+ library. Motor was created to provide support for Tornado, with ``asyncio`` support
34+ added later. Because of this, Motor provides full ``asyncio`` and Tornado support,
35+ but still relies on a thread pool to perform network operations. In some cases,
36+ this might lead to performance degradation when using the Motor library. To
37+ address this issue, the {+driver-async+} API implements ``asyncio`` support directly
38+ into {+driver-short+}. In most cases, the {+driver-async+} API results in
39+ improved performance over Motor. To see performance benchmarks, see the
40+ :ref:`pymongo-async-benchmarks` section.
3041
3142Synchronous Versus Asynchronous
3243~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3344
34- To determine whether to migrate to the {+driver-async+} driver or to continue using
45+ To determine whether to migrate to the {+driver-async+} API or to continue using
3546Synchronous {+driver-short+}, consider the information in this section.
3647
3748Synchronous {+driver-short+} is preferable if the following criteria applies to your
@@ -45,7 +56,7 @@ application or use case:
4556
4657- You prefer the simplicity of synchronous logic when debugging your application
4758
48- Consider migrating to the {+driver-async+} driver if the following criteria applies
59+ Consider migrating to the {+driver-async+} API if the following criteria applies
4960to your application or use case:
5061
5162- Your application implements large, highly concurrent workloads (on the order of
@@ -56,20 +67,134 @@ to your application or use case:
5667
5768- Your application relies on other asynchronous libraries or frameworks, such as FastAPI
5869
70+ .. _pymongo-async-benchmarks:
71+
72+ Performance Benchmarks
73+ ~~~~~~~~~~~~~~~~~~~~~~
74+
75+ The following table shows the performance benchmarks for different tasks
76+ performed with the {+driver-async+} API and the Motor library. Each task was
77+ performed with 10 iterations of 1000 documents each. In most
78+ cases, the {+driver-async+} API results in improved performance over Motor.
79+
80+ .. list-table::
81+ :header-rows: 1
82+ :widths: 40 20 20
83+
84+ * - Operation
85+ - Motor Performance
86+ - {+driver-async+} Performance
87+
88+ * - ``TestFindManyAndEmptyCursor``
89+ - 74.074 MB/s
90+ - 112.490 MB/s
91+
92+ * - ``TestFindManyAndEmptyCursor80Tasks``
93+ - 37.181 MB/s
94+ - 89.521 MB/s
95+
96+ * - ``TestFindManyAndEmptyCursor8Tasks``
97+ - 63.145 MB/s
98+ - 97.165 MB/s
99+
100+ * - ``TestFindOneByID``
101+ - 3.121 MB/s
102+ - 2.922 MB/s
103+
104+ * - ``TestFindOneByID80Tasks``
105+ - 3.789 MB/s
106+ - 4.071 MB/s
107+
108+ * - ``TestFindOneByID8Tasks``
109+ - 3.697 MB/s
110+ - 3.445 MB/s
111+
112+ * - ``TestFindOneByIDUnlimitedTasks``
113+ - 3.866 MB/s
114+ - 4.171 MB/s
115+
116+ * - ``TestGridFsDownload``
117+ - 573.770 MB/s
118+ - 603.578 MB/s
119+
120+ * - ``TestGridFsUpload``
121+ - 430.870 MB/s
122+ - 444.445 MB/s
123+
124+ * - ``TestLargeDocBulkInsert``
125+ - 82.631 MB/s
126+ - 102.105 MB/s
127+
128+ * - ``TestLargeDocClientBulkInsert``
129+ - 75.057 MB/s
130+ - 90.345 MB/s
131+
132+ * - ``TestLargeDocCollectionBulkInsert``
133+ - 85.810 MB/s
134+ - 101.838 MB/s
135+
136+ * - ``TestLargeDocInsertOne``
137+ - 84.832 MB/s
138+ - 101.934 MB/s
139+
140+ * - ``TestLargeDocInsertOneUnlimitedTasks``
141+ - 120.389 MB/s
142+ - 163.553 MB/s
143+
144+ * - ``TestRunCommand``
145+ - 0.036 MB/s
146+ - 0.034 MB/s
147+
148+ * - ``TestRunCommand80Tasks``
149+ - 0.042 MB/s
150+ - 0.043 MB/s
151+
152+ * - ``TestRunCommand8Tasks``
153+ - 0.039 MB/s
154+ - 0.041 MB/s
155+
156+ * - ``TestRunCommandUnlimitedTasks``
157+ - 0.043 MB/s
158+ - 0.042 MB/s
159+
160+ * - ``TestSmallDocBulkInsert``
161+ - 35.071 MB/s
162+ - 38.213 MB/s
163+
164+ * - ``TestSmallDocBulkMixedOps``
165+ - 0.729 MB/s
166+ - 0.446 MB/s
167+
168+ * - ``TestSmallDocClientBulkInsert``
169+ - 25.032 MB/s
170+ - 25.727 MB/s
171+
172+ * - ``TestSmallDocClientBulkMixedOps``
173+ - 1.746 MB/s
174+ - 1.723 MB/s
175+
176+ * - ``TestSmallDocCollectionBulkInsert``
177+ - 34.144 MB/s
178+ - 37.666 MB/s
179+
180+ * - ``TestSmallDocInsertOne``
181+ - 0.539 MB/s
182+ - 0.572 MB/s
183+
184+ * - ``TestSmallDocInsertOneUnlimitedTasks``
185+ - 0.740 MB/s
186+ - 0.786 MB/s
187+
59188Migrate From Motor
60189------------------
61190
62191.. warning:: Motor Deprecation
63-
64- The {+driver-async+} driver is experimental. We do **not** recommend using it
65- in production environments.
66192
67- Motor will be deprecated one year after the **production release** of the
68- {+driver-async+} driver. We strongly recommend that Motor users migrate to
69- the {+driver-async+} driver while Motor is still supported.
193+ Motor will be deprecated on May 14th, 2026. We strongly recommend that Motor users migrate to
194+ the {+driver-async+} API while Motor is still supported.
70195
71- The {+driver-async+} driver functions similarly to the Motor library, but allows
72- for improved latency and throughput due to directly using Python Asyncio instead
196+ The {+driver-async+} API functions similarly to the Motor library, but allows
197+ for improved latency and throughput due to directly using Python ``asyncio`` instead
73198of delegating work to a thread pool. In most cases, you can directly migrate
74199existing Motor applications to {+driver-async+} by using ``AsyncMongoClient`` in
75200place of ``MotorClient``, and changing the application's import statements to
@@ -87,26 +212,22 @@ read and write operations in Motor compared to {+driver-async+}:
87212 from pymongo import AsyncMongoClient
88213
89214To see a list of the asynchronous methods available in the {+driver-async+}
90- driver , see the :ref:`pymongo-async-methods` section. To learn about the versions of Motor
215+ API , see the :ref:`pymongo-async-methods` section. To learn about the versions of Motor
91216that correspond to {+driver-short+}, see the :ref:`pymongo-motor-compatibility` section of
92217the Compatibility guide.
93218
94219The following section shows the method signature changes that you must implement
95- in your application when migrating from Motor to the {+driver-async+} driver.
96-
97- .. warning::
98-
99- The {+driver-async+} driver does not support Tornado.
220+ in your application when migrating from Motor to the {+driver-async+} API.
100221
101222Method Signature Changes
102223~~~~~~~~~~~~~~~~~~~~~~~~
103224
104- The following Motor method signatures behave differently in the {+driver-async+} driver :
225+ The following Motor method signatures behave differently in the {+driver-async+} API :
105226
106227- ``AsyncMongoClient.__init__()`` does not accept an ``io_loop`` parameter.
107- - ``AsyncCursor.each()`` does not exist in the {+driver-async+} driver .
108- - ``MotorGridOut.stream_to_handler()`` does not exist in the {+driver-async+} driver .
109- - ``AsyncCursor.to_list(0)`` is not valid in the {+driver-async+} driver . Use
228+ - ``AsyncCursor.each()`` does not exist in the {+driver-async+} API .
229+ - ``MotorGridOut.stream_to_handler()`` does not exist in the {+driver-async+} API .
230+ - ``AsyncCursor.to_list(0)`` is not valid in the {+driver-async+} API . Use
110231 ``to_list(None)`` instead.
111232- ``MongoClient`` is thread safe and can be used by many threads, however, an
112233 ``AsyncMongoClient`` is not thread safe and should only be used by a single
@@ -115,13 +236,13 @@ The following Motor method signatures behave differently in the {+driver-async+}
115236.. warning::
116237
117238 Motor users may experience a degradation of performance when switching to the
118- {+driver-async+} driver . This is due to the {+driver-async+} driver using native
239+ {+driver-async+} API . This is due to the {+driver-async+} API using native
119240 ``asyncio`` tasks instead of thread-based executors. Thread-based executors
120241 have similar performance characteristics to the synchronous driver, but slower.
121242 This means they perform better for workloads that do not fit the preceding criteria
122- for the {+driver-async+} driver .
243+ for the {+driver-async+} API .
123244
124- If you are experiencing performance slowdown, identify whether the {+driver-async+} driver
245+ If you are experiencing performance slowdown, identify whether the {+driver-async+} API
125246 is necessary for your usecase. If you determine your use case is better served by
126247 synchronous {+driver-short+}, consider using the synchronous driver
127248 with ``asyncio.loop.run_in_executor()`` for asynchronous compatibility. To learn more, see
@@ -132,7 +253,7 @@ The following Motor method signatures behave differently in the {+driver-async+}
132253Migrate from {+driver-short+}
133254-----------------------------
134255
135- The {+driver-async+} driver behaves similarly to {+driver-short+}, but
256+ The {+driver-async+} API behaves similarly to {+driver-short+}, but
136257all methods that perform network operations are coroutines and must be awaited.
137258To migrate from {+driver-short+} to {+driver-async+}, you must update your code
138259in the following ways:
@@ -142,11 +263,11 @@ in the following ways:
142263- If you call an asynchronous method inside a function, mark the function as ``async``.
143264
144265Keep the following points in mind when migrating from synchronous {+driver-short+}
145- to the {+driver-async+} driver :
266+ to the {+driver-async+} API :
146267
147268- To convert an ``AsyncCursor`` to a list, you must use the asynchronous ``cursor.to_list()``
148269 method.
149- - The ``AsyncCollection.find()`` method in the {+driver-async+} driver is synchronous, but
270+ - The ``AsyncCollection.find()`` method in the {+driver-async+} API is synchronous, but
150271 returns an ``AsyncCursor``. To iterate through the cursor, you must use an ``async for``
151272 loop.
152273- The ``AsyncMongoClient`` object does not support the ``connect`` keyword argument.
@@ -163,7 +284,7 @@ to the {+driver-async+} driver:
163284Asynchronous Methods
164285--------------------
165286
166- For a complete list of asynchronous methods available in the {+driver-async+} driver ,
287+ For a complete list of asynchronous methods available in the {+driver-async+} API ,
167288see the `API documentation <{+api-root+}pymongo/asynchronous/index.html>`__.
168289
169290.. note::
@@ -173,5 +294,5 @@ see the `API documentation <{+api-root+}pymongo/asynchronous/index.html>`__.
173294Additional Information
174295----------------------
175296
176- To learn more about asynchronous Python, see the `Python Asyncio documentation
297+ To learn more about asynchronous Python, see the `Python asyncio documentation
177298<https://docs.python.org/3/library/asyncio.html>`__.
0 commit comments