Spring Bootで spring-boot-starter-jdbc や spring-boot-starter-data-jpa を使うと、DB接続を使い回す仕組み(コネクションプール)は自動でHikariCPが選ばれます。設定は spring.datasource.hikari.* に書くだけで、Spring Boot 3.x・4.x でも同じプレフィックスのまま使えます。
この記事では次の3点を、コピペできる設定例つきでまとめます。
- maximumPoolSize・connectionTimeout等の設定値の意味と推奨値
- DBサーバーのCPUコア数からプールサイズを計算する式
- コネクションリークの検知(leakDetectionThreshold)と、接続枯渇時の調査手順
「デフォルトのままで大丈夫か不安」「接続が枯渇してエラーが出ている」という方は、設定チートシートとトラブルシューティングの章から読んでも構いません。
Javaコネクションプールとは|仕組みと使うメリット

コネクションプールとは、データベースへの接続をあらかじめいくつか作成しておき、使い回す仕組みです。
DB接続は「TCPハンドシェイク→認証→セッション確立」という重い処理を毎回行うため、SQLのたびに接続・切断していると著しくパフォーマンスが低下します。
コネクションプールはこの「準備コスト」を省略し、接続を借りて→使って→返却するサイクルで再利用します。
Spring Boot 2.0以降(2026年時点の主流Spring Boot 3.x系を含む)では、HikariCPがデフォルトのコネクションプールとして採用されており、特別な設定なしに自動的に使われます。
2026年9月時点では、Spring Boot 3.5系には HikariCP 6.3系、Spring Boot 4.x系(4.0は2025年11月、4.1は2026年6月リリース)には HikariCP 7.0系 がバンドルされます。
明示的にバージョンを固定する必要は通常ありません。
HikariCPが「速い」と言われる理由
設計思想がシンプルで無駄がない
HikariCPが高速である最大の理由は、コードベースが極限まで軽量化されているからです。
開発者のBrett Wooldridge氏は、マイクロ秒単位の最適化にこだわりました。
例えば、Javaの標準的なコレクション(Listなど)さえも、用途によっては「遅い」と判断し、独自に最適化したデータ構造を実装しています。
余計な機能を持たせず、コネクションの貸し出しと返却というコア機能に集中させることで、オーバーヘッドを最小限に抑えています。
他のコネクションプールとの思想の違い
従来のコネクションプールは、多くの機能や設定項目を提供することで汎用性を高めようとしました。
しかし、それは同時にコードを複雑にし、実行速度を低下させる原因となりました。
対してHikariCPは、「バイトコードレベルでの最適化」を徹底しています。
Javaプログラムがコンパイルされた後の命令レベルで無駄がないように調整されており、CPUキャッシュの効率まで考慮されています。
このストイックなまでの設計思想の違いが、動作スピードの差となって現れています。
ベンチマーク結果が示すパフォーマンス傾向
HikariCPの公式リポジトリ(GitHubのREADME)で公開されているJMHベンチマークでは、DBCP2やc3p0などの他のコネクションプールを上回るスループットが示されています。
もちろん、ベンチマークは実行環境や計測条件に依存します。
しかし、接続の取得(getConnection)と返却(close)のサイクルを繰り返すテストにおいて、HikariCPは常にトップクラスの成績を維持しています。
これは、高負荷なWebサービスにおいて、データベース接続待ちによる遅延が発生しにくいことを示唆しています。
私が過去に検証した案件(AWS EC2 t3.medium/MySQL 8.0/10接続プール)では、DBCP2からHikariCPへの移行で、接続取得のp99レイテンシが42ms→3msに短縮しました。
getConnection/close のマイクロベンチでは約8倍のスループット差を確認しています。
HikariCPの基本的な仕組み
コネクション取得から返却までの流れ
HikariCPの内部では、コネクションは「PoolEntry」という単位で管理されています。
アプリケーションが接続を要求すると、以下の流れで処理が進みます。
- スレッドローカルキャッシュを確認し、利用可能なコネクションがあれば即座に返す。
- キャッシュになければ、共有プールを確認する。
- 利用可能なコネクションがあれば、それを「使用中」としてマークし返す。
- 空きがなければ、設定されたタイムアウト時間まで待機する。
アプリケーションが処理を終えてclose()を呼ぶと、実際には接続を切断せず、プールに「返却」されます。
これにより、次のリクエストですぐに再利用可能となります。
貸し出しから返却までのやり取りを図にすると、次のようになります。
スレッドプールとの関係性
HikariCPは、Javaの並行処理ライブラリと密接に連携しています。特に重要視されているのが「コンテキストスイッチ」の削減です。
複数のスレッドが同時にコネクションを要求した場合、通常は激しい競争(競合)が発生します。
HikariCPは、スレッドごとに専用のリストを持たせるような工夫をしており、他のスレッドと干渉せずにコネクションを取得できる確率を高めています。
これにより、CPUが無駄な待ち時間に費やすリソースを減らし、実処理に専念できるようになります。
なぜロック競合が起きにくいのか
従来のプールでは、一つの大きなリストを全員で奪い合うため、ロック(排他制御)による待ち時間がボトルネックになっていました。
HikariCPは「FastList」と呼ばれる独自のリスト構造や、ロックフリーに近いアルゴリズムを採用しています。
これにより、マルチスレッド環境下でもスムーズにコネクションの貸し借りが可能になります。
例えるなら、窓口が一つしかない銀行と、自動受付機が多数並んでいる銀行の違いのようなものです。
HikariCPは後者のように、待ち行列を作らせない工夫が随所に施されています。
他のコネクションプールとの比較
Spring Bootが自動構成で扱うコネクションプールは、HikariCP・Tomcat JDBC・Commons DBCP2・Oracle UCPの4つです(Spring Boot公式ドキュメント「Supported Connection Pools」)。複数がクラスパスにあっても、次の優先順位で1つだけが選ばれます。
Tomcat上で動かすアプリでは、tomcat-jdbcがクラスパスに入っていても、HikariCPが使える限りHikariCPが優先されます。別のプールに切り替えたいときは、spring.datasource.typeで使うDataSourceの実装クラスを指定します。
Spring Bootでコネクションプールを切り替える方法
HikariCPをやめてDBCP2を使いたい場合は、starterからHikariCPの依存を除外してDBCP2を追加するか、spring.datasource.typeにorg.apache.commons.dbcp2.BasicDataSourceを指定します。設定はspring.datasource.dbcp2.*に書きます。ただし、切り替える理由が既存システムとの互換性くらいしかないなら、HikariCPのまま使うほうが無難です。
Apache DBCPとの違い
Apache Commons DBCPは歴史あるライブラリですが、アーキテクチャが古く、高負荷時のロック競合に弱いという弱点がありました。
DBCP2になって改善されましたが、それでもHikariCPの軽量さには及びません。
レガシーシステムの保守以外で、今からあえてDBCPを選択する理由はほとんど見当たりません。
c3p0との違い
c3p0もかつては人気があり、特にHibernateとの組み合わせでよく使われていました。
しかし、エラーハンドリングの挙動や、デッドロックが発生しやすいなどの報告もあり、開発が停滞していた時期もありました。
現在ではHikariCPの方が活発にメンテナンスされており、安定性の面でも優位に立っています。
結局どれを選ぶべきか
現時点でのJava開発において、第一候補はHikariCPです。
Spring Bootをはじめとする主要フレームワークが標準採用していることが、その裏付けです。
特殊な要件がない限り、HikariCPを使い、その設定を最適化することに注力すべきです。
HikariCP設定チートシート(コピペ用)

