Skip to content

Split View: pgrust: Postgres를 Rust로 다시 쓰고 회귀 테스트 100%를 통과했다 — 그게 정말 뜻하는 것

|

pgrust: Postgres를 Rust로 다시 쓰고 회귀 테스트 100%를 통과했다 — 그게 정말 뜻하는 것

들어가며 — "Postgres를 Rust로 다시 썼다"는 헤드라인

Malcolm Matis(GitHub malisper)가 pgrust를 공개했습니다. 한 줄 소개는 단순합니다 — "A Postgres rewrite in Rust". 헤드라인은 더 셉니다: Postgres 회귀 테스트(regression test)를 100% 통과한다. GeekNews와 Hacker News 상단에 올라온 이 소식은 두 가지 상반된 반응을 동시에 부릅니다 — "드디어 Postgres가 Rust로?"와 "AI로 몇 주 만에 짠 데이터베이스를 누가 프로덕션에 올리나?".

이 글은 둘 다 진정시키려 합니다. pgrust가 실제로 무엇을 해냈는지, 그리고 "회귀 테스트 100% 통과"라는 문장이 무엇을 뜻하고 무엇을 뜻하지 않는지를 정직하게 봅니다. 먼저 사실관계부터: pgrust는 Postgres 18.3 호환을 목표로 하고, 4만6천 개가 넘는 회귀 쿼리에서 Postgres와 동일한 출력을 냅니다. 디스크 포맷이 호환되어 기존 18.3 데이터 디렉터리에서 그대로 부팅됩니다. 그리고 저자 본인이 명시적으로 말합니다 — 아직 프로덕션 준비가 안 됐고, 성능 최적화도 안 됐고, 기존 확장(extension)과도 호환되지 않는다고.

4만6천 개 쿼리를 통과한다는 것 — 이 마일스톤이 진짜인 이유

Postgres 회귀 스위트를 얕잡아 보면 안 됩니다. make check로 돌아가는 이 테스트 묶음은 수십 년간 다듬어진 자산으로, 파서·플래너·실행기·타입 시스템·내장 함수, 그리고 그 사이에 낀 무수한 엣지 케이스를 4만6천 개가 넘는 쿼리로 훑습니다. 통과 기준은 느슨하지 않습니다 — 기대 출력과 바이트 단위로 일치해야 합니다. 숫자 포맷 하나, 에러 메시지 문구 하나가 어긋나도 실패입니다.

pgrust는 이 전부를 Postgres 18.3 기준으로 맞췄고, 스케줄된 동시성을 검증하는 isolation 테스트까지 통과한다고 밝혔습니다. 여기에 디스크 호환성이 얹힙니다. 실제 18.3 데이터 디렉터리에서 부팅된다는 건, 온디스크 페이지 포맷과 카탈로그 구조를 실제로 이해한다는 뜻입니다 — 일부 SQL만 흉내 내는 장난감이 아니라는 신호죠.

SQL 파서 하나라도 처음부터 다시 짜 본 사람은 압니다. 엣지 케이스의 꼬리가 얼마나 긴지. 4만6천 개 쿼리에서 전체 파이프라인이 Postgres와 의견 일치를 본다는 건, 엄청나게 넓은 표면적에서 동작을 재현했다는 뜻입니다. 이건 진짜 마일스톤입니다. 과소평가하면 안 됩니다.

"100% 통과"가 증명하지 않는 것

문제는 사람들이 이 문장을 "프로덕션 Postgres를 대체할 수 있다"로 읽는다는 겁니다. 그건 회귀 스위트가 검증하는 대상을 오해한 것입니다. 회귀 테스트는 대체로 단일 세션·결정론적 쿼리 동작에 대한 호환성 오라클입니다. 다음은 증명하지 않습니다:

  • 내구성과 크래시 복구. 스위트는 쓰기 도중에 kill -9를 날리고 WAL 재생·찢어진 페이지(torn page) 복구·전원 손실 시 fsync 의미를 검증하지 않습니다. 저자도 HN에서 힙 관리와 내구성은 "결국 고치고 싶은 부분"이라며, 스토리지는 향후 OrioleDB 도입을 검토 중이라고 답했습니다.
  • 실전 동시성의 MVCC. isolation 테스트는 각본이 짜인 스케줄을 다룹니다. 실제 부하의 적대적 동시성, 롱런 트랜잭션, vacuum과 블로트(bloat)의 상호작용은 그 바깥입니다.
  • 긴 꼬리. 확장과 PL/Python·PL/Perl·PL/Tcl 같은 절차적 언어는 아직 호환되지 않습니다(저자 명시). 복제, 논리적 디코딩, FDW, 그리고 운영을 지탱하는 생태계 전체가 빠져 있습니다.

