bug: HikariCP connection pool exhaustion causes backend outages #152
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
The backend repeatedly exhausts its HikariCP connection pool (
total=10, active=10, idle=0) roughly 8–10 minutes after startup, causing all subsequent requests to fail with a 30-second timeout. A container restart temporarily fixes it, but it recurs.Root cause
spring.jpa.open-in-viewis enabled (Spring Boot default).This anti-pattern holds a database connection open for the entire duration of each HTTP request — from the moment the request arrives until the HTTP response is fully written. Under concurrent load (e.g. the dashboard's
Promise.allSettledfires 3 API calls in parallel per page load), the pool of 10 connections fills up. Once full, new requests block for 30 seconds before failing.This is confirmed in the startup logs:
Impact
Fix
Add to
backend/src/main/resources/application.yaml:This releases DB connections as soon as a
@Transactionalmethod returns, instead of holding them for the full request lifecycle. All existing service methods are already properly bounded with@Transactional, so no other code changes are needed.Acceptance criteria
spring.jpa.open-in-view: falseadded toapplication.yamlLazyInitializationExceptionappears in logs after the change (all needed associations should be eagerly fetched or loaded within transactions)Already fixed.
spring.jpa.open-in-view: falseis set inapplication.yamlwith an explanatory comment.Lazy-loading safety audit — confirmed all lazy relationships are safe with the current setting:
Person.nameAliases(@OneToMany, lazy)@JsonIgnore— never serializedPersonNameAlias.person(@ManyToOne(LAZY))@JsonIgnore— never serializedNotification.recipient(@ManyToOne(LAZY)).getId()used inside@TransactionalPasswordResetToken.user(@ManyToOne(LAZY))@TransactionalInviteToken.createdBy(@ManyToOne(LAZY))InviteListItemDTObefore returningFull test suite (1213 tests) passes with no
LazyInitializationException.