Kafka는 빠르다 — 나는 Postgres를 쓸 것이다
(topicpartition.io)- Postgres의 퍼블리시/서브스크라이브(pub-sub) 및 큐(queue) 성능을 벤치마크해, 단일 데이터베이스로도 메시징 시스템을 대체할 수 있는 가능성 제시
 - 단일 4vCPU 노드에서 초당 5,036건 쓰기·25,183건 읽기, 3노드 복제 환경에서도 유사한 처리량 유지, 엔드투엔드 지연 186ms(p99) 수준
 - 대형 96vCPU 노드에서는 쓰기 238MiB/s, 읽기 1.16GiB/s 달성, CPU 사용률 10% 미만으로 여유 있는 처리 확인
 - 큐 테스트에서도 단일 노드 기준 초당 2,885건, 복제 환경에서도 2,397건 처리 가능, 대부분의 기업 규모에 충분한 성능
 - 복잡한 분산 시스템 대신 Postgres 단일 인프라로도 수 MB/s 규모의 워크로드 처리 가능성을 입증, “필요할 때까지 단순한 기술을 사용하라”는 실용적 접근 강조
 
기술 선택의 두 진영
- 기술 업계는 유행어 중심 진영과 상식 중심 진영으로 나뉨
- 전자는 “실시간”, “무한 확장”, “AI 기반” 등 마케팅 용어에 끌림
 - 후자는 단순성과 실용성을 중시하며, 불필요한 복잡성을 피함
 
 - 최근 Small Data와 Postgres 르네상스 두 흐름이 후자에 힘을 실음
- 데이터는 작아지고 하드웨어는 강력해짐
 - Postgres는 단일 시스템으로 다양한 목적형 솔루션을 대체 가능 (
jsonb,pgvector,tsvector등) 
 
벤치마크 개요
- 목적: Postgres가 pub/sub 메시징과 큐 처리에서 어느 정도 확장 가능한지 측정
 - 테스트 환경: AWS EC2 
c7i.xlarge(4vCPU) 및c7i.24xlarge(96vCPU) - 세 가지 구성 비교
- 단일 노드
 - 3노드 복제 클러스터
 - 대형 단일 노드
 
 
Pub/Sub 벤치마크 결과
- 
4vCPU 단일 노드
- 쓰기 4.8MiB/s(5,036msg/s), 읽기 24.6MiB/s(25,183msg/s), 지연 60ms(p99)
 - CPU 60% 사용, 디스크 46MiB/s 쓰기
 
 - 
4vCPU 3노드 복제
- 쓰기 4.9MiB/s, 읽기 24.5MiB/s, 지연 186ms(p99)
 - 처리량 유지, 연간 비용 약 $11,514
 
 - 
96vCPU 단일 노드
- 쓰기 238MiB/s(243kmsg/s), 읽기 1.16GiB/s(1.2Mmsg/s), 지연 853ms(p99)
 - CPU 10% 미만, 병목은 파티션당 쓰기 속도
 
 - 결론: 저·중규모 워크로드에서 Kafka와 경쟁 가능한 수준, 단순한 구조로도 수십 MB/s 처리 가능
 
Queue 벤치마크 결과
- 
SELECT FOR UPDATE SKIP LOCKED기반 단순 큐 구현 - 
4vCPU 단일 노드
- 2.81MiB/s(2,885msg/s), 지연 17.7ms(p99), CPU 60%
 
 - 
4vCPU 3노드 복제
- 2.34MiB/s(2,397msg/s), 지연 920ms(p99), CPU 60%
 
 - 
96vCPU 단일 노드
- 19.7MiB/s(20,144msg/s), 지연 930ms(p99), CPU 40~60%
 
 - 단일 노드로도 대부분 기업의 큐 처리량 요구 충족 가능
 
Postgres 사용 판단
- 대부분의 경우 Postgres 기본 선택이 합리적
- SQL로 메시지 디버깅, 수정, 조인 가능
 - Kafka 대비 운영 단순성 및 유지보수 용이
 
 - Kafka는 고성능에 최적화, 그러나 소규모 워크로드에는 과도한 선택
 - “조기 최적화는 모든 악의 근원”이라는 Donald Knuth의 경고 인용
- 수 MB/s 수준까지는 Postgres로 충분
 
 
최소 실행 인프라(MVI) 접근
- 
Minimum Viable Infrastructure: 조직이 이미 익숙한 기술로 최소한의 시스템 구축
- Postgres는 널리 채택되고 인력 확보 용이
 - 구성 요소가 적을수록 장애·운영 부담 감소
 
 - 불필요한 기술 도입은 조직적 오버헤드를 초래
