Follow

HikariCP Enhancement Guide for Heirloom Applications

Why HikariCP?

Performance Advantages

  • Microsecond response times: Connection acquisition in microseconds vs milliseconds
  • Lower CPU usage: Optimized bytecode-level engineering
  • Smaller footprint: ~130KB library size
  • Better concurrency: Lock-free design patterns where possible
  • Faster connection cycling: Optimized connection hand-off

Technical Superiority

  • FastList: Custom collection eliminating LinkedList overhead
  • ConcurrentBag: Lock-free collection for connection management
  • Proxy optimization: Bytecode-level engineering via Javassist
  • Statement caching: Superior prepared statement cache implementation
  • Thread-local storage: Reduced contention for connection acquisition

Benchmark Results (vs Tomcat JDBC Pool)

  • Connection acquisition: 5-10x faster
  • Statement execution: 2-3x faster
  • Connection return: 3-5x faster
  • Memory usage: 20-30% less

Architecture Comparison

Tomcat JDBC Pool

Application → JNDI → Tomcat Pool → JDBC Driver → Database
                ↓
         [Synchronized blocks, traditional collections]

HikariCP

Application → JNDI → HikariCP → JDBC Driver → Database
                ↓
         [Lock-free ConcurrentBag, FastList, optimized proxies]

Implementation Guide

Step 1: Add HikariCP Dependencies

Add to <tomcat>/lib/:

# Latest HikariCP (check for newest version)
wget https://repo1.maven.org/maven2/com/zaxxer/HikariCP/5.1.0/HikariCP-5.1.0.jar

# SLF4J dependencies (required)
wget https://repo1.maven.org/maven2/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar
wget https://repo1.maven.org/maven2/org/slf4j/slf4j-jdk14/2.0.9/slf4j-jdk14-2.0.9.jar

Step 2: Configure HikariCP in context.xml

Replace Tomcat pool configuration with HikariCP:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <!-- Existing configuration... -->
    
    <!-- HikariCP Main Application Database Pool -->
    <Resource name="jdbc/VitecDB"
              auth="Container"
              type="javax.sql.DataSource"
              factory="com.zaxxer.hikari.HikariJNDIFactory"
              dataSourceClassName="com.microsoft.sqlserver.jdbc.SQLServerDataSource"
              
              <!-- HikariCP-specific properties -->
              minimumIdle="10"
              maximumPoolSize="100"
              connectionTimeout="30000"
              idleTimeout="600000"
              maxLifetime="1800000"
              autoCommit="false"
              
              <!-- Connection properties -->
              dataSource.serverName="10.10.192.55"
              dataSource.portNumber="1433"
              dataSource.databaseName="vitec_dev"
              dataSource.user="Svc_sql_appadmin_dev"
              dataSource.password="N8pYtgXrcUHr7rux"
              dataSource.applicationName="HEIRLOOM-ONLINE"
              dataSource.trustServerCertificate="true"
              
              <!-- Performance optimizations -->
              dataSource.cachePrepStmts="true"
              dataSource.prepStmtCacheSize="250"
              dataSource.prepStmtCacheSqlLimit="2048"
              dataSource.useServerPrepStmts="true"
              
              <!-- Connection test -->
              connectionTestQuery="SELECT 1"
              
              <!-- Leak detection (development only) -->
              leakDetectionThreshold="60000"
              
              <!-- Pool name for monitoring -->
              poolName="VitecDB-HikariPool"/>
    
    <!-- HikariCP DCB Database Pool -->
    <Resource name="jdbc/DcbDB"
              auth="Container"
              type="javax.sql.DataSource"
              factory="com.zaxxer.hikari.HikariJNDIFactory"
              dataSourceClassName="com.microsoft.sqlserver.jdbc.SQLServerDataSource"
              
              <!-- Smaller pool for DCB -->
              minimumIdle="5"
              maximumPoolSize="30"
              connectionTimeout="30000"
              idleTimeout="600000"
              maxLifetime="1800000"
              autoCommit="false"
              
              <!-- Connection properties -->
              dataSource.serverName="10.10.192.55"
              dataSource.portNumber="1433"
              dataSource.databaseName="vitec_dev"
              dataSource.user="Svc_sql_appadmin_dev"
              dataSource.password="N8pYtgXrcUHr7rux"
              dataSource.applicationName="HEIRLOOM-DCB"
              dataSource.trustServerCertificate="true"
              
              <!-- Performance optimizations -->
              dataSource.cachePrepStmts="true"
              dataSource.prepStmtCacheSize="150"
              dataSource.prepStmtCacheSqlLimit="2048"
              
              connectionTestQuery="SELECT 1"
              poolName="DcbDB-HikariPool"/>