그리고 방법론이 중요합니다. 테스트가 초록불이 될 때까지 고치는 AI 루프는, **일반적 정확성이 아니라 테스트에 대한 특수 처리(special-casing)**로 수렴할 위험이 있습니다. 한 HN 코멘트는 자기 경험을 이렇게 요약했습니다 — 테스트는 전부 통과했는데 정작 재작성물은 기본 기능에서 깨져 있었다고. "완전한 테스트 스위트란 없다"는 오래된 격언 그대로입니다. 100% 통과는 "테스트한 쿼리에서 알려진 불일치가 없다"이지, "버그가 없다"가 아닙니다. 비판자만 이렇게 말하는 게 아닙니다 — 저자 본인이 프로덕션 준비도, 성능 최적화도 안 됐다고 먼저 못 박았습니다.

성능 숫자, 그리고 AI가 짠 코드라는 점

README는 성능도 주장합니다 — 트랜잭션 워크로드에서 Postgres보다 50% 빠르고, 분석 워크로드에서 약 300배 빠르다(ClickHouse보다는 2배 느리다). 인상적으로 들리지만, 같은 README가 "아직 성능 최적화 안 됨"이라고 적어 둔 점과 나란히 놓고 봐야 합니다. HN에서도 방법론에 회의가 나왔습니다 — fsync는 켜 두고 잰 건지, 그리고 컬럼 지향에 수년간 SIMD를 다듬어 온 ClickHouse와의 비교는 애초에 사과 대 오렌지라는 지적이죠. 이 숫자들은 잘 봐줘야 방향성 정도로 읽는 게 안전합니다.

그럼에도 Rust로 다시 쓴다는 발상 자체는 흥미롭습니다. 메모리 안전성이 공짜로 따라오고, 프로세스 per 연결인 Postgres와 달리 스레드 per 연결 모델을 택해 병렬성 여지를 엽니다. 저자는 좁은 맥락에서 개별 쿼리 3배, 정규식 10배 같은 수치를 들기도 했습니다.

어떻게 만들었는지가 또 하나의 핵심입니다. 저자의 개발기에 따르면 약 2주 동안 약 25만 줄의 Rust가 생성됐고, 그 시점엔 회귀 스위트의 약 3분의 1을 통과했습니다. Codex로 개별 기능을 짜다가, 코딩 에이전트를 최대 17개까지 병렬로 돌려 "CPU가 한계에 닿을 때까지" 밀어붙였다고 합니다. HN 답글에서는 c2rust로 기계 번역을 뜬 뒤 unsafe 코드를 걷어내는 식으로 시작했고, 특화 스킬을 준 Claude로 포팅을 병렬화했다고 밝혔습니다. 즉 "Rust로 다시 썼다"는 부분적으로 "번역한 뒤 다시 썼다"에 가깝습니다 — 속도 면에선 놀랍지만, 그만큼 생성된 미최적화 코드가 많다는 뜻이기도 합니다.

어려운 이유는 명확합니다. 수십 년치 Postgres 엣지 케이스, MVCC, 온디스크 포맷, 확장 ABI. 회귀 스위트가 바(bar) 역할을 하는 건, 바로 그 엣지 케이스들이 다른 방법으로는 보이지 않기 때문입니다.

마치며 — 엔진과 그 바깥

정리하면 이렇습니다. 회귀 테스트 100% 통과는 진짜로 인상적인 마일스톤이고, "Postgres를 안에서부터 바꾸기 쉽게 만든다"는 목표에 훌륭한 연구 수단입니다. 하지만 그것은 "드롭인 프로덕션 Postgres"가 아닙니다. 둘 사이의 간격은 대체로 화려하지 않은 부분 — 내구성, 복제, 백업, 업그레이드, 운영 도구 — 으로 채워져 있고, 그 간격은 년 단위입니다.

이 지점에서 제 CNPG 페일오버 실측 글과 자연스럽게 이어집니다. 프로덕션 Postgres는 쿼리 엔진만이 아닙니다. 그건 복제와 페일오버, 백업, 롤링 업그레이드, 그리고 그걸 자동화하는 오퍼레이터 생태계입니다. 그 글에서 저는 진짜 Postgres 프라이머리를 죽이고 레플리카가 23.1초 만에 무손실로 승격되는 걸 실측했습니다. 갓 몇 주 된 엔진이 아직 기르지 못한 게 바로 그 "엔진 바깥의 비계(scaffolding)"입니다. pgrust는 언어 표면(language surface)에서 이겼고, 프로덕션은 생존성에서 이깁니다. 둘 다 참입니다.

그래서 저는 pgrust를 응원하되, 헤드라인은 헤드라인으로 읽습니다. Rust로 Postgres를 다시 쓰는 실험은 볼 가치가 충분합니다 — 다만 "이제 프로덕션 Postgres 갈아치우면 된다"로 읽는 순간, 저자가 직접 적어 둔 세 줄의 경고를 지나친 것입니다.

참고 자료

pgrust: Postgres Rewritten in Rust, Passing 100% of the Regression Tests — What That Actually Means

Introduction — The "Postgres Rewritten in Rust" Headline

Malcolm Matis (GitHub malisper) released pgrust. The one-line description is simple — "A Postgres rewrite in Rust". The headline is stronger: it passes 100% of the Postgres regression tests. Trending on top of GeekNews and Hacker News, the news pulls two opposite reactions at once — "Postgres in Rust, finally?" and "who's putting a database written by AI in a few weeks into production?".