- 학습, 모니터링, 배포, 운영 비용 증가
 
 
확장성 논의
- 
Postgres는 실제로 확장 가능
- OpenAI는 여전히 단일 쓰기 인스턴스 기반 Postgres 사용
 - 수억 명 사용자 규모에서도 안정적 운영
 
 - 대부분의 기업은 성장 속도가 완만해, 기술 교체까지 수년의 여유 존재
 - “바이럴 대비 설계”는 과도한 오버디자인
- “Coldplay 오프닝을 위해 마샬 앰프를 사는 것과 같다”는 비유 제시
 
 
결론
- 
“깨질 때까지 Postgres를 써라”
- 단순한 기술로도 충분히 높은 성능 확보 가능
 - 필요 이상으로 복잡한 분산 시스템 도입은 비효율적
 - Postgres는 현대 하드웨어와 함께 대부분의 워크로드를 감당할 수 있는 실용적 선택지
 
 
Hacker News 의견
- 
Pareto 원칙을 모든 상황에 적용하는 건 잘못된 해석임
Postgres가 Kafka보다 80%의 유스케이스를 20%의 노력으로 처리한다고 말하는 건 근거 없는 주장임
Pareto 원칙은 멱법칙 분포가 나타나는 상황에서만 의미가 있음
그냥 Postgres가 충분히 많은 유스케이스를 커버하고, 안정적이며, 검증된 도구라고 말하면 됨- 하지만 유스케이스와 기능의 매핑 자체가 멱법칙 분포를 따를 수도 있지 않겠냐는 의견도 있음
 
 - 
작은 규모(시간당 수백 이벤트)부터 대규모(시간당 수조 이벤트)까지 다뤄본 경험상, 먼저 큐가 정말 필요한지부터 따져봐야 함
- 단순히 DB 폴링으로 충분할 수도 있음
 - 한 노드에서 감당 가능하면 서버리스나 단일 프로세스로 처리 가능함
 - 분산 큐가 꼭 필요한 상황이 아니라면, 로드밸런싱 + REST API + 비동기 재시도로도 충분함
 - 정말 분산 큐가 필요하다면 Kafka 같은 전용 솔루션을 쓰는 게 낫다고 생각함
 
- Kafka는 사실 큐가 아니라 분산 로그 시스템임을 명확히 해야 함. MQ 대체재로 오해하는 경우가 많음
 - 스타트업에서는 종종 엔지니어들이 현재 프로젝트보다 다음 커리어를 염두에 두고 복잡한 기술을 선택하는 경향이 있음
 - 코드 구조를 PostgreSQL 기반 큐와 Kafka 기반 큐 모두 대응 가능하게 설계하면, 나중에 전환이 쉬움
 - PostgreSQL은 쓰기 부하가 커질 때 병목이 생기기 쉬움. UPDATE 스트림은 특히 고통스러움
 - Java 개발자로서 항상 큐가 필요했음. DB 폴링은 여러 소비자/생산자 환경에서 두통거리였음. Kafka의 consumer group과 partition은 상태 관리에 큰 도움이 되었음
 
 - 
Postgres를 모든 용도로 쓰는 접근은 위험함
락과 직렬화 레벨이 직관적이지 않아 성능 병목이 생길 수 있음
수십 년간 Postgres를 써왔지만, 맹목적인 신념으로 설계하면 안 됨- 트래픽 급증 시 수직 확장 한계가 문제임. Kafka는 트래픽 버스트를 흡수하지만 Postgres는 쉽게 과부하됨
 - Postgres에 지속 가능한 큐 구조가 추가되면 좋겠지만, Redis 수준을 넘는 확장은 어렵고 LISTEN/NOTIFY는 스케일링이 안 됨 (관련 링크)
 - 사실 모든 데이터 저장소는 동시성 모델을 이해해야 함. 관계형 DB 간에도 큰 차이가 있음
 - Postgres는 무한 확장은 어렵지만, 배치 처리와 단일 행 단위 작업으로 꽤 많은 데이터를 처리할 수 있음
 - 개인적으로는 먼저 Postgres로 시작하고, 병목이 생기면 그때 다른 시스템으로 전환하는 전략을 씀
 
 - 
