pip install asyncpg★Async-only PostgreSQL driver (no sync API). Python 3.9+, PostgreSQL 9.5–18. Everything is awaited inside an event loop.import asyncpg, asyncio conn = await asyncpg.connect("postgresql://user:pw@host/db")★Connect with a DSN (orhost=/user=/database=kwargs). Must run insideasync def/asyncio.run(...).await conn.close()★Close when done. In practice you'll use a pool (card 3) rather than raw connections.# asyncpg has NO sync API — you must use asyncionoteEvery call is a coroutine. To call from sync code, wrap inasyncio.run(). For a sync Postgres driver, usepsycopginstead.
rows = await conn.fetch( "SELECT id, name FROM t WHERE age > $1", 21)★fetchreturns a list of Record objects. ⚠️ Placeholders are$1, $2, …(positional), passed as extra args — NOT%s.r = await conn.fetchrow("SELECT * FROM t WHERE id=$1", 5) r["name"] · r[0] · dict(r)★fetchrow= one row (orNone). Record supports index and key access;dict(r)to convert.val = await conn.fetchval("SELECT count(*) FROM t")★fetchval= a single scalar from the first row/column.await conn.execute("INSERT INTO t(name) VALUES($1)", "amy")★executeruns a statement with no result set (returns the status string). asyncpg auto-uses prepared statements & binary encoding under the hood.
pool = await asyncpg.create_pool(dsn, min_size=5, max_size=20)★Create a pool once at app startup — reusing connections is far cheaper than connecting per request (essential in web apps).async with pool.acquire() as conn: await conn.fetch("SELECT ...")★Borrow a connection for the block; it returns to the pool automatically. This is the everyday pattern in FastAPI/Starlette handlers.await pool.execute("INSERT ... VALUES($1)", x) await pool.fetch("SELECT ...")The pool proxiesexecute/fetch— acquire+run+release in one call for simple queries.await pool.close() # graceful shutdownClose the pool on app shutdown to drain connections cleanly.
async with conn.transaction(): await conn.execute("UPDATE ... ") await conn.execute("INSERT ...")★Thetransaction()context commits on success, rolls back on exception. Nest for savepoints.await conn.executemany( "INSERT INTO t(a,b) VALUES($1,$2)", [(1,2),(3,4)])★executemanyfor batched writes.await conn.copy_records_to_table("t", records=rows, columns=["a","b"])★COPY is the fastest bulk-load path (orders of magnitude over inserts). Alsocopy_to_table(from a file) andcopy_from_query.# JSON/arrays/composites auto-decode to Python; register custom codecsasyncpg decodes PG types to native Python (arrays→list, json→dict viaset_type_codec).conn.cursor()for server-side streaming of huge results.