Guide: Create a DataSource Pool
April 12, 2026 · View on GitHub
Purpose
This guide provides step-by-step instructions for creating and configuring DataSource pools for different deployment scenarios. Follow the steps for the scenario that matches your use case.
Prerequisites
- A Java project with Maven
io.ebean:ebean-datasourcedependency already added topom.xml- Database connection details (URL, username, password)
- Understanding of your deployment environment (standard server, Kubernetes, AWS Lambda, etc.)
Scenario 1: Basic DataSource Pool (Standard Server/VM)
Use this configuration for traditional server deployments.
Step 1 — Create the pool builder
DataSourcePool pool = DataSourcePool.builder()
.name("mypool")
.url("jdbc:postgresql://localhost:5432/myapp")
.username("app_user")
.password("password")
.minConnections(5)
.maxConnections(50)
.build();
Step 2 — Use the pool in your application
try (Connection connection = pool.getConnection()) {
try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM users WHERE id = ?")) {
stmt.setInt(1, 123);
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
// Process results
}
}
}
}
Scenario 2: Read-Only Pool
Use this configuration for read-only workloads (analytics, reporting, caching layers). This adds readOnly(true) and autoCommit(true) options when building the pool.
Step 1 — Create a read-only pool
DataSourcePool readOnlyPool = DataSourcePool.builder()
.name("mypool-readonly")
.url("jdbc:postgresql://read-replica.example.com:5432/myapp")
.username("readonly_user")
.password("password")
.readOnly(true) // Signal no writes will occur
.autoCommit(true) // Skip transaction overhead
.minConnections(5)
.maxConnections(30)
.build();
Step 2 — Use the read-only pool
try (Connection connection = readOnlyPool.getConnection()) {
try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM large_table")) {
try (ResultSet rs = stmt.executeQuery()) {
while (rs.next()) {
// Process results - queries will be faster with read-only optimization
}
}
}
}
Scenario 3: Kubernetes Deployment
Use this configuration when deploying to Kubernetes clusters.
Step 1 — Create a pool with warm-up configuration
When pods start, they immediately receive production traffic. Start with initialConnections
set higher than minConnections to avoid cold-start connection creation overhead.
DataSourcePool pool = DataSourcePool.builder()
.name("mypool")
.url("jdbc:postgresql://postgres.default.svc.cluster.local:5432/myapp")
.username("app_user")
.password(System.getenv("DB_PASSWORD")) // Use environment variables
.minConnections(5)
.initialConnections(20) // Start with 20 connections ready
.maxConnections(50)
.build();
Step 2 — Use environment variables for configuration
For Kubernetes deployments, externalize database credentials:
String dbUrl = System.getenv("DATABASE_URL");
String dbUser = System.getenv("DATABASE_USER");
String dbPass = System.getenv("DATABASE_PASSWORD");
DataSourcePool pool = DataSourcePool.builder()
.name("mypool")
.url(dbUrl)
.username(dbUser)
.password(dbPass)
.minConnections(5)
.initialConnections(20)
.maxConnections(50)
.build();
Scenario 4: AWS Lambda
Use this configuration for AWS Lambda functions.
Step 1 — Create a minimal pool
The ebean datasource automatically detects when it is running in Lambda via the LAMBDA_TASK_ROOT environment variable
and disables background heartbeat validation to optimize for cost and lambda suspend behaviour.
DataSourcePool pool = DataSourcePool.builder()
.name("mypool")
.url("jdbc:postgresql://mydb.region.rds.amazonaws.com:5432/myapp")
.username("app_user")
.password(System.getenv("DB_PASSWORD"))
.minConnections(1)
.initialConnections(2)
.maxConnections(10)
.build();
Step 2 — Understanding Lambda connection pooling
Important: Connection pooling in Lambda is per-Lambda instance, not per-invocation:
- A single Lambda container can be reused across many warm invocations
- Connection pool persists across warm invocations
- Cold starts get a fresh pool
- Connections are trimmed automatically if unused
Configuration Reference
Common Settings
| Setting | Default | Purpose |
|---|---|---|
minConnections | 2 | Minimum connections to maintain in the pool |
initialConnections | Same as minConnections | Connections to create when pool starts (useful for Kubernetes/warm-up) |
maxConnections | 200 | Maximum connections to allow |
readOnly | false | Set to true for read-only workloads |
autoCommit | false | Set to true to skip transaction boundaries |
validateOnHeartbeat | true (false in Lambda) | Enable background connection validation |
heartbeatFreqSecs | 30 | How often to validate connections (seconds) |
Typical Sizing
Development/Testing:
.minConnections(1)
.initialConnections(1)
.maxConnections(5)
Production - Standard Server:
.minConnections(5)
.initialConnections(10)
.maxConnections(50)
Production - High Traffic:
.minConnections(10)
.initialConnections(40)
.maxConnections(100)
Lambda - Standard:
.minConnections(1)
.initialConnections(2)
.maxConnections(10)
Lambda - Provisioned Concurrency:
.minConnections(2)
.initialConnections(10)
.maxConnections(20)
Next Steps
- Read the README for more information about the connection pool
- Check the ebean-datasource GitHub repository for latest updates
- Consult the DataSourceBuilder API documentation for all available configuration options