Postgres의 LISTEN/NOTIFY 기능은 실시간 알림, 스트림, 발행/구독(pub/sub) 시스템에 강력한 도구로 활용될 수 있음에도 불구하고, 그동안 확장성(scalability)이 떨어진다는 오명을 안고 있었습니다. 이는 NOTIFY 호출 시 발생하는 전역 배타적 잠금(global exclusive lock) 때문인데, 이 잠금이 트랜잭션(transaction) 커밋(commit) 과정 전체를 직렬화(serialize)하여 처리량(throughput)을 크게 저해하는 원인이었습니다.
문제의 핵심은 Postgres가 알림의 트랜잭션 커밋 순서를 보장하기 위해 전역 잠금을 사용한다는 점입니다. NOTIFY를 호출하는 트랜잭션이 커밋을 시작할 때 이 잠금을 획득하고, 디스크에 데이터가 완전히 기록될 때까지 해제하지 않습니다. 이로 인해 개별 쓰기 작업이 순차적으로 처리될 수밖에 없어, Postgres의 그룹 커밋(group commit)과 같은 최적화 기능이 무력화됩니다. 이전 구현에서는 초당 2.9K(2천9백) 건의 쓰기 작업만 가능했지만, DBOS 팀은 알림을 메모리에 버퍼링하고 주기적으로 일괄 처리하는 방식으로 이 병목 현상을 해결했습니다. 알림 자체가 데이터의 원천(source of truth)이 아니라 데이터 변경을 알리는 '핑(ping)' 역할만 한다는 점에 착안한 것입니다.
이 최적화 기법을 통해 개별 쓰기 작업은 전역 잠금의 영향을 받지 않고 빠르게 처리될 수 있으며, 버퍼가 가득 찼을 때만 단일 트랜잭션으로 알림을 플러시(flush)하여 잠금 경합을 최소화합니다. 그 결과, 단일 Postgres 서버에서 초당 6만 건의 쓰기 작업을 밀리초(ms) 단위의 낮은 지연 시간으로 달성하는 데 성공했습니다. 이는 실시간 채팅, 대규모 언어모델(LLM) 응답 스트리밍 등 고성능이 요구되는 애플리케이션에서 Postgres LISTEN/NOTIFY의 활용 가능성을 크게 확장하며, 개발자들이 데이터베이스를 더욱 효율적으로 사용할 수 있는 길을 열어줄 것으로 기대됩니다.