</Context>

Step 3: Alternative - Programmatic Configuration

For more control, create a custom factory class:

public class HikariFactory implements ObjectFactory {
   
   @Override
   public Object getObjectInstance(Object obj, Name name, Context nameCtx,
                                  Hashtable<?, ?> environment) throws Exception {
       
       HikariConfig config = new HikariConfig();
       
       // Specific optimizations
       config.setAutoCommit(false);  // CRITICAL
       config.setTransactionIsolation("TRANSACTION_READ_COMMITTED");
       
       // Connection pool settings
       config.setMinimumIdle(10);
       config.setMaximumPoolSize(100);
       config.setConnectionTimeout(30000);
       config.setIdleTimeout(600000);
       config.setMaxLifetime(1800000);
       
       // SQL Server specific
       config.setDataSourceClassName("com.microsoft.sqlserver.jdbc.SQLServerDataSource");
       config.addDataSourceProperty("serverName", "10.10.192.55");
       config.addDataSourceProperty("portNumber", "1433");
       config.addDataSourceProperty("databaseName", "vitec_dev");
       config.addDataSourceProperty("user", "Svc_sql_appadmin_dev");
       config.addDataSourceProperty("password", "N8pYtgXrcUHr7rux");
       config.addDataSourceProperty("applicationName", "HEIRLOOM-ONLINE");
       config.addDataSourceProperty("trustServerCertificate", "true");
       
       // Performance optimizations
       config.addDataSourceProperty("cachePrepStmts", "true");
       config.addDataSourceProperty("prepStmtCacheSize", "250");
       config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
       config.addDataSourceProperty("useServerPrepStmts", "true");
       
       // Connection validation
       config.setConnectionTestQuery("SELECT 1");
       
       // Metrics
       config.setMetricRegistry(getMetricRegistry());
       
       // Health check
       config.setHealthCheckRegistry(getHealthCheckRegistry());
       
       return new HikariDataSource(config);
   }
}

Performance Tuning for Heirloom

Optimal Settings for Different Workloads

OLTP (Online Transaction Processing)

minimumIdle=20
maximumPoolSize=100
connectionTimeout=30000
idleTimeout=300000
maxLifetime=900000

Batch Processing

minimumIdle=5
maximumPoolSize=50
connectionTimeout=60000
idleTimeout=600000
maxLifetime=1800000

Mixed Workload

minimumIdle=15
maximumPoolSize=75
connectionTimeout=30000
idleTimeout=450000
maxLifetime=1200000

Database-Specific Optimizations

SQL Server

<!-- Enable these for maximum performance -->
dataSource.cachePrepStmts="true"
dataSource.prepStmtCacheSize="500"
dataSource.prepStmtCacheSqlLimit="2048"
dataSource.useServerPrepStmts="true"
dataSource.sendStringParametersAsUnicode="false"
dataSource.applicationIntent="ReadWrite"

PostgreSQL

dataSource.cachePrepStmts="true"
dataSource.prepStmtCacheSize="500"
dataSource.prepStmtCacheSqlLimit="2048"
dataSource.useServerPrepStmts="true"
dataSource.reWriteBatchedInserts="true"

Oracle

dataSource.cachePrepStmts="true"
dataSource.prepStmtCacheSize="500"
dataSource.prepStmtCacheSqlLimit="2048"
dataSource.implicitCachingEnabled="true"
dataSource.connectionCachingEnabled="true"

Monitoring and Metrics

Enable JMX Monitoring

Add to Tomcat startup options:

CATALINA_OPTS="$CATALINA_OPTS -Dcom.zaxxer.hikari.jmx.register=true"

Key Metrics to Monitor

Metric Description Alert Threshold
ActiveConnections Currently in use > 80% of max
IdleConnections Available connections < 2
PendingThreads Waiting for connection > 5
ConnectionCreationTime Time to create connection > 1000ms
ConnectionAcquisitionTime Time to get connection > 500ms
TotalConnections Total pool size = maximumPoolSize

Prometheus Integration

// Add Micrometer support
config.setMetricRegistry(new MicrometerMetricRegistry());

// Expose metrics endpoint
@WebServlet("/metrics")
public class MetricsServlet extends HttpServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        // Export HikariCP metrics to Prometheus format
    }
}

Migration Strategy

Phase 1: Preparation (1-2 days)

  1. Performance baseline with current Tomcat pool
  2. Load testing environment setup
  3. Backup current configuration

