v0.8.0 Release Notes¶
Release Date: February 2026
This release introduces the Data Layer features, providing first-class database and Redis integration with connection pooling, transaction management, and async support.
Highlights¶
- Enhanced Database Pooling - Async connection pool with health monitoring & automatic reconnection
- Redis Integration - Async Redis client with pool management, Pub/Sub, and cluster mode
- Transaction Support - Automatic transaction management with
@transactionaldecorator
New Features¶
Enhanced Database Connection Pooling¶
Database connection pooling with health monitoring and automatic reconnection:
from cello import App, DatabaseConfig
app = App()
app.enable_database(DatabaseConfig(
url="postgresql://user:pass@localhost/mydb",
pool_size=20,
min_idle=5,
max_lifetime_secs=1800,
idle_timeout_secs=300,
connect_timeout_secs=5,
))
Features:
- Configurable pool size with min idle connections
- Connection health checks and automatic reconnection
- Connection lifetime management to prevent stale connections
- Pool metrics exposed via Prometheus (
/metrics) - Support for PostgreSQL, MySQL, and SQLite connection strings
Redis Integration¶
Full-featured async Redis client with connection pooling:
from cello import App, RedisConfig
app = App()
app.enable_redis(RedisConfig(
url="redis://localhost:6379",
pool_size=10,
default_ttl=3600,
key_prefix="myapp:",
))
# Or use convenience constructors
app.enable_redis(RedisConfig.local()) # localhost defaults
app.enable_redis(RedisConfig.cluster( # cluster mode
url="redis://cluster:7000",
pool_size=20,
))
Features:
- Async connection pool with configurable size
- All Redis data types: strings, hashes, lists, sets
- Key expiration and TTL management
- Pub/Sub messaging support
- Redis Cluster mode
- TLS support for secure connections
- Key prefix namespacing
- Pool metrics via Prometheus
Supported Operations:
from cello.database import Redis
redis = await Redis.connect(config)
# String operations
await redis.set("key", "value", ttl=3600)
value = await redis.get("key")
await redis.delete("key")
count = await redis.incr("counter")
# Hash operations
await redis.hset("user:1", "name", "Alice")
name = await redis.hget("user:1", "name")
data = await redis.hgetall("user:1")
# List operations
await redis.lpush("queue", "task1", "task2")
task = await redis.lpop("queue")
items = await redis.lrange("queue", 0, -1)
# Pub/Sub
await redis.publish("events", '{"type": "update"}')
Transaction Support¶
Automatic transaction management with the @transactional decorator:
from cello import App
from cello.database import transactional
app = App()
@app.post("/transfer")
@transactional
async def transfer(request):
data = request.json()
# All database operations here run in a single transaction
await db.execute(
"UPDATE accounts SET balance = balance - $1 WHERE id = $2",
data["amount"], data["from_id"]
)
await db.execute(
"UPDATE accounts SET balance = balance + $1 WHERE id = $2",
data["amount"], data["to_id"]
)
return {"success": True}
# Transaction auto-commits on success
# Transaction auto-rollbacks on exception
Features:
- Decorator-based transaction boundaries
- Automatic commit on success
- Automatic rollback on exception
- Works with both sync and async handlers
- Transaction context available via dependency injection
- Nested transaction support (savepoints)
Improvements¶
Performance¶
- Connection pool warming - Pre-establish minimum idle connections on startup
- Redis pipelining - Batch multiple Redis commands for reduced round trips
- Lazy connection creation - Connections created on demand, not at startup
Observability¶
- Pool metrics - Active connections, idle connections, wait time, and error counts exposed via Prometheus
- Redis metrics - Command count, latency, cache hit/miss ratio at
/metrics - Health check integration - Database and Redis connectivity included in
/healthendpoint
Developer Experience¶
- Convenience constructors -
RedisConfig.local()andRedisConfig.cluster()for common setups - Pythonic API -
DatabaseandRediswrapper classes with intuitive async methods - Type hints - Full type annotations on all public APIs
Bug Fixes¶
- Fixed
loogsparameter typo inApp.run()method (renamed tologs) - Fixed
Response.error()usage in circuit breaker example (method does not exist) - Fixed CORS middleware ignoring custom origins configuration
- Fixed connection leak when handler raises exception during response building
- Improved error messages for invalid configuration values
Example¶
See the complete database demo example for a working application demonstrating all Data Layer features.
from cello import App, Response, DatabaseConfig, RedisConfig
from cello.database import transactional
app = App()
# Enable database and Redis
app.enable_database(DatabaseConfig(
url="postgresql://user:pass@localhost/mydb",
pool_size=20,
max_lifetime_secs=1800,
))
app.enable_redis(RedisConfig(
url="redis://localhost:6379",
pool_size=10,
))
@app.get("/")
def home(request):
return {"status": "ok", "version": "0.8.0"}
@app.post("/transfer")
@transactional
async def transfer(request):
# Automatic transaction management
return {"success": True}
app.run()
Migration Guide¶
See the Migration Guide for detailed upgrade instructions.
Quick Migration¶
-
Update your dependency:
-
Import new Data Layer classes:
-
Configure database and Redis (optional - only if you need these features):
-
No breaking changes from v0.7.0 - all existing code continues to work.
Contributors¶
Thanks to all contributors who made this release possible!
Full Changelog¶
See the complete changelog for all changes.