한 줄 목표
Server 애플리케이션이 생성하는 PostgreSQL Runtime Hikari Connection에 공통 statement_timeout과 lock_timeout 안전선을 적용해,
장시간 SQL과 Lock 대기가 DB Connection을 과도하게 점유하지 않도록 합니다.
쉽게 설명하면
현재 Server의 DB 요청은 PostgreSQL이 응답하거나 외부에서 Transaction을 중단할 때까지 오래 대기할 수 있습니다.
느린 SQL 또는 비효율적인 조회
→ Runtime Connection 장시간 점유
→ Connection Pool의 사용 가능한 Connection 감소
→ 정상 API도 Connection을 얻지 못하고 지연
다른 Transaction이 Row Lock 보유
→ 후속 요청이 Lock을 계속 대기
→ Transaction과 Connection이 장시간 유지
→ 장애가 관련 없는 요청으로 확산
이번 작업에서는 Runtime Hikari Pool이 생성하는 각 물리 Connection에 공통 Timeout 기본값을 적용해 다음 원칙을 보장합니다.
개별 SQL은 정해진 시간 이상 실행되지 않습니다.
Lock 획득 대기시간은 SQL 전체 제한보다 짧게 설정합니다.
Timeout이 발생한 Transaction은 정상적으로 Rollback됩니다.
Rollback 후 Connection은 정상적으로 Pool에 반환되어 재사용되거나,
유효하지 않은 경우 안전하게 폐기됩니다.
배경과 현재 문제
현재 Server는 Spring Boot DataSource와 PostgreSQL Runtime 계정을 사용하지만,
Runtime Connection에 적용되는 공통 statement_timeout과 lock_timeout 정책이 명시되어 있지 않습니다.
애플리케이션 코드의 성능 최적화와 별개로 DB 수준의 최소 보호선이 없으면 다음 위험이 있습니다.
- 예상보다 오래 실행되는 SQL이 Runtime Connection을 장시간 점유
- Lock 경합이 해소될 때까지 요청이 과도하게 대기
- 일부 느린 요청이 Connection Pool 고갈로 확대
- 장애 상황에서 API 응답 지연과 Timeout 원인을 구분하기 어려움
- 로컬·CI·운영 환경별 Session 설정이 달라질 가능성
이번 Issue는 Query별 최적화가 아니라 Server Runtime Hikari Connection에 적용되는 공통 최소 안전선을 담당합니다.
책임 경계
#34: Runtime/Flyway Role 분리와 RLS 보안 경계
- Flyway Migration Role과 Spring Boot Runtime Role의 분리
- Runtime Role의 최소 권한과
NOSUPERUSER, NOBYPASSRLS, 비소유자 원칙
- RLS Policy와 Tenant 격리
- Transaction-local
app.company_id
- 제한된 bootstrap 함수와 권한 경계
#9: 분리된 DB Role의 배포 Provisioning과 Pool 운영
- #34에서 정의한 Role·권한 모델을 Demo/Staging PostgreSQL에 실제 적용
- 각 Role의 Credential 생성·회전과 배포 Secret 주입
prod Profile의 Runtime/Flyway Credential 연결
- Hikari Pool 크기·수명·배포 설정
- Hikari
connectionTimeout 등 Pool 대여 대기 정책
- 본 Issue가 정의한 Timeout 환경변수의 배포 연결
본 Issue: Runtime Connection의 PostgreSQL 실행 Timeout
- Server Runtime Hikari Connection의
statement_timeout
- Server Runtime Hikari Connection의
lock_timeout
- 값의 의미·기본값·허용 범위·검증
- Timeout 발생 후 Transaction Rollback
- Connection의 정상 반환·후속 요청 재사용 또는 안전한 폐기
- 실제 Session 적용값 검증
#9와 #34에서는 다음 설정을 추가하지 않습니다.
ALTER ROLE ... SET statement_timeout = ...;
ALTER ROLE ... SET lock_timeout = ...;
ALTER DATABASE ... SET statement_timeout = ...;
ALTER DATABASE ... SET lock_timeout = ...;
Server Runtime Connection에서는 본 Issue의 애플리케이션 설정을 두 Timeout의 단일 진실 공급원으로 사용합니다.
PostgreSQL 전역 설정으로도 같은 값을 별도 관리하지 않습니다.
Runtime Credential은 Server 애플리케이션 전용으로 사용합니다.
같은 Role을 사용하는 psql, 운영 스크립트 또는 별도 애플리케이션의 Connection은 본 Issue의 보장 범위에 포함하지 않으며,
필요한 경우 별도 Role과 Timeout 정책을 사용합니다.
확정한 적용 방식
HikariCP connectionInitSql을 사용합니다.
Hikari가 새 물리 Connection을 생성한 뒤 Pool에 등록하기 전에 하나의 초기화 SQL을 실행해 Session 범위 Timeout을 설정합니다.
SELECT
pg_catalog.set_config('statement_timeout', '30000ms', false),
pg_catalog.set_config('lock_timeout', '3000ms', false);
pg_catalog.set_config(..., false)는 현재 물리 Connection의 Session 범위에 적용됩니다.
Transaction마다 초기화 SQL을 반복 실행하지 않습니다.
선택 이유
- Server 애플리케이션의 Runtime Hikari Connection에만 적용 가능
- 새 물리 Connection 생성 시 동일 설정 적용
- Runtime Role이나 Migration 변경 불필요
- Flyway Connection과 책임 경계 유지
- 로컬 및 PostgreSQL 통합 테스트에서 재현 가능
- 설정 오류와 Session 적용 실패를 Connection 생성 단계에서 발견 가능
주의사항
connectionInitSql은 새 물리 Connection 생성 시 실행되며 기존 Session을 실시간으로 갱신하는 기능이 아닙니다.
- 초기화 SQL이 실패한 Connection은 정상 Pool Connection으로 등록되어서는 안 됩니다.
- 애플리케이션 설정은 시작 전에 확정하며 Runtime hot reload는 지원하지 않습니다.
- 향후 Pool 구현이나 DB Proxy가 변경되면 Session 초기화 보장 여부를 다시 검토합니다.
설정 정책
statement_timeout과 lock_timeout은 Duration으로 입력받습니다.
- PostgreSQL에 전달할 때 millisecond 단위의 명시적인 값으로 변환합니다.
- 음수, 파싱 실패, 지원하지 않는 단위와 millisecond 미만 정밀도는 거부합니다.
lock_timeout < statement_timeout을 강제합니다.
- 초기 MVP 기본값은
statement_timeout=30s, lock_timeout=3s로 설정합니다.
0은 Timeout Guard 비활성화를 의미하므로 허용하지 않습니다.
- 필수 설정 누락과 잘못된 값은 Connection 생성 전 애플리케이션 설정 검증에서 Fail-fast 처리합니다.
- 초기화 SQL 실패 시 해당 Connection을 Pool에 등록하지 않습니다.
- 정상 초기화된 Runtime Connection을 획득할 수 없는 상태를 정상 DB 상태로 판단하지 않습니다.
- Runtime 코드에서 두 값을
SET SESSION으로 다시 변경하지 않습니다.
- 업무별 예외가 필요하면 후속 Issue에서
SET LOCAL 기반 Transaction-local override만 허용합니다.
두 기본값은 영구적인 최적값이 아니며, Staging의 정상 Query 실행시간과 Lock 경합 관측 결과에 따라 후속 Issue에서 조정할 수 있습니다.
구현 범위
설정 모델
Runtime Connection 적용
오류 처리
테스트 시나리오
1. 설정 유효성
2. Runtime Role과 Session 적용
3. Statement Timeout
4. Lock Timeout
5. Connection Pool
6. 기존 PostgreSQL 보안 기능 회귀
7. 기존 Outbox 회귀
8. 설정 격리
9. 로그와 보안
완료 조건
관측과 보안 요구사항
- Timeout 발생 횟수는 SQL이나 Parameter가 아닌 제한된 내부 코드로 구분합니다.
- SQL·Parameter·개인정보를 Metric Label로 사용하지 않습니다.
- DB Credential을 로그에 기록하지 않습니다.
- 무제한 retry를 금지합니다.
- 사용자 요청을 무기한 대기시키지 않습니다.
- 개발 Profile의 의도적인 Hibernate SQL 출력 정책은 이번 Issue에서 변경하지 않습니다.
이번 Issue에서 하지 않는 것
ALTER ROLE·ALTER DATABASE·PostgreSQL 전역 설정으로 Timeout 구성
- Flyway Connection에 Runtime Timeout 적용
- Flyway Migration 파일 변경
transaction_timeout
idle_in_transaction_session_timeout
- Hikari tuning 전체
- Tenant Context 구현 또는 RLS Policy 변경
- AOP·Annotation 기반 Timeout
- Query 최적화, N+1 개선, Index 분석
- Pool sizing과
max_connections 산정
- Runtime Credential을 사용하는 외부 Client의 Timeout 보장
- Runtime hot reload
후속 Issue 후보
PostgreSQL Session 종료 Guard
transaction_timeout
idle_in_transaction_session_timeout
- Session 종료 감지
- Pool recovery
- Metric·Alert
업무별 Timeout 정책
- Read/Write 분리
- Batch 작업
- Outbox 전용 Timeout
- API별 Transaction-local override
선행·연결 관계
선행 Issue는 없습니다.
한 줄 목표
Server 애플리케이션이 생성하는 PostgreSQL Runtime Hikari Connection에 공통
statement_timeout과lock_timeout안전선을 적용해,장시간 SQL과 Lock 대기가 DB Connection을 과도하게 점유하지 않도록 합니다.
쉽게 설명하면
현재 Server의 DB 요청은 PostgreSQL이 응답하거나 외부에서 Transaction을 중단할 때까지 오래 대기할 수 있습니다.
이번 작업에서는 Runtime Hikari Pool이 생성하는 각 물리 Connection에 공통 Timeout 기본값을 적용해 다음 원칙을 보장합니다.
배경과 현재 문제
현재 Server는 Spring Boot DataSource와 PostgreSQL Runtime 계정을 사용하지만,
Runtime Connection에 적용되는 공통
statement_timeout과lock_timeout정책이 명시되어 있지 않습니다.애플리케이션 코드의 성능 최적화와 별개로 DB 수준의 최소 보호선이 없으면 다음 위험이 있습니다.
이번 Issue는 Query별 최적화가 아니라 Server Runtime Hikari Connection에 적용되는 공통 최소 안전선을 담당합니다.
책임 경계
#34: Runtime/Flyway Role 분리와 RLS 보안 경계
NOSUPERUSER,NOBYPASSRLS, 비소유자 원칙app.company_id#9: 분리된 DB Role의 배포 Provisioning과 Pool 운영
prodProfile의 Runtime/Flyway Credential 연결connectionTimeout등 Pool 대여 대기 정책본 Issue: Runtime Connection의 PostgreSQL 실행 Timeout
statement_timeoutlock_timeout#9와#34에서는 다음 설정을 추가하지 않습니다.Server Runtime Connection에서는 본 Issue의 애플리케이션 설정을 두 Timeout의 단일 진실 공급원으로 사용합니다.
PostgreSQL 전역 설정으로도 같은 값을 별도 관리하지 않습니다.
Runtime Credential은 Server 애플리케이션 전용으로 사용합니다.
같은 Role을 사용하는
psql, 운영 스크립트 또는 별도 애플리케이션의 Connection은 본 Issue의 보장 범위에 포함하지 않으며,필요한 경우 별도 Role과 Timeout 정책을 사용합니다.
확정한 적용 방식
HikariCP
connectionInitSql을 사용합니다.Hikari가 새 물리 Connection을 생성한 뒤 Pool에 등록하기 전에 하나의 초기화 SQL을 실행해 Session 범위 Timeout을 설정합니다.
pg_catalog.set_config(..., false)는 현재 물리 Connection의 Session 범위에 적용됩니다.Transaction마다 초기화 SQL을 반복 실행하지 않습니다.
선택 이유
주의사항
connectionInitSql은 새 물리 Connection 생성 시 실행되며 기존 Session을 실시간으로 갱신하는 기능이 아닙니다.설정 정책
statement_timeout과lock_timeout은Duration으로 입력받습니다.lock_timeout < statement_timeout을 강제합니다.statement_timeout=30s,lock_timeout=3s로 설정합니다.0은 Timeout Guard 비활성화를 의미하므로 허용하지 않습니다.SET SESSION으로 다시 변경하지 않습니다.SET LOCAL기반 Transaction-local override만 허용합니다.두 기본값은 영구적인 최적값이 아니며, Staging의 정상 Query 실행시간과 Lock 경합 관측 결과에 따라 후속 Issue에서 조정할 수 있습니다.
구현 범위
설정 모델
DB_STATEMENT_TIMEOUT환경변수 주입, 기본값30sDB_LOCK_TIMEOUT환경변수 주입, 기본값3s0·음수·파싱 실패·미지원 단위·millisecond 미만 값 거부lock_timeout < statement_timeout검증Runtime Connection 적용
connectionInitSql구성pg_catalog.set_config를 사용하는 하나의 SQL 문으로 두 Session Timeout 설정오류 처리
노출 금지
개인정보 노출 금지
테스트 시나리오
1. 설정 유효성
lock_timeout < statement_timeout허용0거부30s·3s기본값 검증2. Runtime Role과 Session 적용
ALTER ROLE SET없이 초기화 SQL 성공pg_catalog.current_setting으로 두 Session 적용값 확인판단하지 않음
3. Statement Timeout
SELECT pg_sleep(...);4. Lock Timeout
5. Connection Pool
유효하지 않은 경우 안전하게 폐기
6. 기존 PostgreSQL 보안 기능 회귀
7. 기존 Outbox 회귀
8. 설정 격리
9. 로그와 보안
완료 조건
관측과 보안 요구사항
이번 Issue에서 하지 않는 것
ALTER ROLE·ALTER DATABASE·PostgreSQL 전역 설정으로 Timeout 구성transaction_timeoutidle_in_transaction_session_timeoutmax_connections산정후속 Issue 후보
PostgreSQL Session 종료 Guard
transaction_timeoutidle_in_transaction_session_timeout업무별 Timeout 정책
선행·연결 관계
선행 Issue는 없습니다.