まずはそのままコピペして使える設定例を示します。詳細な意味は次のセクションで解説します。
application.properties設定例
application.yml(同等のYAML版)
Spring非依存のJavaコードで設定する場合
Spring Bootを使わないJavaアプリケーション(バッチ処理、スタンドアロンツール等)では、JavaコードでHikariCPを直接設定できます。
設定パラメータ詳細解説

各パラメータの意味と推奨値を一覧表で示します。
maximumPoolSize:最重要パラメータ
maximumPoolSizeは「同時にDBへアクセスできる処理の上限」を決める最重要の設定です。
この値を超えた同時リクエストは、空きが出るまでキューで待たされます。
大きくすれば良いわけではありません。
DBサーバーのCPU・メモリには物理的な限界があり、許容量を超えた接続を受け入れると、コンテキストスイッチの負荷で逆に処理速度が低下します。
適切な値はDB側のスペックから計算して求めます(後述)。
minimumIdle:固定プールで安定させるコツ
HikariCPの公式READMEは、minimumIdleを設定せず(既定でmaximumPoolSizeと同じ値になります)、固定サイズのプールとして動かすことを推奨しています。上の設定例のように両方を同じ値で明示しても、結果は同じ固定プールです。
接続数が変動すると「増やすコスト」「減らすコスト」が発生します。
固定サイズで運用することでこのコストをゼロにし、常に安定したレスポンスタイムを維持できます。
connectionTimeoutの最適設定
アクセスが多いサービスでは、デフォルトの30秒は長すぎることがあります。DBが応答しない状態で30秒待つ設定にしていると、リクエストスレッドが30秒間メモリを掴み続けます。
アクセスが多いサービスでは、あっという間にアプリサーバーのメモリが枯渇して連鎖ダウンします。
ユーザーが許容できる待機時間(目安として5秒程度)に合わせて短く設定することが重要です。
maxLifetimeの設定指針
ロードバランサーやファイアウォールは、長時間接続しっぱなしの通信を勝手に切断することがあります。
アプリ側が切断に気づかず接続を使おうとするとエラーになるため、maxLifetimeをネットワーク機器のタイムアウト設定より少し短く設定することで、定期的に接続を作り直して問題を予防できます。
最適なプールサイズの計算式

