r2d2

A generic, backend-agnostic connection pool for Rust

Library
Cargo
v0.8.10
1,655stars
MIT OR Apache-2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
44/100Fair
Development Activity0
Maintenance20
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture78
Code Quality75
Innovation60
Learning Curve72

r2d2 is a generic connection pool for Rust that is agnostic to the type of connection it manages. Instead of opening a new database or network connection on every request — inefficient and prone to resource exhaustion under load — r2d2 maintains a pool of ready-to-use connections and hands them out for repeated reuse, returning them to the pool automatically when they go out of scope.

Backend-specific behavior (how to open a connection, how to check its health) is supplied by implementing r2d2’s ManageConnection trait, which is why the ecosystem around r2d2 consists of thin adapter crates for individual backends — r2d2-postgres, r2d2-sqlite, r2d2-mysql, diesel::r2d2, and Redis’s own built-in r2d2 feature, among others — all sharing this one pooling core.

What You Get

  • A generic Pool<M: ManageConnection> type handing out and reclaiming connections automatically via RAII scope guards
  • The ManageConnection trait defining how a connection is created and health-checked, implemented by adapter crates per backend
  • Configurable pool sizing (max_size, min_idle) and connection lifecycle timeouts via Pool::builder()
  • An event/logging hook (src/event.rs) for observing pool state changes
  • A broad adapter ecosystem: r2d2-postgres, r2d2-sqlite, r2d2-mysql, r2d2-memcache, diesel::r2d2, and Redis’s built-in r2d2 feature

Common Use Cases

  • Pooling PostgreSQL, MySQL, or SQLite connections for a Rust web server handling concurrent requests
  • Sharing a bounded set of Redis connections across worker threads via redis-rs’s r2d2 feature
  • Providing connection pooling to a Diesel ORM application via its built-in diesel::r2d2 integration
  • Implementing pooling for a custom or niche backend by writing a small ManageConnection adapter

Under The Hood

Architecture: The crate centers on src/lib.rs (640 lines), which implements the Pool struct, its internal connection queue, and the checkout/checkin lifecycle backed by parking_lot synchronization primitives and a scheduled-thread-pool for background idle-connection maintenance (health checks, minimum-idle replenishment). src/config.rs (311 lines) defines the builder pattern for pool configuration (max size, timeouts, min idle), src/event.rs exposes lifecycle events for observability, and src/extensions.rs provides small trait-extension helpers. The ManageConnection trait is the sole extension point, deliberately kept minimal so third-party crates can adapt any connection type with little glue code.

Tech Stack: Pure Rust, 2018 edition, with a deliberately tiny dependency footprint: log for tracing pool events, parking_lot for lower-overhead mutexes/condvars than the standard library’s, and scheduled-thread-pool for periodic background maintenance tasks. No async runtime dependency — r2d2 is a synchronous, blocking-style pool (the async equivalent in the Rust ecosystem is typically bb8 or deadpool).

Code Quality: src/test.rs (728 lines) is a substantial in-crate test suite covering pool sizing, timeout behavior, connection health-check failures, and concurrent checkout scenarios using a mock connection manager — proportionally larger than the library’s own implementation code, reflecting the correctness bar expected of concurrency-sensitive pooling primitives. The codebase has had very low recent commit activity (last commit 2024-10) but the API has been stable for years and the crate remains one of the most-downloaded in the Rust database ecosystem.

API Design: The public surface is intentionally narrow — implement ManageConnection (two required methods: connect and is_valid/has_broken), then use Pool::builder().build(manager) and pool.get() to check out a connection that returns itself to the pool via Drop. This RAII-based checkout pattern means callers never need to remember to release a connection explicitly, and the trait-based extension point is why dozens of independent adapter crates exist without needing changes to r2d2 itself.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search