[{"data":1,"prerenderedAt":970},["ShallowReactive",2],{"page-\u002Fasync-engines-dialects-and-connection-pooling\u002F":3},{"id":4,"title":5,"body":6,"description":47,"extension":964,"meta":965,"navigation":87,"path":966,"seo":967,"stem":968,"__hash__":969},"content\u002Fasync-engines-dialects-and-connection-pooling\u002Findex.md","Async Engines, Dialects, and Connection Pooling in SQLAlchemy 2.0",{"type":7,"value":8,"toc":940},"minimark",[9,13,18,27,32,41,140,144,151,155,166,170,184,188,191,236,244,297,301,316,320,329,333,336,356,364,478,482,497,501,508,512,522,525,636,640,643,647,658,662,668,676,846,850,908,912,918,924,930,936],[10,11,5],"h1",{"id":12},"async-engines-dialects-and-connection-pooling-in-sqlalchemy-20",[14,15,17],"h2",{"id":16},"understanding-sqlalchemy-20-async-architecture","Understanding SQLAlchemy 2.0 Async Architecture",[19,20,21,22,26],"p",{},"SQLAlchemy 2.0 introduces a foundational architectural shift from thread-blocking synchronous execution to a coroutine-driven, non-blocking I\u002FO model. Traditional database connectivity relies on OS threads to wait for network round-trips, which introduces context-switching overhead and caps throughput under high concurrency. The async architecture delegates I\u002FO waits to Python’s ",[23,24,25],"code",{},"asyncio"," event loop, allowing the interpreter to yield control and resume execution only when the database driver signals readiness.",[28,29,31],"h3",{"id":30},"the-event-loop-and-coroutine-execution-model","The Event Loop and Coroutine Execution Model",[19,33,34,35,40],{},"The async engine operates by wrapping the underlying async driver in an awaitable execution pipeline. Every database interaction—from connection acquisition to query execution and result fetching—must be explicitly awaited. This design eliminates thread contention and dramatically reduces memory overhead, making it ideal for high-throughput API servers and background workers. Before diving into driver selection, establishing baseline connectivity requires careful attention to ",[36,37,39],"a",{"href":38},"\u002Fasync-engines-dialects-and-connection-pooling\u002Fconfiguring-async-engines-and-connection-pools\u002F","Configuring Async Engines and Connection Pools"," to ensure your event loop remains responsive and free of hidden blocking calls.",[42,43,48],"pre",{"className":44,"code":45,"language":46,"meta":47,"style":47},"language-python shiki shiki-themes github-light github-dark","from sqlalchemy.ext.asyncio import create_async_engine\nfrom typing import Final\n\nDATABASE_URL: Final[str] = \"postgresql+asyncpg:\u002F\u002Fuser:pass@localhost\u002Fdb\"\nengine = create_async_engine(DATABASE_URL, echo=True)\n","python","",[23,49,50,69,82,89,112],{"__ignoreMap":47},[51,52,55,59,63,66],"span",{"class":53,"line":54},"line",1,[51,56,58],{"class":57},"szBVR","from",[51,60,62],{"class":61},"sVt8B"," sqlalchemy.ext.asyncio ",[51,64,65],{"class":57},"import",[51,67,68],{"class":61}," create_async_engine\n",[51,70,72,74,77,79],{"class":53,"line":71},2,[51,73,58],{"class":57},[51,75,76],{"class":61}," typing ",[51,78,65],{"class":57},[51,80,81],{"class":61}," Final\n",[51,83,85],{"class":53,"line":84},3,[51,86,88],{"emptyLinePlaceholder":87},true,"\n",[51,90,92,96,99,102,105,108],{"class":53,"line":91},4,[51,93,95],{"class":94},"sj4cs","DATABASE_URL",[51,97,98],{"class":61},": Final[",[51,100,101],{"class":94},"str",[51,103,104],{"class":61},"] ",[51,106,107],{"class":57},"=",[51,109,111],{"class":110},"sZZnC"," \"postgresql+asyncpg:\u002F\u002Fuser:pass@localhost\u002Fdb\"\n",[51,113,115,118,120,123,125,128,132,134,137],{"class":53,"line":114},5,[51,116,117],{"class":61},"engine ",[51,119,107],{"class":57},[51,121,122],{"class":61}," create_async_engine(",[51,124,95],{"class":94},[51,126,127],{"class":61},", ",[51,129,131],{"class":130},"s4XuR","echo",[51,133,107],{"class":57},[51,135,136],{"class":94},"True",[51,138,139],{"class":61},")\n",[28,141,143],{"id":142},"greenlet-integration-for-legacy-compatibility","Greenlet Integration for Legacy Compatibility",[19,145,146,147,150],{},"To ease migration from legacy codebases, SQLAlchemy leverages ",[23,148,149],{},"greenlet"," to run synchronous ORM operations within async contexts. While this shim allows gradual refactoring, it introduces hidden thread scheduling and should be treated as a transitional mechanism. Production architectures should prioritize fully async-native patterns to avoid unpredictable latency spikes and event loop starvation.",[14,152,154],{"id":153},"async-dialects-and-driver-selection","Async Dialects and Driver Selection",[19,156,157,158,161,162,165],{},"SQLAlchemy’s async support is dialect-agnostic but strictly enforces DBAPI 2.0 async compliance. The underlying driver must natively implement ",[23,159,160],{},"async","\u002F",[23,163,164],{},"await"," semantics; otherwise, the event loop will block on synchronous socket calls.",[28,167,169],{"id":168},"dbapi-20-async-compliance-requirements","DBAPI 2.0 Async Compliance Requirements",[19,171,172,173,175,176,179,180,183],{},"Async drivers must expose non-blocking socket operations and integrate with ",[23,174,25],{}," event loops. SQLAlchemy validates this compliance at runtime and will raise ",[23,177,178],{},"RuntimeError"," if a synchronous driver is passed to ",[23,181,182],{},"create_async_engine()",". Additionally, drivers must support async cursor execution, async transaction management, and proper connection state tracking to prevent pool corruption.",[28,185,187],{"id":186},"postgresql-mysql-and-sqlite-async-support","PostgreSQL, MySQL, and SQLite Async Support",[19,189,190],{},"Each major RDBMS ecosystem offers distinct async driver implementations with varying performance characteristics, prepared statement caching, and connection lifecycle behaviors:",[192,193,194,210,227],"ul",{},[195,196,197,201,202,205,206,209],"li",{},[198,199,200],"strong",{},"PostgreSQL:"," ",[23,203,204],{},"postgresql+asyncpg:\u002F\u002F"," delivers exceptional throughput via native binary protocol support and efficient prepared statement caching. The modern ",[23,207,208],{},"psycopg"," (v3) also provides async capabilities but follows a different architectural model.",[195,211,212,201,215,218,219,222,223,226],{},[198,213,214],{},"MySQL:",[23,216,217],{},"mysql+aiomysql:\u002F\u002F"," and ",[23,220,221],{},"mysql+asyncmy:\u002F\u002F"," wrap the MySQL protocol in async-compatible layers, with ",[23,224,225],{},"asyncmy"," generally offering lower latency for high-concurrency workloads.",[195,228,229,201,232,235],{},[198,230,231],{},"SQLite:",[23,233,234],{},"sqlite+aiosqlite:\u002F\u002F"," executes synchronous SQLite operations in a dedicated thread pool to bypass the GIL while exposing an async interface.",[19,237,238,239,243],{},"When architecting PostgreSQL workloads, evaluating ",[36,240,242],{"href":241},"\u002Fasync-engines-dialects-and-connection-pooling\u002Fchoosing-between-asyncpg-and-psycopg-async-drivers\u002F","Choosing Between asyncpg and psycopg Async Drivers"," reveals critical trade-offs in connection lifecycle management and binary protocol efficiency.",[42,245,247],{"className":44,"code":246,"language":46,"meta":47,"style":47},"# PostgreSQL (asyncpg)\nPG_URL = \"postgresql+asyncpg:\u002F\u002Fuser:pass@localhost:5432\u002Fapp_db\"\n# MySQL (aiomysql)\nMYSQL_URL = \"mysql+aiomysql:\u002F\u002Fuser:pass@localhost:3306\u002Fapp_db\"\n# SQLite (aiosqlite)\nSQLITE_URL = \"sqlite+aiosqlite:\u002F\u002F\u002F.\u002Fapp.db\"\n",[23,248,249,255,266,271,281,286],{"__ignoreMap":47},[51,250,251],{"class":53,"line":54},[51,252,254],{"class":253},"sJ8bj","# PostgreSQL (asyncpg)\n",[51,256,257,260,263],{"class":53,"line":71},[51,258,259],{"class":94},"PG_URL",[51,261,262],{"class":57}," =",[51,264,265],{"class":110}," \"postgresql+asyncpg:\u002F\u002Fuser:pass@localhost:5432\u002Fapp_db\"\n",[51,267,268],{"class":53,"line":84},[51,269,270],{"class":253},"# MySQL (aiomysql)\n",[51,272,273,276,278],{"class":53,"line":91},[51,274,275],{"class":94},"MYSQL_URL",[51,277,262],{"class":57},[51,279,280],{"class":110}," \"mysql+aiomysql:\u002F\u002Fuser:pass@localhost:3306\u002Fapp_db\"\n",[51,282,283],{"class":53,"line":114},[51,284,285],{"class":253},"# SQLite (aiosqlite)\n",[51,287,289,292,294],{"class":53,"line":288},6,[51,290,291],{"class":94},"SQLITE_URL",[51,293,262],{"class":57},[51,295,296],{"class":110}," \"sqlite+aiosqlite:\u002F\u002F\u002F.\u002Fapp.db\"\n",[14,298,300],{"id":299},"connection-pooling-strategies-for-high-concurrency-workloads","Connection Pooling Strategies for High-Concurrency Workloads",[19,302,303,304,307,308,311,312,315],{},"In async environments, connection pooling must operate without thread contention. SQLAlchemy 2.0 defaults to ",[23,305,306],{},"AsyncAdaptedQueuePool",", which replaces the traditional ",[23,309,310],{},"QueuePool"," with an ",[23,313,314],{},"asyncio.Queue","-backed implementation. This ensures that connection acquisition and release are fully awaitable and do not block the event loop.",[28,317,319],{"id":318},"asyncadaptedqueuepool-vs-nullpool","AsyncAdaptedQueuePool vs NullPool",[19,321,322,324,325,328],{},[23,323,306],{}," is optimal for long-running services where connection reuse amortizes TCP handshake and authentication overhead. Conversely, ",[23,326,327],{},"NullPool"," disables pooling entirely and is appropriate for serverless environments (AWS Lambda, Cloud Run) where connection multiplexing is handled externally or cold starts make pooling counterproductive.",[28,330,332],{"id":331},"tuning-pool_size-max_overflow-and-pool_recycle","Tuning pool_size, max_overflow, and pool_recycle",[19,334,335],{},"Proper pool configuration prevents resource exhaustion and stale connection errors:",[192,337,338,344,350],{},[195,339,340,343],{},[23,341,342],{},"pool_size",": Base number of persistent connections. Align with your database instance's max connection limit divided by application replicas.",[195,345,346,349],{},[23,347,348],{},"max_overflow",": Burst capacity during traffic spikes. Keep conservative to avoid overwhelming the RDBMS.",[195,351,352,355],{},[23,353,354],{},"pool_recycle",": Forces connection refresh after a set interval. Essential for cloud-managed databases (RDS, Aurora) that silently terminate idle connections.",[19,357,358,359,363],{},"To prevent production outages during traffic spikes, implement robust monitoring and recovery strategies outlined in ",[36,360,362],{"href":361},"\u002Fasync-engines-dialects-and-connection-pooling\u002Fhandling-connection-leaks-and-pool-exhaustion\u002F","Handling Connection Leaks and Pool Exhaustion",".",[42,365,367],{"className":44,"code":366,"language":46,"meta":47,"style":47},"from sqlalchemy.ext.asyncio import create_async_engine\nfrom sqlalchemy.pool import AsyncAdaptedQueuePool\n\nengine = create_async_engine(\n \"postgresql+asyncpg:\u002F\u002Fuser:pass@localhost\u002Fdb\",\n poolclass=AsyncAdaptedQueuePool,\n pool_size=20,\n max_overflow=10,\n pool_recycle=3600,\n pool_pre_ping=True,\n)\n",[23,368,369,379,391,395,404,412,422,435,448,461,473],{"__ignoreMap":47},[51,370,371,373,375,377],{"class":53,"line":54},[51,372,58],{"class":57},[51,374,62],{"class":61},[51,376,65],{"class":57},[51,378,68],{"class":61},[51,380,381,383,386,388],{"class":53,"line":71},[51,382,58],{"class":57},[51,384,385],{"class":61}," sqlalchemy.pool ",[51,387,65],{"class":57},[51,389,390],{"class":61}," AsyncAdaptedQueuePool\n",[51,392,393],{"class":53,"line":84},[51,394,88],{"emptyLinePlaceholder":87},[51,396,397,399,401],{"class":53,"line":91},[51,398,117],{"class":61},[51,400,107],{"class":57},[51,402,403],{"class":61}," create_async_engine(\n",[51,405,406,409],{"class":53,"line":114},[51,407,408],{"class":110}," \"postgresql+asyncpg:\u002F\u002Fuser:pass@localhost\u002Fdb\"",[51,410,411],{"class":61},",\n",[51,413,414,417,419],{"class":53,"line":288},[51,415,416],{"class":130}," poolclass",[51,418,107],{"class":57},[51,420,421],{"class":61},"AsyncAdaptedQueuePool,\n",[51,423,425,428,430,433],{"class":53,"line":424},7,[51,426,427],{"class":130}," pool_size",[51,429,107],{"class":57},[51,431,432],{"class":94},"20",[51,434,411],{"class":61},[51,436,438,441,443,446],{"class":53,"line":437},8,[51,439,440],{"class":130}," max_overflow",[51,442,107],{"class":57},[51,444,445],{"class":94},"10",[51,447,411],{"class":61},[51,449,451,454,456,459],{"class":53,"line":450},9,[51,452,453],{"class":130}," pool_recycle",[51,455,107],{"class":57},[51,457,458],{"class":94},"3600",[51,460,411],{"class":61},[51,462,464,467,469,471],{"class":53,"line":463},10,[51,465,466],{"class":130}," pool_pre_ping",[51,468,107],{"class":57},[51,470,136],{"class":94},[51,472,411],{"class":61},[51,474,476],{"class":53,"line":475},11,[51,477,139],{"class":61},[14,479,481],{"id":480},"async-session-management-and-execution-patterns","Async Session Management and Execution Patterns",[19,483,484,485,488,489,492,493,496],{},"The ",[23,486,487],{},"AsyncSession"," object is the primary interface for ORM operations in async workflows. Unlike its synchronous counterpart, every I\u002FO-bound method must be explicitly awaited. Transaction boundaries are strictly managed; implicit autocommit is disabled by default to enforce explicit ",[23,490,491],{},"commit()"," or ",[23,494,495],{},"rollback()"," calls.",[28,498,500],{"id":499},"asyncsession-lifecycle-and-transaction-boundaries","AsyncSession Lifecycle and Transaction Boundaries",[19,502,503,504,507],{},"Sessions should be scoped to a single logical unit of work, typically an HTTP request or background job. The ",[23,505,506],{},"async with session.begin():"," context manager automatically commits successful transactions and rolls back on exceptions, ensuring deterministic state management.",[28,509,511],{"id":510},"explicit-vs-implicit-connection-handling","Explicit vs Implicit Connection Handling",[19,513,514,515,492,518,521],{},"Lazy loading is fundamentally incompatible with async execution because it triggers synchronous I\u002FO during attribute access. Developers must use ",[23,516,517],{},"selectinload()",[23,519,520],{},"joinedload()"," to eagerly fetch relationships. Additionally, connection handling should remain explicit; relying on implicit connection acquisition obscures transaction boundaries and complicates error isolation.",[19,523,524],{},"For deterministic resource cleanup and transaction isolation, adopt the architectural patterns detailed in Async Session Patterns and Context Managers.",[42,526,528],{"className":44,"code":527,"language":46,"meta":47,"style":47},"from sqlalchemy.ext.asyncio import AsyncSession\nfrom sqlalchemy import select\nfrom typing import Optional\n\nasync def fetch_user(session: AsyncSession, user_id: int) -> Optional[User]:\n async with session.begin():\n result = await session.execute(\n select(User).where(User.id == user_id)\n )\n return result.scalars().first()\n",[23,529,530,541,553,564,568,588,599,612,623,628],{"__ignoreMap":47},[51,531,532,534,536,538],{"class":53,"line":54},[51,533,58],{"class":57},[51,535,62],{"class":61},[51,537,65],{"class":57},[51,539,540],{"class":61}," AsyncSession\n",[51,542,543,545,548,550],{"class":53,"line":71},[51,544,58],{"class":57},[51,546,547],{"class":61}," sqlalchemy ",[51,549,65],{"class":57},[51,551,552],{"class":61}," select\n",[51,554,555,557,559,561],{"class":53,"line":84},[51,556,58],{"class":57},[51,558,76],{"class":61},[51,560,65],{"class":57},[51,562,563],{"class":61}," Optional\n",[51,565,566],{"class":53,"line":91},[51,567,88],{"emptyLinePlaceholder":87},[51,569,570,572,575,579,582,585],{"class":53,"line":114},[51,571,160],{"class":57},[51,573,574],{"class":57}," def",[51,576,578],{"class":577},"sScJk"," fetch_user",[51,580,581],{"class":61},"(session: AsyncSession, user_id: ",[51,583,584],{"class":94},"int",[51,586,587],{"class":61},") -> Optional[User]:\n",[51,589,590,593,596],{"class":53,"line":288},[51,591,592],{"class":57}," async",[51,594,595],{"class":57}," with",[51,597,598],{"class":61}," session.begin():\n",[51,600,601,604,606,609],{"class":53,"line":424},[51,602,603],{"class":61}," result ",[51,605,107],{"class":57},[51,607,608],{"class":57}," await",[51,610,611],{"class":61}," session.execute(\n",[51,613,614,617,620],{"class":53,"line":437},[51,615,616],{"class":61}," select(User).where(User.id ",[51,618,619],{"class":57},"==",[51,621,622],{"class":61}," user_id)\n",[51,624,625],{"class":53,"line":450},[51,626,627],{"class":61}," )\n",[51,629,630,633],{"class":53,"line":463},[51,631,632],{"class":57}," return",[51,634,635],{"class":61}," result.scalars().first()\n",[14,637,639],{"id":638},"framework-integration-and-production-deployment","Framework Integration and Production Deployment",[19,641,642],{},"Modern ASGI frameworks (FastAPI, Starlette, Litestar) provide lifecycle hooks that align perfectly with SQLAlchemy’s async engine lifecycle. The engine must be initialized once at startup and explicitly disposed of during shutdown to drain the connection pool and release underlying sockets.",[28,644,646],{"id":645},"asgi-lifespan-management","ASGI Lifespan Management",[19,648,649,650,653,654,657],{},"Application startup should configure the engine and session factories, while shutdown must invoke ",[23,651,652],{},"await engine.dispose()"," to gracefully close all pooled connections. Skipping disposal leaves sockets in ",[23,655,656],{},"TIME_WAIT"," state and can exhaust file descriptors under sustained load.",[28,659,661],{"id":660},"dependency-injection-and-graceful-shutdown","Dependency Injection and Graceful Shutdown",[19,663,664,665,667],{},"Dependency injection patterns should yield a fresh ",[23,666,487],{}," per request, ensuring transactional boundaries map cleanly to HTTP request lifecycles. Health check endpoints should query the pool status to detect connection exhaustion before routing traffic.",[19,669,670,671,675],{},"For production-grade architectural patterns, consult ",[36,672,674],{"href":673},"\u002Fasync-engines-dialects-and-connection-pooling\u002Fintegrating-sqlalchemy-async-with-fastapi-and-starlette\u002F","Integrating SQLAlchemy Async with FastAPI and Starlette"," to implement robust lifespan management and dependency injection.",[42,677,679],{"className":44,"code":678,"language":46,"meta":47,"style":47},"from contextlib import asynccontextmanager\nfrom fastapi import FastAPI\nfrom sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n # Startup: Engine initialized at module level\n yield\n # Shutdown: Gracefully drain pool and close sockets\n await engine.dispose()\n\napp = FastAPI(lifespan=lifespan)\n\nasync def get_session() -> AsyncSession:\n async_session = async_sessionmaker(engine, expire_on_commit=False)\n async with async_session() as session:\n yield session\n",[23,680,681,693,705,716,720,725,737,742,747,752,759,763,782,787,800,821,837],{"__ignoreMap":47},[51,682,683,685,688,690],{"class":53,"line":54},[51,684,58],{"class":57},[51,686,687],{"class":61}," contextlib ",[51,689,65],{"class":57},[51,691,692],{"class":61}," asynccontextmanager\n",[51,694,695,697,700,702],{"class":53,"line":71},[51,696,58],{"class":57},[51,698,699],{"class":61}," fastapi ",[51,701,65],{"class":57},[51,703,704],{"class":61}," FastAPI\n",[51,706,707,709,711,713],{"class":53,"line":84},[51,708,58],{"class":57},[51,710,62],{"class":61},[51,712,65],{"class":57},[51,714,715],{"class":61}," AsyncSession, async_sessionmaker\n",[51,717,718],{"class":53,"line":91},[51,719,88],{"emptyLinePlaceholder":87},[51,721,722],{"class":53,"line":114},[51,723,724],{"class":577},"@asynccontextmanager\n",[51,726,727,729,731,734],{"class":53,"line":288},[51,728,160],{"class":57},[51,730,574],{"class":57},[51,732,733],{"class":577}," lifespan",[51,735,736],{"class":61},"(app: FastAPI):\n",[51,738,739],{"class":53,"line":424},[51,740,741],{"class":253}," # Startup: Engine initialized at module level\n",[51,743,744],{"class":53,"line":437},[51,745,746],{"class":57}," yield\n",[51,748,749],{"class":53,"line":450},[51,750,751],{"class":253}," # Shutdown: Gracefully drain pool and close sockets\n",[51,753,754,756],{"class":53,"line":463},[51,755,608],{"class":57},[51,757,758],{"class":61}," engine.dispose()\n",[51,760,761],{"class":53,"line":475},[51,762,88],{"emptyLinePlaceholder":87},[51,764,766,769,771,774,777,779],{"class":53,"line":765},12,[51,767,768],{"class":61},"app ",[51,770,107],{"class":57},[51,772,773],{"class":61}," FastAPI(",[51,775,776],{"class":130},"lifespan",[51,778,107],{"class":57},[51,780,781],{"class":61},"lifespan)\n",[51,783,785],{"class":53,"line":784},13,[51,786,88],{"emptyLinePlaceholder":87},[51,788,790,792,794,797],{"class":53,"line":789},14,[51,791,160],{"class":57},[51,793,574],{"class":57},[51,795,796],{"class":577}," get_session",[51,798,799],{"class":61},"() -> AsyncSession:\n",[51,801,803,806,808,811,814,816,819],{"class":53,"line":802},15,[51,804,805],{"class":61}," async_session ",[51,807,107],{"class":57},[51,809,810],{"class":61}," async_sessionmaker(engine, ",[51,812,813],{"class":130},"expire_on_commit",[51,815,107],{"class":57},[51,817,818],{"class":94},"False",[51,820,139],{"class":61},[51,822,824,826,828,831,834],{"class":53,"line":823},16,[51,825,592],{"class":57},[51,827,595],{"class":57},[51,829,830],{"class":61}," async_session() ",[51,832,833],{"class":57},"as",[51,835,836],{"class":61}," session:\n",[51,838,840,843],{"class":53,"line":839},17,[51,841,842],{"class":57}," yield",[51,844,845],{"class":61}," session\n",[14,847,849],{"id":848},"common-pitfalls","Common Pitfalls",[192,851,852,862,870,886,898],{},[195,853,854,857,858,861],{},[198,855,856],{},"Blocking the event loop with synchronous drivers or legacy ORM calls:"," Using ",[23,859,860],{},"create_engine()"," or executing synchronous queries within an async context will freeze the event loop and degrade throughput to zero.",[195,863,864,201,867,869],{},[198,865,866],{},"Sharing AsyncSession instances across concurrent coroutines causing state corruption:",[23,868,487],{}," maintains transactional state and identity maps that are not thread\u002Fcoroutine-safe. Concurrent access leads to race conditions and inconsistent query results.",[195,871,872,875,876,492,878,881,882,885],{},[198,873,874],{},"Misconfiguring pool_recycle leading to 'server closed the connection unexpectedly' errors:"," Cloud databases terminate idle connections aggressively. Without ",[23,877,354],{},[23,879,880],{},"pool_pre_ping",", the pool will hand out dead connections, causing intermittent ",[23,883,884],{},"ConnectionResetError"," exceptions.",[195,887,888,891,892,492,895,897],{},[198,889,890],{},"Using lazy-loaded relationships in async contexts without explicit joinedload\u002Fselectinload:"," Accessing unloaded attributes triggers synchronous I\u002FO, raising ",[23,893,894],{},"MissingGreenlet",[23,896,178],{}," exceptions in strict async environments.",[195,899,900,903,904,907],{},[198,901,902],{},"Failing to call await engine.dispose() during application shutdown, causing connection leaks:"," Omitting disposal leaves connections in a half-open state, eventually exhausting database connection limits and triggering ",[23,905,906],{},"PoolTimeout"," errors.",[14,909,911],{"id":910},"faq","FAQ",[19,913,914,917],{},[198,915,916],{},"Can I use SQLAlchemy 2.0 async with synchronous DBAPI drivers?","\nNo. Async engines strictly require fully async-compatible drivers (e.g., asyncpg, aiomysql, aiosqlite). Synchronous drivers will block the event loop and raise runtime errors.",[19,919,920,923],{},[198,921,922],{},"How does connection pooling differ between sync and async SQLAlchemy?","\nAsync mode uses AsyncAdaptedQueuePool by default, which manages connections via coroutines instead of OS threads, eliminating thread contention and reducing memory overhead.",[19,925,926,929],{},[198,927,928],{},"Is it safe to share an AsyncSession across multiple concurrent requests?","\nNo. AsyncSession is not coroutine-safe for concurrent operations. Each request or background task must instantiate its own session to prevent transaction state collisions.",[19,931,932,935],{},[198,933,934],{},"How do I handle database migrations with async SQLAlchemy?","\nAlembic supports async execution via run_migrations_online() with an async connection, but migration scripts themselves typically execute synchronously during deployment pipelines.",[937,938,939],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":47,"searchDepth":71,"depth":71,"links":941},[942,946,950,954,958,962,963],{"id":16,"depth":71,"text":17,"children":943},[944,945],{"id":30,"depth":84,"text":31},{"id":142,"depth":84,"text":143},{"id":153,"depth":71,"text":154,"children":947},[948,949],{"id":168,"depth":84,"text":169},{"id":186,"depth":84,"text":187},{"id":299,"depth":71,"text":300,"children":951},[952,953],{"id":318,"depth":84,"text":319},{"id":331,"depth":84,"text":332},{"id":480,"depth":71,"text":481,"children":955},[956,957],{"id":499,"depth":84,"text":500},{"id":510,"depth":84,"text":511},{"id":638,"depth":71,"text":639,"children":959},[960,961],{"id":645,"depth":84,"text":646},{"id":660,"depth":84,"text":661},{"id":848,"depth":71,"text":849},{"id":910,"depth":71,"text":911},"md",{},"\u002Fasync-engines-dialects-and-connection-pooling",{"title":5,"description":47},"async-engines-dialects-and-connection-pooling\u002Findex","7KIYwrVBiv66iwL_0kOdwRfzAcDgE40DL06qrHaASY8",1778149144400]