SQL 기반 이벤트 로그 테이블 접근법이 효과적이라고 생각함
다만 클라이언트 측 도구 부족이 단점임. Kafka는 라이브러리 생태계가 풍부해서 그 점이 장점임
우리 회사는 서비스 간 이벤트 전달을 SQL 기반으로 표준화했음 (feedapi-spec)
Kafka만큼 성숙하진 않지만, 여러 스토리지 엔진을 지원하는 공통 라이브러리 스택으로 발전 가능성이 있음- LLM 기반 코드 생성 도구가 발전하면서 이런 클라이언트 갭을 메우는 게 쉬워졌음
 - Kafka를 싫어하는 입장에서 이런 접근이 훨씬 매력적으로 보임
 
 - 
요즘 사람들은 너무 새로운 기술에 끌리는 경향이 있음
Postgres는 훌륭하지만, 문제에 맞는 도구를 써야 함
Postgres는 pub-sub용으로 설계되지 않았고, Kafka는 그걸 위해 만들어졌음
모든 제품이 ‘모든 걸 다 하려는’ 트렌드는 피해야 함. 각자 한 가지를 잘하는 도구가 더 낫다고 생각함 - 
“단조 증가 오프셋 번호”를 구현하는 건 까다로운 문제임
단순 시퀀스는 트랜잭션 순서와 커밋 타이밍이 어긋나서 문제를 일으킴- 한 가지 방법은 카운터 전용 테이블을 두고, 같은 트랜잭션 내에서 잠금으로 순서를 보장하는 것임 (참고 링크)
 - Lamport Clock이나 Vector Clock을 이용해 분산 환경에서 순서를 보장할 수도 있음 (Lamport timestamp, Vector clock)
 - 절대적인 순서를 강제하기보다, 배치 단위로 번호를 할당하거나, 커밋 후 별도 프로세스가 순서를 부여하는 방식이 더 현실적임
 - “SELECT FOR UPDATE SKIP LOCKED”를 이용해 중복 처리를 피하는 방법도 있음
 
 - 
Kafka 벤치마크를 실제로 해봤는지 의문임
96 vCPU 환경에서 얻은 결과는 Kafka의 4 vCPU 설정으로도 가능함
Postgres 성능이 비정상적으로 느림
Kafka가 필요 없으면 쓰지 말되, Postgres로 5k msg/s를 자랑하는 건 의미 없음- Redpanda(카프카 호환 구현체)는 노트북에서도 초당 25만 메시지를 처리함 (영상 링크)
 - 288 vCPU 환경에서 그보다 낮은 성능은 낭비임
 - Postgres를 쓰는 이유가 단순히 “이미 있으니까”라면 이해하지만, 새 인프라 추가 전 검증은 필요함
 - Kafka는 적은 하드웨어에서도 네트워크 대역폭 한계까지 도달함
 - AWS에서 24xlarge 인스턴스 하나로 운영하는 건 비효율적이며, 그 비용이면 큰 Kafka 클러스터를 운영할 수 있음
 
 - 
“새 기술에 집착하는 사람들”과 “배운 것만 고집하는 사람들” 두 극단이 있음
현실적인 엔지니어는 그 중간에서 실용적인 선택을 함- 나는 세 번째 부류임: “지금 있는 건 다 별로고, 새 것도 결국 별로일 것”이라고 생각하는 타입임
 - 결국 중요한 건 문제를 합리적으로 보고 최적의 해결책을 찾는 태도임
 - 예를 들어 Elasticsearch를 Postgres로 대체하려는 시도는 가능하지만, 검색 기능의 완성도는 ES가 훨씬 뛰어남
 
 - 
Kafka의 핵심 기능은 소비자별 오프셋 제어임
여러 팀이 같은 토픽을 읽는 환경에서는 필수 기능임
오프셋을 앞뒤로 조정할 수 있는 점이 여러 번 생명줄이 되었음
Postgres 큐에서 이런 기능을 지원하는지 궁금함- 각 소비자가 자체 오프셋을 관리하면 되지 않겠냐는 의견도 있음
 - 하지만 대부분의 경우, 높은 처리량이 필요하지 않다면 Kafka의 복잡한 오프셋 관리까지는 필요 없음
 - 결국 비즈니스 요구 속도와 운영 복잡도의 균형 문제임
 
 - 
“버즈워드를 좇는 진영 vs 상식 진영”이라는 구도 자체가 틀림
Kafka를 Postgres로 재구현하려는 건 상식이 아님
정말 Kafka 수준의 기능이 필요하다면 그냥 Kafka를 쓰면 됨- 실제로는 Kafka 전체를 구현한 게 아니라, 단순한 pub-sub 쿼리 두 개만 만든 사례였음