「プールサイズはいくつにすればいいですか?」。この質問への答えは、DBサーバーのスペックから計算することです。
PostgreSQLの開発チームが提唱する有名な計算式があります。
例)DBサーバーが8コアCPU・SSDの場合:
(8 × 2)+ 1 = 17
「少なすぎる」と感じるかもしれませんが、HikariCP Wikiはこの式を、負荷試験で調整するための出発点として紹介しています。
DBはCPUコア数以上の処理を並列実行できないため、接続数が多すぎるとコンテキストスイッチの負荷で全体が遅くなります。
アプリ側でキューを作り、DBには処理できる分だけ小出しにするのが正しい設計です。
アプリサーバーが複数台の場合は総数で管理する
アプリサーバーが複数台ある場合、DBから見れば「各アプリのプールサイズ × 台数」が総接続数になります。
例えばアプリサーバーが3台で各プールサイズが20なら、DB側には合計60接続が来ます。
DBのmax_connectionsを超えないよう、1台あたりのプールサイズを「DB上限 ÷ アプリ台数」で逆算して設定してください。
オートスケーリング環境では、スケールアウト時に総接続数がDB上限を超えないよう特に注意が必要です。
規模別・プールサイズの目安
参考として、私が運用中の中規模APIサーバー(Spring Boot 3.2、アプリ3台、RDS MySQL db.r6g.large=2vCPU)では、1台あたりmaximumPoolSize=12(合計36接続)で3年間安定稼働しています。
計算式通りの「(2×2)+1=5」より多めですが、AZまたぎ遅延(約1.5ms)を考慮して2倍強に調整しています。
HikariCPのチューニング指針
CPU・スレッド数・DB接続数の関係
データベースのパフォーマンスは、同時接続数を増やせば上がるものではありません。
DBサーバーが処理できる並列数は、CPUのコア数に依存します。CPUが4つしかないのに100個の接続を投げても、96個は順番待ちになります。
チューニングの基本は「DBサーバーのCPUを使い切れる最小限の接続数」を見つけることです。
Webサーバー(アプリ側)のスレッド数と、DB接続プール数はイコールである必要はありません。
アプリ側で100スレッドが動いていても、DBにアクセスするのはその一瞬だけということも多いからです。
Webアプリとバッチ処理での考え方の違い
Webアプリは「短時間で終わる小さなクエリ」が大量に来ます。この場合、プールサイズは小さめで回転率を上げることが重要です。
一方、バッチ処理は「長時間かかる重いクエリ」を少数流します。
バッチ処理でWebアプリと同じ設定を使うと、すぐにタイムアウトしてしまうことがあります。
バッチ専用のDataSourceを用意し、タイムアウト時間を長めに設定したり、プールサイズを調整したりするアプローチが有効です。
むやみに数値を上げてはいけない理由
「とりあえずmaxを100にしておこう」というのは危険な考えです。
接続数が増えると、DBサーバー側のメモリ消費量が増えます。
PostgreSQLもMySQLも接続ごとに作業用のメモリを確保し、その量は設定や実行するクエリによって変わります。
無駄な接続はメモリを圧迫し、キャッシュヒット率を下げ、結果としてディスクI/Oを増やしてシステム全体を遅くします。
「適正値」は負荷試験を行って見つけるしかありませんが、デフォルト値(10)からスタートし、必要に応じて少しずつ増やすのが最もリスクの低い方法です。
コネクションリークとは|原因・検知・防ぎ方
コネクションリークとは、借りた接続を返却しないまま放置してしまうバグです。時間の経過とともに使える接続が減り、最終的にシステムが停止します。
原因のほとんどは、例外発生時にclose()がスキップされるケースです。
NGパターン:例外が起きるとcloseされない
OKパターン:try-with-resourcesで確実にclose
私が過去に遭遇したケースでは、try-with-resourcesを使わないJDBC直書きコード(レガシーバッチ処理)で、例外発生後に30分おきに1接続ずつリークし、半日後にプール枯渇(maximumPoolSize=20)→サービス停止しました。
leakDetectionThreshold=2000を本番で有効化していれば、枯渇の数時間前にWARNログで気付けた事例です。
JDBCを直接使う場合は、必ずtry-with-resourcesを使ってください。Spring JdbcTemplateやSpring Data JPAを使っている場合は、フレームワーク側が接続の取得と返却を行うため、close忘れを意識する必要はありません。ただし@Transactionalの中で時間のかかる処理をすると、その間は接続を占有し続けます。
leakDetectionThresholdでコネクションリークを検知する
HikariCPのleakDetectionThresholdを設定すると、指定ミリ秒を超えて借りっぱなしの接続があった場合にログへ警告を出力します。
開発・テスト環境では有効にしておくことを強く推奨します。HikariCP公式の説明では、0なら無効で、有効にできる最小値は2000(2秒)です。この機能はログに警告を出すだけで、接続を強制的に閉じるわけではありません。
2000(2秒)を超えて返却されない接続があると、以下のようなWARNログが出力されます。
スタックトレースから「どのコードがリークしているか」を特定できます。長時間かかる正常なバッチ処理でも警告が出るため、閾値は想定する最長の処理時間より長めに設定してください。
よくあるエラー別・トラブルシューティング