This piece tries to calm both. What did pgrust actually accomplish, and what does the sentence "passes 100% of the regression tests" mean — and, crucially, not mean? The facts first: pgrust targets compatibility with Postgres 18.3 and produces output matching Postgres across more than 46,000 regression queries. It is disk-compatible, so it boots directly from an existing 18.3 data directory. And the author says so himself — it is not production-ready, not performance-optimized, and not compatible with existing extensions.

Passing 46,000 Queries — Why This Milestone Is Real

Do not underrate the Postgres regression suite. Run by make check, this battery of tests is an asset honed over decades: it sweeps the parser, planner, executor, type system, built-in functions, and the countless edge cases wedged between them across more than 46,000 queries. The bar is not loose — output must match the expected results byte-for-byte. One number formatted differently, one error-message wording off, and it fails.

pgrust lines all of that up against Postgres 18.3, and reports passing the isolation tests that verify scheduled concurrency as well. On top of that sits disk compatibility. Booting from a real 18.3 data directory means it actually understands the on-disk page format and catalog layout — a signal that this is not a toy that mimics a subset of SQL.

Anyone who has reimplemented even a single SQL parser from scratch knows how long the tail of edge cases is. When the whole pipeline agrees with Postgres across 46,000 queries, it has reproduced behavior over an enormous surface area. This is a real milestone. Do not underrate it.

What "100%" Does Not Prove

The trouble is that people read that sentence as "can replace production Postgres." That misreads what the regression suite verifies. Regression tests are a compatibility oracle for mostly single-session, deterministic query behavior. They do not prove:

  • Durability and crash recovery. The suite does not kill -9 mid-write and verify WAL replay, torn-page recovery, or fsync semantics under power loss. On Hacker News the author himself called heap management and durability "something I eventually want to fix," noting he is looking at adopting OrioleDB for storage down the line.
  • MVCC under real concurrency. The isolation tests cover scripted schedules. The adversarial concurrency of real workloads, long-running transactions, and the interplay of vacuum and bloat live outside that.
  • The long tail. Extensions and procedural languages like PL/Python, PL/Perl, and PL/Tcl are not compatible yet (the author says so). Replication, logical decoding, FDWs, and the entire operational ecosystem are absent.

And the method matters. An AI loop that keeps fixing until the tests go green risks converging on special-casing to the test rather than general correctness. One HN commenter summarized their own experience: all the tests passed with flying colors, yet the rewrite itself was broken even on basic functionality. It is the old maxim — there is no such thing as a complete test suite. "100% passing" means "no known divergence on the tested queries," not "bug-free." And it is not only critics saying this — the author put the three warnings up front himself: not production-ready, not performance-optimized.

Performance Claims, and the Fact That AI Wrote the Code

The README makes performance claims too — 50% faster than Postgres on transaction workloads, and roughly 300x faster on analytical workloads (2x slower than ClickHouse). It sounds impressive, but it has to be read next to the fact that the same README says it is "not performance optimized yet." HN was skeptical of the methodology: was fsync left on when measuring, and the comparison against ClickHouse — column-oriented and SIMD-tuned over years — is apples-to-oranges to begin with. Treat these numbers as directional at best.

Even so, the idea of a rewrite in Rust is genuinely interesting. Memory safety comes along for free, and unlike Postgres's process-per-connection model, pgrust chooses a thread-per-connection model, opening room for parallelism. The author cited figures like 3x on individual queries and 10x on regex in narrow contexts.

How it was built is another crux. Per the author's own write-up, about 250,000 lines of Rust were generated in roughly two weeks, passing about a third of the regression suite at that point. He started with Codex for individual features, then scaled to as many as 17 coding agents running in parallel "before maxing out the CPU." In HN replies he described starting from a c2rust mechanical translation and then rewriting the unsafe code, parallelizing the porting with Claude given specialized skills. So "rewritten in Rust" is partly "translated, then rewritten" — remarkable for speed, but also a way of saying there is a lot of generated, unoptimized code in there.

The reason it is hard is clear: decades of Postgres edge cases, MVCC, the on-disk format, the extension ABI. The regression suite serves as the bar precisely because those edge cases are otherwise invisible.

Closing — The Engine and Everything Around It

To sum up: passing 100% of the regression tests is a genuinely impressive milestone, and an excellent research vehicle for the goal of "making Postgres easier to change from the inside." But it is not "drop-in production Postgres." The gap between the two is filled mostly with the unglamorous parts — durability, replication, backups, upgrades, operational tooling — and that gap is measured in years.

This is exactly where it connects to my CNPG failover measurement piece. Production Postgres is not just the query engine. It is replication and failover, backups, rolling upgrades, and the operator ecosystem that automates all of it. In that article I killed a real Postgres primary and measured a replica getting promoted in 23.1 seconds with zero data loss. That "scaffolding around the engine" is precisely what an engine only a few weeks old has not yet grown. pgrust wins on the language surface; production wins on survivability. Both are true.

So I root for pgrust while reading the headline as a headline. The experiment of rewriting Postgres in Rust is well worth watching — but the moment you read it as "now I can swap out production Postgres," you have skipped past the three lines of warning the author wrote himself.

References