TL;DR
Neon はアイドル時に Compute を自動停止できる serverless PostgreSQL ですが、アプリケーション側の設定によっては DB 接続が残り続け、期待どおり sleep しないことがあります。
今回、自分の個人開発環境で以下を見直しました。
- Neon の Scale to Zero / Autoscaling 設定
- Backend の WARMUP / Health Check 実装
- HikariCP の Connection Pool 設定
特に影響が大きかったのは HikariCP の設定です。
Spring Boot のデフォルト datasource は HikariCP ですが、設定次第ではアプリ起動中に idle connection が維持され続けます。個人開発規模では、多少のコールドスタートを許容してでも「不要な connection を積極的に閉じる」方が、Neon の sleep を活かしやすいと感じました。
┌──────────────────────────┐
│ Cloudflare Workers │
│ Cron Trigger │
└─────────────┬────────────┘
│
│ WARMUP request
│ No DB access
▼
┌──────────────┐ ┌──────────────────────────┐
│ User │ ───────▶ │ Backend │
│ Browser │ │ Spring Boot on Render │
└──────────────┘ │ │
│ WARMUP: No DB access │
│ App API: DB on demand │
└─────────────┬────────────┘
│
│ DB access only when needed
▼
┌──────────────────────────┐
│ Neon PostgreSQL │
│ Compute sleeps when idle │
└──────────────────────────┘
背景
個人開発しているサービスで、以下の構成を利用しています。
- Frontend: Vue.js + Cloudflare Pages
- Backend: Spring Boot + Render
- DB: Neon(PostgreSQL)
Neon は idle 状態になると Compute を停止できるため、アクセス頻度が低い個人開発サービスと相性が良いです。
一方で、Backend 側の設定によっては、
アプリにはアクセスされていないのに、Neon の Compute が active のままになる
という状態が起こります。
実際に自分の環境でも DB usage が想定より高くなっており、調査したところ主に以下の3点を見直す必要がありました。
技術スタック
- Java 21
- Spring Boot
- HikariCP
- Render
- Neon(PostgreSQL)
- Cloudflare Pages
- Cloudflare Workers
問題1: Neon の Scale to Zero / Autoscaling 設定
状況
まず Neon 側で、Compute が idle 時に停止する設定になっているかを確認しました。
Neon では Compute の autosuspend / Scale to Zero によって、一定時間アクセスがない場合に Compute を停止できます。
ただし、Autoscaling や Compute size の設定を触っている場合、意図した構成になっているかは確認しておいた方がよいです。
今回のケースでは、細かい autoscaling よりも「アクセスがない時間帯に確実に sleep すること」の方が重要でした。
※ Autoscaling 設定そのものが sleep を妨げると断定できるわけではありません。ここでは、まず Neon 側の停止条件と設定を確認した、という位置づけです。
対応
個人開発用途として、必要最小限の Compute 設定に見直しました。
問題2: WARMUP endpoint が DB アクセスしていた
状況
Backend 自体は Render 上で Spin Down させたくなかったため、Cloudflare Workers の Cron Trigger から定期的に WARMUP endpoint を呼び出していました。
Cloudflare Workers Cron Trigger
-> WARMUP endpoint
-> Spring Boot on Render
ただし、当初この WARMUP endpoint の処理内で DB アクセスが発生していました。
そのため、ユーザーアクセスがない時間帯でも WARMUP request のたびに Neon PostgreSQL へ接続が発生し、結果として Neon の Compute が sleep しづらい状態になっていました。
対応
WARMUP endpoint では DB にアクセスしないように変更しました。
Neon のような休眠・復帰がある DB では、スリープ防止 ping のたびに DB 接続を起こすのは無駄ですし、監視ノイズも増えます。なので「生存確認はアプリだけ」「実際の業務 API で DB が必要なときだけ接続する」ようにしています。
これにより、
- Backend は Spin Down しづらくする
- Neon PostgreSQL は idle 時に sleep できる
という状態を両立しやすくなりました。
Spring Boot 側の設定例
management:
endpoint:
health:
probes:
enabled: true
health:
db:
enabled: false
この設定では Spring Boot Actuator の DB health indicator を無効化できます。
ただし、readiness で DB 接続確認をしたい場合は、環境に応じて health group や custom health indicator を分けるのがよさそうです。
問題3: HikariCP が idle connection を保持していた
これが一番影響が大きかった
Spring Boot のデフォルト datasource は HikariCP です。
HikariCP は高性能な connection pool ですが、デフォルトでは connection を再利用する前提の挙動になります。
特に注意したいのは minimumIdle です。
HikariCP では minimumIdle を明示しない場合、基本的に maximumPoolSize と同じ値として扱われます。つまり、固定サイズの connection pool に近い挙動になり、idle connection が残りやすくなります。
Neon のように idle 時の停止を活かしたい場合、アプリケーション側が connection を保持し続けていると、期待どおり sleep しない原因になります。
対応
個人開発用途では、connection pool をかなり短めに閉じる設定へ変更しました。
方針としては、
多少 cold start が増えても、アクセスがない時間帯は DB を sleep させる
という判断です。
設定例
spring:
datasource:
hikari:
minimum-idle: 0
idle-timeout: 60000
各設定の意味
| 設定 | 内容 |
|---|---|
minimum-idle |
idle connection を最低何本維持するか。0 にすると保持しない方向に寄せられる |
idle-timeout |
idle connection を破棄するまでの時間(ms) |
注意点
この設定は、connection を積極的に閉じる方向に寄せています。
そのため、以下のような影響があります。
- 初回アクセス時の latency が増える
- DB が sleep していた場合、cold start が発生する
- アクセス頻度が高い環境では connection 再確立のコストが増える
個人開発や低トラフィックなサービスでは十分許容できましたが、本番サービスで常時アクセスがある場合は別途チューニングが必要です。
特に、アクセス頻度が高い production 環境では minimum-idle: 0 や短すぎる max-lifetime が逆効果になる可能性があります。
結果
設定変更後、以下を確認できました。
- Neon の Compute が期待どおり sleep するようになった
- active time が大幅に減った
- 不要な usage が減った
修正前は、4/11 20:00 に DB を作成してから、4/27 23:00 ごろに Neon Free Plan の 100 CU-hour / month の上限に到達していました。
期間としては約16.1日なので、単純計算では以下のようになります。
- 修正前: 約 6.2 CU-hour / day
- 修正後: 直近2日間の平均で約 0.34 CU-hour / day
単純比較ではありますが、1日あたりの CU-hour は約 6.2 から約 0.34 まで減り、約95%削減できた計算になります。
ただし、現状はお試しで知り合い数人にだけアプリを共有している状態なので、そもそものアクセス数はかなり少ないです。そのため、この削減率はあくまで自分の環境での目安として見ています。
まとめ
Neon のような serverless DB は便利ですが、DB 側の設定だけでなく、application 側の connection 管理も重要です。
特に Spring Boot + HikariCP 構成では、デフォルト設定のままだと connection pool が idle connection を保持しやすいため、Neon の sleep を活かしきれないことがあります。
個人開発では、以下の見直しが効果的でした。
- Neon 側で Scale to Zero / autosuspend 設定を確認する
- WARMUP endpoint では DB にアクセスしない
- HikariCP の
minimum-idleを0にする - idle connection を短めに破棄する
低トラフィックな個人開発サービスでは、Backend は warm 状態に保ちつつ、DB はアクセスがない時間帯に sleep させる構成の方がコスト最適化しやすいと思います。
近日中に、開発中のアプリについても別記事で紹介する予定です。
よければ、そちらもまた見てもらえるとうれしいです。

