OpenAI가 PGConf.dev 2025에서 발표한 PostgreSQL 운영 및 확장 노하우와 실제 문제 사례, 그리고 커뮤니티에 요구하는 기능 제안까지 담은 인프라 인사이트를 한글로 정리했다.
PGConf.dev 2025 글로벌 개발자 컨퍼런스에서, OpenAI의 Bohan Zhang이 OpenAI의 PostgreSQL 활용 베스트 프랙티스를 공유하며, 세계적으로 손꼽히는 유니콘 기업의 데이터베이스 운영기를 공개했다.
OpenAI에서는 하나의 writer와 여러 reader로 구성된 언샤딩 아키텍처를 사용하고 있습니다. 우리는 PostgreSQL이 대규모 읽기 트래픽에서도 우아한 확장이 가능함을 보여주고 있습니다.
— PGConf.dev 2025, OpenAI의 Bohan Zhang
Bohan Zhang은 OpenAI Infrastructure 팀 소속으로, Carnegie Mellon University의 Andy Pavlo 교수 지도 하에 공부했고, 함께 OtterTune을 공동 창업하기도 했다.
PostgreSQL은 OpenAI의 대부분 핵심 시스템을 뒷받침하는 핵심 DBMS다. 만약 PostgreSQL이 장애를 일으키면 OpenAI의 주요 서비스 다수가 직접 타격을 받게 된다. 실제로 PostgreSQL 이슈로 인해 ChatGPT 서비스가 중단된 사례도 여러 차례 있었다.
OpenAI는 Azure의 매니지드 DB 서비스를 이용하며, 샤딩 없는 전형적인 PostgreSQL 마스터-리플리카 복제 구조를 쓴다. 즉, 하나의 프라이머리(마스터)와 40개 이상의 리플리카로 구성하고 있다. 월 5억명 이상의 사용자를 가진 OpenAI와 같은 서비스에서 확장성은 무엇보다 중요한 과제다.
OpenAI의 프라이머리-리플리카 구조는 읽기 확장성에서는 매우 좋으나, '쓰기 요청'이 최대 병목 포인트로 부상했다. 이를 해결하기 위해 OpenAI는 최대한 쓰기 작업을 분산하고, 신규 서비스가 프라이머리 DB에 추가로 부담을 주지 않도록 조치했다.
PostgreSQL의 MVCC(Multi-Version Concurrency Control) 설계 특성상 테이블 및 인덱스 팽창과 같은 문제도 나타난다. 자동 vacuum 등의 튜닝이 어려울 수 있는데, 모든 쓰기가 새로운 버전을 생성하며, 인덱스 접근시 추가적인 visible 체크가 필요하기 때문이다. 이러한 설계는 리플리카 확장 시 여러 도전과제로 이어진다—예를 들면 WAL(Write-Ahead Logging)의 증가는 복제 지연을 유발할 수 있고, 리플리카가 늘면 네트워크 대역폭이 병목이 되기도 한다.
이런 문제를 풀기 위해 다음과 같은 다양한 노력을 기울였다.
첫 번째는 프라이머리에서 쓰기 작업 피크를 완화하는 것이다. 예를 들면:
또한 읽기 요청은 최대한 리플리카에 오프로딩한다. 프라이머리에서 제거할 수 없는 읽기(읽기-쓰기 트랜잭션 등)는 효율을 극대화한다.
두 번째는 쿼리 레이어 최적화다. 긴 트랜잭션은 GC 지연 및 자원 점유를 유발하므로, "Idle in Transaction" 세션에 세션/스테이트먼트/클라이언트별 타임아웃을 적용했다. 복잡한 멀티 조인(한 번에 12개 테이블 등) 쿼리도 적극적으로 최적화했다. PT에서는 ORM 남용이 비효율 쿼리로 쉽게 이어지기 때문에 주의하라고 강조했다.
프라이머리 DB는 명백한 단일 장애점이다. 만약 이 노드가 다운되면 쓰기 작업이 불가능하다. 하지만 읽기 전용 리플리카는 많기 때문에 일부가 비정상이어도 나머지에서 읽기가 가능하다. 실제로 주요 요청 대부분은 read only이므로 프라이머리 장애 상황에서도 계속 서비스가 가능하다.
더 나아가, 요청을 우선순위별로 분리하여, 고우선순위 요청은 전용 리드온리 리플리카에 할당, 저우선순위 요청의 간섭을 막는다.
네 번째는 이 클러스터에서는 최소한의 스키마 변경만 허용한다는 것이다:
또, 운영 중 1초 이상 지속되는 Long query가 스키마 변경을 장시간 블럭하여 결국 스키마 변경이 실패하는 문제가 있다. 이에, 어플리케이션 측에서 느린 쿼리를 튜닝/오프로드하도록 했다.
OpenAI는 실제 겪은 장애 케이스도 공유했다:
마지막으로, Bohan은 PostgreSQL 개발 커뮤니티에 아래와 같은 이슈와 기능 제안을 남겼다:
pg_stat_statements
는 쿼리별 평균 응답시간만 제공하고, p95/p99 latency는 비노출되어 있다. 히스토그램 또는 퍼센타일 지표를 노출해 달라PGConf.Dev 2025가 비록 개발 중심 행사지만, 사용자사례(특히 OpenAI처럼 실제 스케일의 극한 활용 사례)가 공유된다면 코어 개발자들도 흥미로워한다. 이들이 평소 실제 인터넷 대규모 운영환경을 직접 경험하는 경우는 드물기 때문.
2017년 말, 노풍은 탄탄(탄탄: 중국 소셜서비스)에서 수십개 PostgreSQL 클러스터(당시 중국 최대급, 약 2.5M QPS)를 운영했다. 당시 최대 클러스터는 33개 리플리카에 40만 QPS를 기록했다. 병목도 역시 단일 노드의 write 성능이었고, 어플리케이션 차원에서 샤딩을 도입해 해결했다.
OpenAI가 겪는 문제와 해결책 모두 익숙한 내용이다. 다만 8년 전과 달리 최신 하드웨어 성능이 워낙 강력해 샤딩 없이도 단일 PostgreSQL 클러스터로 모든 서비스를 수용할 수 있게 된 점이 새롭다. 이는 "분산 데이터베이스가 꼭 필요한 것은 아니다"라는 주장에 강한 근거가 된다.
OpenAI는 Azure 관리형 PostgreSQL, 고스펙 서버, 40여개 리플리카(리전 간 포함)—전체 QPS 약 100만. 모니터링 도구로 Datadog을 쓰고, 서비스는 쿠버네티스를 통해 PgBouncer(connection pool)로 RDS 클러스터에 접속한다.
OpenAI는 전략적 고객이라 Azure PostgreSQL팀이 직접적이고 세심한 지원을 제공한다. 하지만 클라우드 서비스가 아무리 좋아도, 운영/어플리케이션 측의 높은 역량과 경각심이 필수다. 실제로 OpenAI도 PostgreSQL 운영에서 여러 함정에 빠지곤 한다.
고가용성은 발표에서 다뤄지지 않았으나, Azure RDS가 이를 제공하는 듯하다. 모니터링은 Datadog을 사용—OpenAI조차 가격이 매우 비싸다고 느낀다.
컨퍼런스 후 밤샘 술자리에서 노풍, Bohan, 그리고 두 DB 창업자가 오랫동안 이야기 나눴지만, 여기서 공개할 수 없는 뒷이야기도 많다고 한다—ㅎㅎ.
Bohan이 제기한 요구 및 제안에 대해 현장에서 답변을 남긴다. 사실 OpenAI가 원하는 기능 대부분은 이미 PostgreSQL 생태계 어딘가에는 있다. 다만 코어 PostgreSQL 또는 Azure RDS에서는 공식적으로 열리지 않았을뿐.
PostgreSQL은 인덱스 disable 기능을 제공한다. 시스템 카탈로그 pg_index의 indisvalid 필드를 false로 바꾸면, 플래너가 해당 인덱스를 무시(선택하지 않음)하는데, DML 동작시 유지(업데이트)만 한다. 이는 concurrent index 생성시 isready, isvalid flag와 동일 메커니즘이니 마법은 아니다.
단, OpenAI처럼 RDS 환경에선 슈퍼유저 권한이 없어 시스템 카탈로그 수동 변경이 불가하다.
하지만 굳이 disable이 목적이라면, 모니터링 뷰에서 인덱스가 프라이머리/리플리카 양쪽에서 장기간 접근 없는 것을 확인 후, 안전하게 drop하는 것이 더 현실적이다.
Pigsty 모니터링 시스템을 활용하면 실시간 인덱스 전환 과정도 추적할 수 있다.
CREATE UNIQUE INDEX CONCURRENTLY pgbench_accounts_pkey2
ON pgbench_accounts USING BTREE(aid);
-- 이전 인덱스를 invalid로 선언(더 이상 사용 안함, 유지만)
UPDATE pg_index SET indisvalid = false
WHERE indexrelid = 'pgbench_accounts_pkey'::regclass;
pg_stat_statements가 P95~99 분포 지표를 제공하지 않는 이유는 메모리 사용량이 급증(수십 배)해서이다. 유지보수자에 확인해본 결과 단기 지원 계획은 없다. pgbouncer도 마찬가지.
하지만 pg_stat_monitor 확장 모듈은 Percentile latency를 제공한다(성능 오버헤드는 감안 필요). 두 번째는 eBPF로 패시브 RT 측정, 세 번째는 어플리케이션 DAL 레이어에서 쿼리 대기시간 자체 측정 등 대안이 있다.
가장 우아한 방법은 eBPF지만 Azure 관리형 DB 특성상 서버 액세스가 불가능해 현실적으로 어렵다.
사실 PostgreSQL 로그(설정: log_statement=ddl 또는 그 이상)를 통해 모든 DDL 변경이 기록된다. pgaudit 확장도 사용 가능하다.
문제는 로그가 아니라 SQL로 쿼리 가능해야 할 때다. CREATE EVENT TRIGGER로 DDL 이벤트를 테이블에 기록하거나, pg_ddl_historization 확장 이용이 대안(이미 패키징 완성됨). 다만 이것도 슈퍼유저 권한이 필요하다(특히 Azure는 지원이 약함).
State=Active, WaitEvent=ClientRead는 백엔드 프로세스가 SQL 문장 처리 중이며, 아직 ReadyForQuery를 클라이언트에 전달하지 않은 상태임을 의미한다. 일반적으로 row lock, buffer pin 등 리소스 사용 중이며, 주로 COPY FROM STDIN idle 상태나 TCP 블록, 혹은 특이하게 BIND~EXECUTE 사이 통신에서 발생할 수 있다. 버그라기보다는, 실제 커넥션 액티비티에 따라 다르다.
CPU 관점에서는 idle임에도 State는 active일 수 있으나, 이는 PostgreSQL이 statement 실행 상태만을 추적하기 때문이다. Pigsty 등에서는 HAProxy 차원에서 커넥션 최대수명(예: 24시간, 강한 보안시 1시간) 제한도 하고, 가능한 클라이언트 커넥션풀에서 직접 커넥션 수명 관리 권장이 필요하다. Azure 관리형 PostgreSQL에서 이게 지원되는지는 불명이다.
기본 파라미터는 지나치게 보수적이다(예: 메모리 256MB, 심지어 256KB도 허용!--생산 DB가 1TB 물리 메모리로도 256MB 세팅에서 꽤 오래 잘 버티기도 함). 물론 이 덕분에 어떤 환경에서도 PostgreSQL이 구동될 수 있다. 초기치 튜닝은 RDS 등에서 Heuristic 기반으로 잘 지원되고 있다. 그러나 여전히 initdb, pg_ctl 등에서 CPU/Mem/Disk 상황 자동 탐지 및 최적값 세팅 옵션이 추가되면 더욱 좋겠다.
OpenAI가 겪는 도전은 PostgreSQL 자체보다 Azure 관리형 DB의 제약에서 오는 경우가 많다. 만약 이 한계를 넘으려면 클라우드의 IaaS 계층에서 직접 셀프호스팅(PostgreSQL+Pigsty 등) 클러스터를 NVMe SSD 인스턴스에 구성하는 방법이 있다.
사실 Pigsty도 노풍이 이런 스케일의 PostgreSQL 운영 한계를 겪으며 직접 만든 시스템으로, 셀프호스팅 RDS에 가깝다. 많은 문제점이 이미 Pigsty에서 해결책이 구현되어 있다.
OpenAI에도 도움을 제안하고 싶지만, 이토록 빠르게 성장하는 기업에선 인프라 튜닝은 우선순위가 아닐 수도 있다. 다행히 실력있는 PostgreSQL DBA들이 계속 한계를 뚫고 혁신하고 있다.