문의 저장이 안 끝나면 풀부터 늘리지 않는다. 포스트그레 기본은 문장 제한, 락 대기, 트랜잭션 안 유휴를 0으로 둔다. 액션이 커밋 전에 메일을 기다리면 세션이 idle in transaction으로 남는다. 슈퍼베이스 역할은 익명 3초, 인증 8초, 대시보드 역할은 전역 2분 상한이다. 개발자, Next.js, 백엔드, API, PostgreSQL, 슈퍼베이스 기준으로 제한 숫자 칸만 보고 풀 글, 오토배큠 글과 자리를 섞지 않는다. 2026년 8월 공식 문서.
문의 저장이 안 끝나면 풀부터 늘리지 않습니다. 포스트그레 기본은 문장 제한, 락 대기, 트랜잭션 안 유휴를 모두 0으로 둡니다. 0은 꺼짐이라, 한 문이 끝나지 않아도 서버가 안 자릅니다. 액션이 커밋 전에 메일을 기다리면 세션이 idle in transaction으로 남고, 락과 죽은 튜플이 같이 묶입니다.
저는 12개 사이트 파트너십 저장을 연 채로 리센드를 기다린 날이 있습니다. 화면은 안 풀리고 풀은 찼습니다. 풀 고갈은 피지바운서 글, 응답 뒤 메일은 after 글입니다. 목록이 느린 칸은 페이지네이션 글입니다. 여기는 제한 숫자 칸만 봅니다.
풀 숫자를 올리기 전에 상태를 봅니다. active면 문장 제한, idle in transaction이면 트랜잭션 안 유휴, 락 대기는 lock 이벤트가 있을 때입니다.
파트너십 문의가 수 분째 스피너를 돌린 날이 있습니다. 저장은 이미 들어갔고, 같은 함수가 메일을 기다리고 있었습니다. 연결은 살아 있는데 쿼리가 없는 상태였습니다. 피지바운서 글은 연결이 반환되지 않아 풀이 찬 기록입니다. 오늘은 그 앞에, 세션이 왜 안 끝나는지 가르는 칸입니다.
칸
기본
언제 보나
끝나면
문장 제한
0, 꺼짐
한 문이 길게 돈다
그 문만 취소. 57014
락 대기
0, 꺼짐
다른 세션 락을 기다린다
그 문만 취소. 55P03
트랜잭션 안 유휴
0, 꺼짐
BEGIN 뒤 클라이언트가 멈춤
세션 종료, 롤백
세션 유휴
0, 꺼짐
트랜잭션 없이 놀고 있음
세션 종료. 풀러에는 잘 안 켬
트랜잭션 제한
0, 꺼짐. 17부터
짧은 문이 이어져 BEGIN이 길다
세션 종료. 준비된 트랜잭션은 제외
문서도 설정 파일에 문장 제한을 전역으로 넣지 말라고 적습니다. 모든 세션이 같이 잘립니다. 마이그레이션 잠금은 무중단 마이그레이션 글입니다. 재고 동시 쓰기는 낙관적 락 글입니다. 오늘은 초를 어디에 적을지입니다.
풀을 먼저 늘리지 않습니다 | 유휴 트랜잭션이 자리를 차지한 채로 한도만 올리면, 같은 패턴이 더 많은 연결로 늘어납니다. 상태를 본 뒤에 초를 넣습니다.
문장 제한과 락 대기, 유휴는 칸이 다르다
다섯 숫자는 서로 다른 시계입니다. 문장 제한은 한 문의 서버 처리 시간이고, 락 대기는 락을 얻는 동안만 돕니다. 트랜잭션 안 유휴는 클라이언트가 다음 문을 안 보내는 동안입니다.
포스트그레 18 문서는 단위 없이 쓰면 밀리초라고 적습니다. '15s'처럼 단위를 붙이는 편이 읽기 쉽습니다. 락 대기를 문장 제한과 같거나 더 크게 두면, 문서 그대로 문장 제한이 먼저 터져 락 대기는 의미가 없습니다. 트랜잭션 제한이 다른 둘보다 짧거나 같으면, 긴 쪽은 무시됩니다.
죽은 튜플이 안 지워지는 날은 오토배큠 글과 맞닿습니다. 열린 트랜잭션이 최근 죽은 줄을 아직 볼 수 있어서, 배큠이 그 줄을 못 지웁니다. 디스크가 느는 글과 자리를 섞지 않습니다. 여기는 그 트랜잭션을 몇 초에 자를지입니다.
역할에 문장 제한과 트랜잭션 안 유휴를 같이 넣는다
-- https://www.postgresql.org/docs/current/runtime-config-client.html
SHOW statement_timeout;
SHOW lock_timeout;
SHOW idle_in_transaction_session_timeout;
SHOW idle_session_timeout;
SHOW transaction_timeout;
-- 앱이 쓰는 역할. 단위를 붙인다
ALTER ROLE app SET statement_timeout = '15s';
ALTER ROLE app SET lock_timeout = '3s';
ALTER ROLE app SET idle_in_transaction_session_timeout = '20s';
-- idle_session_timeout 은 풀러 연결에 잘 안 켠다
active 와 idle in transaction 은 넣는 초가 다르다
커밋 전에 메일을 기다리면 세션이 남는 자리
BEGIN 뒤에 외부 HTTP를 두면, 쿼리는 끝났는데 세션은 트랜잭션 안 유휴입니다. 메일은 커밋 다음이나 after로 보냅니다.
문의 행을 넣은 뒤 같은 클라이언트에서 리센드를 기다린 적이 있습니다. 수신함이 느린 오후에 연결이 한동안 안 돌아왔습니다. 버튼 잠금은 폼 훅 글이고, 응답을 먼저 보내는 칸은 after 글입니다. 오늘은 그 대기가 데이터베이스 세션을 붙잡는 자리입니다.
주문과 알림을 같은 커밋에 맞춰야 하면 아웃박스 글입니다. 메일 본문을 트랜잭션 안에 넣지 말고, 행만 커밋한 뒤 워커가 보냅니다. 소프트 삭제 유니크는 부분 유니크 글입니다. 제한 숫자와 자리를 섞지 않습니다.
SELECT FOR UPDATE 뒤에 HTTP를 두지 않습니다 | 행 락을 잡은 채로 카카오, 토스, 리센드를 기다리면 다른 요청이 그 행에서 멈춥니다. 락 대기가 꺼져 있으면 더 오래 붙습니다.
슈퍼베이스 역할은 3초, 8초, 2분이 기본이다
클라이언트 API는 역할 초가 이미 있습니다. 익명 3초, 인증 8초입니다. 대시보드와 외부 도구가 쓰는 postgres 역할은 전역 2분 상한입니다. 서버 액션이 서비스 롤이면 기본이 비어 있어, 인증자 8초에 기대거나 직접 적어야 합니다.
슈퍼베이스 타임아웃 문서는 대시보드와 클라이언트 쿼리의 설정 상한을 60초로 둡니다. 그 이상은 수퍼바이저 세션 모드나 직접 연결입니다. 세션에서 SET statement_timeout 은 트랜잭션 모드 6543, 대시보드, 클라이언트 API에서는 안 됩니다. 직접 연결이나 세션 모드 5432만 됩니다.
역할
문장 제한 기본
어디서 쓰나
초를 어디에 적나
anon
3초
브라우저 익명
역할. 올리면 노티파이로 재로드
authenticated
8초
로그인 클라이언트
역할. 상한 60초
service_role
없음. 비면 인증자 8초
서버 액션, 배치
역할에 15~30초를 직접 적음
postgres
없음. 전역 2분 상한
대시보드, 프리즈마, 피에스큐엘
긴 인덱스는 세션 모드에서 SET
ORM 고르는 칸은 드리즐과 프리즈마 글입니다. 시각 저장은 타임스탬프 글입니다. 행 권한은 알엘에스 글입니다. 오늘은 역할 초만 봅니다.
슈퍼베이스 서비스 롤에 초를 적고 포스트그레스트를 재로드한다
-- https://supabase.com/docs/guides/database/postgres/timeouts
ALTER ROLE service_role SET statement_timeout = '15s';
ALTER ROLE service_role SET idle_in_transaction_session_timeout = '30s';
ALTER ROLE service_role SET lock_timeout = '3s';
SELECT rolname, rolconfig
FROM pg_roles
WHERE rolname IN ('anon', 'authenticated', 'postgres', 'service_role');
-- 클라이언트 API 역할 초를 바꿨으면
NOTIFY pgrst, 'reload config';
익명 3초, 인증 8초. 서비스 롤은 직접 적는다
설정 파일에 전역으로 넣으면 마이그레이션이 같이 죽는다
문장 제한을 postgresql.conf 에 넣지 않습니다. 문서가 모든 세션에 영향을 준다고 말립니다. 앱 역할에만 적고, 인덱스 생성 세션은 그 연결에서만 풉니다.
동시 인덱스 생성을 15초 문장 제한 아래에서 돌리면, 테이블이 큰 날 중간에 잘립니다. 무중단 마이그레이션 글이 세션에 문장 제한과 락 대기를 명시하라고 적어 둔 자리입니다. 앱과 마이그레이션이 같은 역할을 쓰면, 앱 초가 배포 문을 자릅니다. 마이그레이션 역할과 앱 역할을 나눕니다.
전역을 4초로 낮추는 슈퍼베이스 예는 모든 역할의 빈 값을 덮습니다. 대시보드 긴 조회도 같이 짧아집니다. 역할 칸이 비어 있는 서비스 롤만 손보는 편이 안전합니다.
인덱스 세션만 문장 제한을 잠시 푼다. 전역 파일은 건드리지 않는다
-- 세션 모드 또는 직접 연결에서만
SET statement_timeout = '30min';
SET lock_timeout = '5s';
CREATE INDEX CONCURRENTLY inquiry_email_live_idx
ON inquiry (email)
WHERE deleted_at IS NULL;
-- 확인
SHOW statement_timeout;
세션 유휴를 풀러에 켜지 않습니다 | 문서가 미들웨어가 예기치 않은 종료를 잘 못 다룰 수 있다고 적습니다. 트랜잭션 안 유휴만 앱 역할에 넣고, 세션 유휴는 대화형 계정에만 둡니다.
상태를 본 뒤에 숫자를 넣는 한 바퀴
먼저 누가 오래 붙잡는지 봅니다. 상태, 트랜잭션 나이, 대기 이벤트를 한 표로 적고, 그다음 역할 초를 넣습니다. 초를 넣은 뒤 같은 조회를 한 번 더 합니다.
관리 목록이 오프셋으로 느려진 칸은 페이지네이션 글입니다. 여기 조회는 그 목록을 고치는 쿼리가 아닙니다. 지금 붙어 있는 세션이 문을 실행 중인지, 트랜잭션만 열어 둔 채 메일 쪽을 보는지 가르는 표입니다.
지금 붙은 세션의 상태와 나이를 본다
-- https://www.postgresql.org/docs/current/monitoring-stats.html
SELECT pid,
usename,
state,
wait_event_type,
wait_event,
now() - xact_start AS xact_age,
now() - query_start AS query_age,
left(query, 80) AS query
FROM pg_stat_activity
WHERE datname = current_database()
AND pid <> pg_backend_pid()
ORDER BY xact_start NULLS LAST;
상태와 나이를 적은 뒤에 역할 초를 넣는다
오늘 앱 역할에 초 하나만 적는다
오늘 할 일은 앱 역할에 문장 제한 15초와 트랜잭션 안 유휴 20초입니다. 락 대기는 3초입니다. 메일은 커밋 밖으로 옮깁니다. 풀 한도와 전역 파일은 그대로 둡니다.
노드 풀이면 새 연결마다 SET 를 한 줄 넣을 수 있습니다. 슈퍼베이스 트랜잭션 모드면 SET 이 안 붙으니 역할에 적습니다. 저는 파트너십 액션부터 이 숫자를 넣었습니다. 화면이 풀린 뒤에야 풀 글의 연결 수를 다시 봤습니다.
오늘 한 줄 | 풀 한도보다 역할 초가 먼저입니다. 문장 제한 15초, 트랜잭션 안 유휴 20초, 메일은 커밋 다음입니다.
참고 자료
포스트그레 18 클라이언트 기본값 | 문장 제한, 트랜잭션 제한, 락 대기, 트랜잭션 안 유휴, 세션 유휴. 기본 0. 2026년 8월 확인