Привет, Хабр!
HikariCP вполне можно назвать де-факто стандартом JDBC connection pooling в современной JVM-экосистеме: он используется по умолчанию в Spring Boot, часто выбирается в Java, Kotlin и Scala-проектах, активно поддерживается и хорошо знаком DevOps/SRE-командам по метрикам и поведению.

Типичная конфигурация пула выглядит примерно следующим образом:
Пример конфигурации
val config = new HikariConfig() config.setJdbcUrl(url) config.setUsername(user) config.setPassword(password) config.setMaximumPoolSize(connectionPoolMaxSize) config.setLeakDetectionThreshold(1000) config.setAutoCommit(true) sslRootCert.foreach(config.addDataSourceProperty("sslrootcert", _)) new HikariDataSource(config)
И конфиг:
Пример HOCON-конфига
db.jdbc { dataSource { url = ${?DATASOURCE_URL} user = ${?DB_USER} password = ${?DB_PASSWD} } connectionPool { maxSize = 32 maxSize = ${?DB_CONNECTION_SIZE} } }
Вроде не ужас. HikariCP есть, размер пула вынесен в переменную окружения, пароль не захардкожен в боевом конфиге, SSL-сертификат поддерживается. Можно жить.
Но если смотреть на это пристальнее, то возникают вопросы:
Почему пул именно 32 или 42 или 52?
Что будет, если база или сетевой балансировщик закрывает соединения раньше, чем Hikari?
Сколько ждать свободное соединение: 30 секунд по умолчанию или меньше?
Видим ли мы метрики пула?
Работает ли
leakDetectionThreshold = 1000, или мы просто успокаиваем себя красивой строчкой?
Погнали разбираться. В этой части — что такое HikariCP, где он живёт, какие версии актуальны и как задаёт минимальный и типовой конфиг. Во второй части разберём размер пула, Kubernetes/PgBouncer, доработаем конфиг из начала, типовые ошибки и продовый чеклист.
1. HikariCP: что это вообще такое
Определение
HikariCP это JDBC connection pool.
JDBC тут ключевое слово. HikariCP не привязан к одному языку или фреймворку. Это библиотека для JVM, которая управляет JDBC-соединениями. Поэтому она одинаково естественно живёт в Java, Kotlin, Scala, Groovy, Clojure и вообще в любом языке, который в итоге работает поверх JVM и JDBC.
Что делает пул
заранее открывает несколько соединений к базе;
выдаёт соединение коду, когда надо выполнить запрос;
принимает соединение обратно после
close();следит за жизненным циклом соединений;
ограничивает количество одновременных походов в базу;
даёт метрики, чтобы понять, где приложение упёрлось в БД.
Без пула каждый запрос мог бы создавать новое физическое соединение. Это дорого: TCP, TLS, аутентификация, настройка сессии, иногда ещё и прокси между приложением и базой. С пулом приложение берёт уже готовое соединение, работает и возвращает его обратно.
Пул не ускоряет сам SQL, он ограничивает и упорядочивает доступ к базе
Главная мысль, которую легко пропустить: пул не ускоряет сам SQL. Он ограничивает и упорядочивает доступ к базе. Хорошо настроенный пул делает систему стабильнее. Плохо настроенный пул умеет очень красиво положить базу, особенно если у вас 20 pod’ов и в каждом maximumPoolSize = 50.
2. Где используют HikariCP
Java
В Java-мире HikariCP давно стал вариантом “по умолчанию”. В Spring Boot он используется как дефолтный JDBC pool, если в classpath есть spring-boot-starter-jdbc или spring-boot-starter-data-jpa.
Kotlin
В Kotlin всё то же самое. Если проект на Spring Boot или Ktor с JDBC/Exposed, HikariCP обычно подключается через стандартную конфигурацию.
Scala
В Scala его можно встретить рядом с Quill, Slick, ScalikeJDBC, ZIO, Akka. Смысл тот же: HikariDataSource передают в контекст выбранной database-библиотеки или регистрируют в обёртке над DataSource.
Groovy
В Groovy это Grails, Spring Boot, plain JDBC-скрипты и сервисы.
Clojure
В Clojure HikariCP используют через next.jdbc, hikari-cp и похожие обёртки.
Python, Go, Node.js и Ruby
В Python, Go, Node.js и Ruby HikariCP обычно не используют, потому что там нет JDBC как базового слоя. Там свои пулы: database/sql в Go, SQLAlchemy QueuePool в Python, pg.Pool в Node.js и так далее.
3. Версии на апрель 2026
По Maven Central и репозиторию проекта актуальная основная линия HikariCP: 7.0.x, последняя версия, которую я нашёл, 7.0.2.
Важный момент по совместимости
Современный артефакт HikariCP рассчитан на Java 11+. Старые Java 8-проекты не надо механически тащить на 7.x. Для них нужно отдельно смотреть совместимую ветку и ограничения своего фреймворка.
Крупные вехи
3.4.5- старая, но ещё встречается в живых проектах. Релиз 2020 года.4.x- эпоха Java 8/11-перехода, появилсяkeepaliveTime.5.x- уже более современная линия для новых JVM-стеков.6.x- много внутренних исправлений, включая работу с credentials и JDBC lifecycle.7.x- актуальная major-линия, Java 11+, исправления вокруг reflection, credentials provider, interruption в pool filling loop.
Осторожно с virtual threads
А теперь ложка дёгтя. В апреле 2026 я бы аккуратно смотрел на HikariCP 7.0.2 в проектах с virtual threads. Есть открытые обсуждения про CPU saturation в сценариях с большим количеством virtual threads, где соединения активно берутся и возвращаются в пул. Это не значит “не обновляться никогда”. Это значит: если у вас Java 21, virtual threads и высокий DB-throughput, обновление надо прогонять под нагрузкой, а не только через unit-тесты.
Для обычного JVM-сервиса без virtual threads история проще: смотрим совместимость JVM и фреймворка, обновляемся на поддерживаемую версию, запускаем нагрузочный тест.
4. Минимальная настройка в разных JVM-языках
Начнём с голого HikariCP, без Spring Boot магии.
Java
Пример настройки HikariCP на Java
import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import javax.sql.DataSource; public final class DataSourceFactory { public static DataSource create() { HikariConfig config = new HikariConfig(); config.setJdbcUrl(System.getenv("DB_URL")); config.setUsername(System.getenv("DB_USER")); config.setPassword(System.getenv("DB_PASSWORD")); config.setPoolName("app-postgres"); config.setMaximumPoolSize(16); config.setMinimumIdle(16); config.setConnectionTimeout(5_000); config.setValidationTimeout(2_000); config.setMaxLifetime(25 * 60_000); config.setKeepaliveTime(2 * 60_000); config.setAutoCommit(true); return new HikariDataSource(config); } }
Kotlin
Пример настройки HikariCP на Kotlin
import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource import javax.sql.DataSource fun dataSource(): DataSource { val config = HikariConfig().apply { jdbcUrl = System.getenv("DB_URL") username = System.getenv("DB_USER") password = System.getenv("DB_PASSWORD") poolName = "app-postgres" maximumPoolSize = 16 minimumIdle = 16 connectionTimeout = 5_000 validationTimeout = 2_000 maxLifetime = 25 * 60_000 keepaliveTime = 2 * 60_000 isAutoCommit = true } return HikariDataSource(config) }
Scala
Пример настройки HikariCP на Scala
import com.zaxxer.hikari.{HikariConfig, HikariDataSource} object DataSourceFactory { def create(): HikariDataSource = { val config = new HikariConfig() config.setJdbcUrl(sys.env("DB_URL")) config.setUsername(sys.env("DB_USER")) config.setPassword(sys.env("DB_PASSWORD")) config.setPoolName("app-postgres") config.setMaximumPoolSize(16) config.setMinimumIdle(16) config.setConnectionTimeout(5000) config.setValidationTimeout(2000) config.setMaxLifetime(25 * 60 * 1000) config.setKeepaliveTime(2 * 60 * 1000) config.setAutoCommit(true) new HikariDataSource(config) } }
Синтаксис разный, смысл один: HikariCP это один и тот же HikariConfig и HikariDataSource, просто обёрнутые в привычный язык.
5. Если у вас Spring Boot
В Spring Boot обычно не надо руками создавать HikariDataSource. Достаточно настроек:
Пример настройки HikariCP в Spring Boot
spring: datasource: url: jdbc:postgresql://db.example.local:5432/app username: ${DB_USER} password: ${DB_PASSWORD} hikari: pool-name: app-postgres maximum-pool-size: 16 minimum-idle: 16 connection-timeout: 5000 validation-timeout: 2000 max-lifetime: 1500000 keepalive-time: 120000 auto-commit: true register-mbeans: true
Полезные метрики HikariCP
Если включён Spring Boot Actuator и Micrometer, метрики Hikari обычно можно получить без большого шаманства. Самые полезные:
hikaricp.connections.active- сколько соединений сейчас занято;hikaricp.connections.idle- сколько свободно;hikaricp.connections.pending- сколько потоков ждут соединение;hikaricp.connections.timeout- сколько раз приложение не дождалось соединения;hikaricp.connections.acquire- сколько времени занимает получение соединения;hikaricp.connections.usage- как долго соединение держат.
Без метрик настройка пула превращается в догадки: кажется, что всё работает, пока не начались таймауты и очередь за соединениями.
6. Главные параметры HikariCP
maximumPoolSize
Максимальное количество соединений в пуле. Включает и занятые, и свободные.
Если пул достиг этого размера, а свободных соединений нет, поток будет ждать до connectionTimeout. Потом получит ошибку.
Самая частая ошибка: ставить maximumPoolSize по количеству пользователей или HTTP-потоков. База не становится быстрее от того, что вы открыли к ней 100 соединений. Часто становится медленнее: контекстные переключения, конкуренция за CPU, locks, память, лишняя нагрузка на планировщик.
minimumIdle
Минимальное количество свободных соединений, которое Hikari старается держать.
Если minimumIdle не задан, HikariCP по умолчанию делает его равным maximumPoolSize. Получается fixed-size pool: все соединения создаются и держатся тёплыми.
Для серверных приложений с предсказуемой нагрузкой это часто нормальный вариант. Меньше сюрпризов на всплесках. Если хотите динамический пул, задавайте minimumIdle ниже maximumPoolSize, но понимайте цену: новые соединения могут создаваться прямо во время нагрузки.
connectionTimeout
Сколько ждать свободное соединение из пула.
Дефолт HikariCP: 30 секунд. Для многих backend-сервисов это слишком долго. Если запрос 30 секунд стоит в очереди за соединением, пользователь уже давно не счастлив, а ваш HTTP thread занят и держит ресурсы.
Я обычно начинаю с 2-5 секунд для online API и отдельно думаю про batch/background jobs.
validationTimeout
Сколько ждать проверки соединения. Дефолт: 5 секунд.
Если база или сеть деградирует, длинные проверки могут добавить неприятную задержку. 1-2 секунды часто достаточно, но надо смотреть на сеть и географию.
idleTimeout
Сколько idle-соединение может лежать в пуле перед удалением.
Работает только если minimumIdle < maximumPoolSize. Если пул fixed-size, параметр почти не участвует в жизни.
maxLifetime
Максимальный возраст соединения.
Это один из самых важных параметров для прода. Он должен быть меньше таймаута, после которого соединение может прибить база, proxy, load balancer, firewall или managed cloud-инфраструктура.
Если инфраструктура закрывает соединения через 30 минут, ставить maxLifetime = 30m плохо. Лучше 25-29 минут, в зависимости от конкретного окружения. Hikari сам добавляет небольшое размазывание по времени, чтобы не убивать весь пул разом.
keepaliveTime
Периодическая проверка idle-соединений, чтобы инфраструктура не считала их мёртвыми.
Появился не в самых древних версиях, поэтому если у вас HikariCP 3.4.5, пора посмотреть changelog и совместимость. В современных версиях дефолт около 2 минут. Значение должно быть меньше maxLifetime.
leakDetectionThreshold
Через сколько миллисекунд Hikari логирует предупреждение, что соединение слишком долго не вернули в пул.
Дефолт: 0, то есть выключено. Минимальное значение для включения: 2000 мс.
И вот тут возвращаемся к конфигу из начала статьи:
config.setLeakDetectionThreshold(1000)
Выглядит как “ловим утечки быстрее”. На деле в современных HikariCP значение меньше 2 секунд не считается валидным. То есть такая настройка может быть просто отключена валидацией. Обидный случай: строчка есть, а пользы нет.
В проде я бы не держал короткий leak detection постоянно. Он может шуметь на нормальных длинных запросах. Лучше включать временно при расследовании или ставить порог выше ожидаемого p99 использования соединения.
Вместо вывода:
Во второй части разберём выбор размера пула (формула из PostgreSQL/Hikari wiki, закон Литтла, метрики), суммирование соединений по репликам и связку с Kubernetes, роль PgBouncer, доработку «типового» конфига из примера, полный HOCON и Scala-код, типовые ошибки, мини-чеклист для прода и полезные ссылки.
Если вам близки темы разработки, рефакторинга, архитектуры и стартапов, буду рад видеть вас в моём Telegram-канале.
Успешных вам релизов!