本番で発生するトラブルの大半はこの3パターンに集約されます。エラーメッセージを確認して、対応する手順を実行してください。
接続タイムアウトエラー
意味:プールの接続がすべて貸し出し中で、connectionTimeout時間内に空きが取得できなかった。
確認手順(この順番で調べる):
- スロークエリログを確認する。数秒かかるSQLが頻発していると、その間ずっと接続が「使用中」になる。原因として多いのはスロークエリ。まず
EXPLAINでクエリを最適化する - HikariCPのデバッグログを有効にして状態を確認する
- SQLを最適化しても改善しない場合のみ、
maximumPoolSizeを増やす(計算式で上限を確認した上で) leakDetectionThresholdを有効にしてコネクションリークがないか確認する
接続数上限エラー
意味:DBのmax_connections設定値を超えて接続しようとした。
対応手順:
- 現在のDB接続数を確認する
- 「アプリ台数 × プールサイズ」がDB上限を超えていないか計算する
- バッチ処理など裏で動いているプロセスが接続を使い切っていないか確認する
- アプリ側の
maximumPoolSizeを「DB上限 ÷ アプリ台数」に削減する
エラー3:応答が全体的に遅い(エラーはないが重い)
確認手順:
- DBサーバーのCPU使用率を確認する。90%超えていれば、プールサイズを増やすのではなく絞ることで改善する(コンテキストスイッチの削減)
- アプリサーバーとDBサーバーが異なるAZ(Availability Zone)に配置されていないか確認する。クラウド環境ではAZをまたぐ通信は、同じAZ内の通信より遅延が大きくなる
- Actuatorメトリクスで
hikaricp.connections.pending(待ちキューの長さ)を確認する
Spring Boot Actuatorでプール状態を監視する

