liveBook · Manning

Connection pooling

As explained in Python Concurrency with asyncio

Connection pooling is the practice of maintaining reusable network connections so multiple operations can share them.

Connection pooling maintains reusable network or database connections so multiple operations can share them. Reusing connections avoids the resource and time costs of creating one for every request or query. section 4.2.1 section 5.5.2

A pool provides a bounded workflow:

  • Acquire an available connection before running an operation. section 5.5.2
  • Run one query per connection; one SQL connection cannot safely process multiple concurrent queries at once. section 5.5.1
  • Release the connection after the operation so another task can reuse it. section 5.5.2
  • Wait when all finite connections are busy; waiting is part of connection acquisition. section 5.5.2

Concurrent product queries

An e-commerce service can create an asyncpg pool and let each query task use `async with pool.acquire() as connection`. `asyncio.gather` then runs independent product queries concurrently, while the pool limits database concurrency. In the demonstrated comparison, 10,000 queries took about 21.8 seconds sequentially and 4.8 seconds concurrently. section 5.5 section 5.5.2

Listing 5.7 Establishing a connection pool and running queries concurrently
import asyncio
import asyncpg
 
product_query = \
    """
SELECT
p.product_id,
p.product_name,
p.brand_id,
s.sku_id,
pc.product_color_name,
ps.product_size_name
FROM product as p
JOIN sku as s on s.product_id = p.product_id
JOIN product_color as pc on pc.product_color_id = s.product_color_id
JOIN product_size as ps on ps.product_size_id = s.product_size_id
WHERE p.product_id = 100"""
 
 
async def query_product(pool):
    async with pool.acquire() as connection:
        return await connection.fetchrow(product_query)
 
 
async def main():
    async with asyncpg.create_pool(host='127.0.0.1',
                                   port=5432,
                                   user='postgres',
                                   password='password',
                                   database='products',
                                   min_size=6,
                                   max_size=6) as pool:    #1
 
        await asyncio.gather(query_product(pool),
                             query_product(pool))          #2
 
 
asyncio.run(main())

Use the asyncpg listing to see pool creation, scoped acquisition, query execution, and concurrent task scheduling together. section 5.5.2

How Python Concurrency with asyncio covers it

How deep it goes
Explains caching, acquisition, release, finite capacity, waiting, and concurrent execution, without detailing pool internals.
Examples
Uses aiohttp sessions, asyncpg product queries, a 100,000-SKU dataset, and sequential-versus-concurrent timing.
What it assumes
Assumes basic asyncio concurrency and asynchronous database access, while teaching connection acquisition and reuse from first principles.
What you can do after
Apply it via asyncpg and asyncio to execute independent database queries concurrently while reusing bounded connections.
How it connects
Connects connection pooling with asyncio, asynchronous I/O, HTTP requests, SQL queries, and database transactions.

Also explained in

Compare how 9 books explain connection pooling →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Python Concurrency with asyncio. The section links point to the parts of the book it draws on.