Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsMachine Coding Exercises
✓ FreeAdvanced· 7 min read

Connection Pool Design

Building a ConnectionPool class from scratch with acquire/release semantics, why BlockingQueue is the natural internal structure, and the block-vs-timeout-vs-throw decision when the pool is exhausted.

Published September 23, 2026


Connection Pool Design

Connection Pooling covered why pools exist and how to tune a production one (HikariCP). This lesson is the from-scratch class design an interviewer might ask for directly.

Core class: acquire/release semantics

class ConnectionPool {
    private final BlockingQueue<Connection> availableConnections;
    private final Set<Connection> allConnections; // tracks every connection this pool owns, for leak detection
    private final int maxSize;

    ConnectionPool(int maxSize, ConnectionFactory factory) {
        this.maxSize = maxSize;
        this.availableConnections = new LinkedBlockingQueue<>(maxSize);
        this.allConnections = ConcurrentHashMap.newKeySet();
        for (int i = 0; i < maxSize; i++) {
            Connection conn = factory.create();
            availableConnections.offer(conn);
            allConnections.add(conn);
        }
    }

    Connection acquire() throws InterruptedException {
        return availableConnections.take(); // blocks if none available — see the exhaustion policy discussion below
    }

    void release(Connection conn) {
        if (!allConnections.contains(conn)) throw new IllegalArgumentException("Connection not owned by this pool");
        availableConnections.offer(conn); // returns it to the pool for reuse
    }
}

Why BlockingQueue is the natural fit

A connection pool's core operation — "hand out an available resource, block if none are free, and let another thread's release() unblock a waiting acquirer" — is exactly BlockingQueue's contract (see Concurrent Utilities & Coordination): take() blocks until an element is available, offer()/put() makes one available and wakes a waiting take(). Building this manually with wait()/notify() (the way Producer-Consumer Class Design does deliberately, as a learning exercise) would just be reimplementing what BlockingQueue already provides correctly — for a real connection pool, reaching for the existing concurrent utility is the right call, not an instructive detour.

When the pool is exhausted: block, timeout, or throw

interface AcquireStrategy {
    Connection acquire(BlockingQueue<Connection> pool) throws InterruptedException, PoolExhaustedException;
}

class BlockIndefinitelyStrategy implements AcquireStrategy {
    public Connection acquire(BlockingQueue<Connection> pool) throws InterruptedException {
        return pool.take(); // waits as long as it takes
    }
}

class TimeoutStrategy implements AcquireStrategy {
    private final long timeoutMs;
    public Connection acquire(BlockingQueue<Connection> pool) throws InterruptedException, PoolExhaustedException {
        Connection conn = pool.poll(timeoutMs, TimeUnit.MILLISECONDS);
        if (conn == null) throw new PoolExhaustedException("No connection available within " + timeoutMs + "ms");
        return conn;
    }
}

class FailFastStrategy implements AcquireStrategy {
    public Connection acquire(BlockingQueue<Connection> pool) throws PoolExhaustedException {
        Connection conn = pool.poll(); // returns immediately, null if empty
        if (conn == null) throw new PoolExhaustedException("Pool exhausted");
        return conn;
    }
}

This is the same Strategy-pattern separation as everywhere else in this course — which policy is correct depends entirely on the caller's context: a background batch job might reasonably block indefinitely, while a user-facing request handler almost certainly wants a bounded timeout (an unbounded wait here means a slow downstream dependency turns into an indefinitely-hanging user request) — HikariCP's own real connectionTimeout setting (see Connection Pooling) is exactly the TimeoutStrategy shape, not a coincidence.

Follow-up questions this topic invites — and their answers

Q: Why track allConnections separately from availableConnections? A: availableConnections only holds connections currently free for reuse — allConnections tracks every connection the pool has ever created, which is what enables release() to validate that a caller isn't returning a connection this pool didn't issue (a real bug class — releasing a foreign or already-released connection), and is also the natural structure for leak detection: periodically checking which allConnections entries have been checked out longer than a threshold without being released.

Q: How would you detect a connection leak (never released)? A: Track a checkout timestamp per connection (a wrapper object pairing Connection with acquiredAt), and run a periodic background check (a ScheduledExecutorService task, see ExecutorService & Thread Pools) flagging or force-reclaiming connections held longer than a configured threshold — this is precisely HikariCP's own leakDetectionThreshold feature, reimplemented at a conceptual level.

Q: What happens if a connection in the pool goes stale (the underlying network connection dies) while sitting idle? A: acquire() should validate a connection's liveness before handing it out (a lightweight ping/health-check), replacing it with a freshly created one if the check fails — handing out a dead connection and only discovering that on actual use would surface as a confusing failure far from its real cause.

Q: Is a fixed-size pool always correct, or would a pool that grows/shrinks be better? A: A fixed size is simpler and avoids the connection-storm risk of aggressively creating many new connections under a sudden load spike — but a pool with a configurable min/max (like HikariCP's minimumIdle/maximumPoolSize) that grows toward maxSize under sustained demand and shrinks back toward minimumIdle when idle balances resource efficiency against burst capacity better than a purely fixed size.

Previous

Thread-Safe LRU Cache

Next

Producer-Consumer Class Design

AI Tutor

Lesson: Connection Pool Design

Quick actions

AI responses can be inaccurate. Verify critical information.