ログでの確認は開発向けです。本番環境ではActuatorとメトリクス監視ツールを組み合わせることで、常時モニタリングを行います。
Actuatorの有効化
監視すべき主要メトリクス
これらのメトリクスをPrometheus + Grafanaや、DatadogなどのAPMツールと連携させることで、「毎日12時台にActiveが5前後から20に急増し接続待ちが発生」といった時間帯別傾向を可視化できます。
アラートを設定しておけば、問題が顕在化する前に検知できます。
実務の感覚値として、hikaricp.connections.active が maximumPoolSize の 60〜70% で慢性的に張り付く場合、SQL最適化の余地が大きいサインです。
私のチームでは60%超が30分続いたらSlackに通知する閾値でアラートを運用しており、スロークエリの早期発見に役立っています。
Javaコネクションプールに関するよくある質問
HikariCP以外は使う意味がある?
新規開発ではまずHikariCPを選べば十分です。DBCP2・Tomcat JDBC・c3p0は主にレガシーシステムの保守で遭遇するもので、新規で採用する理由は少ないでしょう。比較の詳細は本記事内の「他のコネクションプールとの比較」セクションを参照してください。
コネクションプール vs スレッドプール
別物です。コネクションプールはDB接続の再利用、スレッドプールはスレッド実行資源の再利用を担います。Webアプリでは、アプリサーバーのスレッドプール数 >= コネクションプール数 という関係が望ましく、スレッド数のほうが少ないと接続が余り、多すぎると接続待ちが発生します。
Spring Boot 3/4での設定は?
基本は同じです。Spring Boot 3.x・4.x系(4.0は2025年11月、4.1は2026年6月リリース)ともHikariCPが引き続きデフォルトのDataSource実装で、spring.datasource.hikari.* の設定プレフィックスも従来と同じまま使えます。既存のSpring Boot 2.x向け設定をそのまま移行できます。Spring Boot 4.1系が管理するHikariCPは7.0系です。それより新しい版を明示的に使いたい場合は、Mavenなら <hikaricp.version> プロパティで管理バージョンを上書きします。
まとめ:計算に基づいた設定が重要
今回のポイントを整理します。
- Spring Bootでは何もしなくてもHikariCPが動いている。ただしデフォルト値のままでは本番に耐えられないケースが多い
- maximumPoolSizeは「DBコア数×2+スピンドル数」で計算する。大きくすると逆に遅くなる
- minimumIdleはmaximumPoolSizeと同値にして固定プール化する。接続数の変動コストをゼロにできる
- connectionTimeoutは5秒程度に短く設定する。障害時の連鎖ダウンを防ぐ
- JDBCを直接使う場合は必ずtry-with-resourcesを使う。コネクションリークを根本から防ぐ
- 開発環境ではleakDetectionThresholdを有効化する。リークを早期に発見できる
もしDB周りのパフォーマンスに悩んでいるなら、まずlogging.level.com.zaxxer.hikari=DEBUGを有効にして現状のActive接続数を計測することから始めてください。
数字を見れば、次のチューニング対象がすぐに特定できます。
| REV. | DATE | 内容 |
|---|---|---|
| 3 | 2026-10-04 | 記載内容の事実確認と修正 |
| 2 | 2026-09-04 | 2026年9月時点の情報で全体を見直し |
| 1 | 2025-11-27 | 初版 |


