Connection Pooling in Geode
Connection pooling is essential for high-performance Geode applications. By reusing established connections instead of creating new ones for each request, pooling dramatically reduces latency and improves throughput.
Why Connection Pooling Matters
Establishing a new Geode connection involves:
- QUIC handshake (TLS 1.3 negotiation)
- Protocol initialization (HELLO message exchange)
- Authentication (if enabled)
This overhead, while small per connection, becomes significant at scale. Connection pooling amortizes this cost across many requests.
Python Client Pooling
from geode_client import ConnectionPool
# Create pool with configuration
pool = ConnectionPool(
host="localhost",
port=3141,
min_connections=5, # Minimum idle connections
max_connections=50, # Maximum total connections
connection_timeout=30.0, # Timeout for acquiring connection
idle_timeout=300.0 # Close idle connections after 5 minutes
)
async def query_with_pool():
# Acquire connection from pool
async with pool.acquire() as conn:
result, _ = await conn.query("""
MATCH (u:User {id: $id})
RETURN u.name
""", {'id': 123})
return result
# Pool manages connection lifecycle automatically
Go Client Pooling
The Go client uses database/sql which provides built-in connection pooling:
import (
"database/sql"
_ "geodedb.com/geode"
)
// Open creates a pool, not a single connection
db, err := sql.Open("geode", "localhost:3141")
if err != nil {
log.Fatal(err)
}
// Configure pool settings
db.SetMaxOpenConns(50) // Maximum connections
db.SetMaxIdleConns(10) // Maximum idle connections
db.SetConnMaxLifetime(5 * time.Minute)
db.SetConnMaxIdleTime(1 * time.Minute)
// Queries automatically use pooled connections
rows, err := db.QueryContext(ctx, "MATCH (u:User) RETURN u.name")
Rust Client Pooling
use geode_client::{Client, PoolConfig};
// Configure connection pool
let config = PoolConfig {
min_connections: 5,
max_connections: 50,
connection_timeout: Duration::from_secs(30),
idle_timeout: Duration::from_secs(300),
};
let client = Client::builder()
.host("localhost")
.port(3141)
.pool_config(config)
.build()
.await?;
// Connections managed automatically
let result = client.query("MATCH (n:Node) RETURN count(n)").await?;
Pool Sizing Guidelines
Minimum connections: Set based on baseline load. Having connections ready reduces latency for initial requests after idle periods.
Maximum connections: Consider:
- Server capacity (check Geode server configuration)
- Application concurrency requirements
- Memory overhead per connection
- Network limits
Rule of thumb: Start with max_connections = (number of cores * 2) + disk spindles for the database server, adjusted for your workload.
Monitoring Pool Health
Track these metrics:
- Active connections vs. pool size
- Connection wait time
- Connection creation rate
- Connection errors
# Python pool statistics
stats = pool.stats()
print(f"Active: {stats.active}")
print(f"Idle: {stats.idle}")
print(f"Waiting: {stats.waiting}")
Best Practices
Size appropriately: Oversized pools waste resources; undersized pools cause contention.
Handle exhaustion gracefully: Set appropriate timeouts and handle pool exhaustion errors.
Release connections promptly: Don’t hold connections during long-running application logic.
Use connection health checks: Configure pools to validate connections before use.