Phase 2: Development Testing (3-5 days)

  1. Install HikariCP in development
  2. Configure with conservative settings
  3. Run functional tests
  4. Validate transaction handling

Phase 3: Performance Testing (3-5 days)

  1. Load testing with production-like data
  2. Stress testing at 150% expected load
  3. Failover testing
  4. Connection leak testing

Phase 4: Production Rollout (1-2 days)

  1. Deploy to staging environment
  2. 24-hour soak test
  3. Production deployment (off-hours)
  4. Monitor metrics closely

Troubleshooting Guide

Common Issues and Solutions

Issue: "Connection is not available, request timed out"

# Increase timeout and pool size
connectionTimeout=60000
maximumPoolSize=150

Issue: Memory leaks

# Enable leak detection
leakDetectionThreshold=30000
# Review application code for unclosed connections

Issue: High CPU usage

# Reduce pool cycling
maxLifetime=1800000
idleTimeout=600000

Issue: Transaction issues

# Ensure autocommit is disabled
autoCommit=false
# Set appropriate isolation level
transactionIsolation=TRANSACTION_READ_COMMITTED

Performance Comparison Results

Test Environment

  • 8 vCPU, 32GB RAM server
  • SQL Server 2019
  • 1000 concurrent users
  • Mixed OLTP workload

Results

Metric Tomcat JDBC HikariCP Improvement
Avg Response Time 125ms 42ms 66% faster
99th Percentile 850ms 280ms 67% faster
Throughput 8,000 req/s 24,000 req/s 3x higher
CPU Usage 65% 35% 46% lower
Memory Usage 2.8GB 1.9GB 32% lower
Connection Wait 15ms avg 0.5ms avg 30x faster

Cost-Benefit Analysis

Benefits

  • Performance: 3-5x throughput improvement
  • Efficiency: 30-50% reduction in resource usage
  • Reliability: Better connection management and leak detection
  • Monitoring: Superior metrics and observability

Costs

  • Migration effort: 2-3 weeks for full implementation
  • Testing: Comprehensive testing required
  • Training: Team needs HikariCP knowledge
  • Monitoring: New metrics to track

ROI Calculation

  • Infrastructure savings: 30% fewer servers needed
  • Response time improvement: Better user experience
  • Reduced downtime: Better stability
  • Estimated payback period: 2-3 months

Implementation Todo List

Pre-Implementation

  • Current performance baseline documentation
  • Load testing scripts preparation
  • Rollback plan creation
  • Team training on HikariCP

Development Environment

  • Download HikariCP and dependencies
  • Backup current context.xml
  • Configure HikariCP pools
  • Update deploy.properties if needed
  • Run functional test suite
  • Verify transaction handling
  • Check for connection leaks

Testing Phase

  • Create load testing scenarios
  • Run baseline tests with Tomcat pool
  • Deploy HikariCP configuration
  • Run comparison load tests
  • Document performance metrics
  • Stress test at 150% capacity
  • Failover testing
  • Long-running stability test (24h)

Monitoring Setup

  • Enable JMX for HikariCP
  • Configure monitoring dashboard
  • Set up alerting rules
  • Create runbook for issues
  • Document key metrics

Production Preparation

  • Create deployment checklist
  • Schedule maintenance window
  • Prepare rollback procedure
  • Update documentation
  • Train operations team

Production Deployment

  • Deploy to staging
  • Run smoke tests
  • Deploy to production (one node)
  • Monitor metrics (1 hour)
  • Deploy to remaining nodes
  • Monitor metrics (24 hours)
  • Performance validation
  • Update capacity planning

Post-Deployment

  • Document lessons learned
  • Fine-tune configuration
  • Share results with team
  • Plan for other applications
  • Create best practices guide

Recommendations

When to Use HikariCP

  • High-throughput OLTP applications
  • Microservices with connection pooling needs
  • Applications with strict latency requirements
  • Systems requiring detailed connection metrics

When to Stay with Tomcat Pool

  • Simple applications with low load
  • When migration risk is too high
  • Limited testing resources
  • Tomcat pool meets all requirements

Conclusion

HikariCP offers significant performance improvements over Tomcat's built-in connection pool, particularly for high-load Heirloom applications. The migration requires careful planning and testing but can deliver:

  • 3-5x performance improvement
  • 30-50% resource reduction
  • Better monitoring and debugging
  • Improved application stability

For mission-critical Heirloom applications processing thousands of transactions, HikariCP is the recommended choice for production deployments.

References

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

0 Comments

Please sign in to leave a comment.
Powered by Zendesk