# Performance Differences Between pgrust and PostgreSQL: A Deep Dive into the Rust Rewrite

> Explore pgrust vs PostgreSQL performance. Discover how pgrust offers 50% faster transactions and 300x faster analytics by leveraging Rust's efficiency and modern architecture.

- Repository: [Michael Malis/pgrust](https://github.com/malisper/pgrust)
- Tags: deep-dive
- Published: 2026-07-13

---

**pgrust achieves approximately 50% faster transaction processing and up to 300× faster analytical query performance compared to PostgreSQL 18.3** by replacing the process-per-connection model with threads, leveraging Rust's zero-cost abstractions, and utilizing thread-local storage for backend state.

pgrust is a Rust-rewritten implementation of PostgreSQL 18.3 maintained by malisper that maintains binary compatibility with the upstream server while exploring architectural improvements. Understanding the performance differences between pgrust and PostgreSQL requires examining three core redesigns: the concurrency model, language choice, and memory management strategies.

## Concurrency Model: Processes vs Threads

### PostgreSQL's Process-Per-Connection Architecture

Traditional PostgreSQL uses a **process-per-connection** model where each client connection spawns a separate OS process via `fork()`. This design incurs heavy context-switch overhead and duplicated memory pages through copy-on-write semantics. When handling thousands of concurrent connections, the scheduler overhead and memory duplication create significant bottlenecks in transaction-heavy workloads.

### pgrust's Thread-Per-Connection Design

pgrust replaces processes with **threads**, running one OS thread per client within a shared address space. This eliminates the costly `fork()` operations and allows CPU caches to reuse data across connections more effectively. According to the repository's performance benchmarks at line 37 of the README, this architectural shift alone yields **approximately 50% faster** performance on typical transaction workloads.

## Language Choice and Compilation Advantages

### C Implementation Limitations

PostgreSQL's C implementation relies on manual memory management and pointer arithmetic, which limits the compiler's ability to perform aggressive inlining and optimizations. Safety-related bugs in memory management can also cause hidden stalls that degrade performance unpredictably.

### Rust's Zero-Cost Abstractions

pgrust is implemented in **Rust**, which provides zero-cost abstractions and guaranteed memory safety without runtime garbage collection. The Rust compiler produces tighter machine code through aggressive inlining while eliminating costly runtime checks. These optimizations contribute to **300× speedups** on analytical queries where tight data-processing loops dominate execution time.

## Memory Management and Execution Pipeline

### Process-Local State in PostgreSQL

PostgreSQL relies heavily on process-local static globals and per-process memory pools (such as `Backend` and `ExecutorState` structures). Updating these structures requires copying data across processes during parallel operations, creating latency and contention in both read-only and write-heavy workloads.

### Thread-Local Storage in pgrust

pgrust replaces process-local storage with **thread-local storage** using `thread_local!` macros throughout the engine. This design eliminates inter-process copying and enables true sharing of reusable caches. You can see this implementation in [`crates/common/wait_error/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/common/wait_error/src/lib.rs), which handles error states without cross-process synchronization, and in `crates/backend/rmgrdesc_next/src/*`, where core resource-manager descriptors for WAL and transaction logs benefit from shared-memory access patterns.

The PL/pgSQL parser in [`crates/pl/plpgsql/src/plpgsql_gram/src/parser.rs`](https://github.com/malisper/pgrust/blob/main/crates/pl/plpgsql/src/plpgsql_gram/src/parser.rs) demonstrates how the original C parser was ported while preserving thread-local parsing state, reducing contention during complex query compilation.

## Benchmark Results and Real-World Impact

The performance differences between pgrust and PostgreSQL vary significantly by workload type:

- **Transaction workloads (OLTP)**: Approximately **50% faster** than PostgreSQL due to reduced context-switching and thread creation overhead
- **Analytical workloads (OLAP)**: Approximately **300× faster** than PostgreSQL, while remaining only **2× slower** than ClickHouse on ClickBench benchmarks

Because pgrust maintains the same on-disk format as PostgreSQL, these performance gains require no migration work—existing data directories work immediately with the pgrust binary.

## Implementation Examples

The following examples demonstrate pgrust's drop-in compatibility while illustrating its performance-oriented architecture:

```rust
// Launching the pgrust server (equivalent to postgres -D <dir>)
use std::process::Command;

fn launch_pgrust(data_dir: &str) {
    let status = Command::new("target/release/postgres")
        .args(&[
            "-D", data_dir,
            "-F",                 // disable fsync for demo
            "-c", "listen_addresses=", // bind to all interfaces
            "-p", "5432",
        ])
        .status()
        .expect("failed to launch pgrust");
    assert!(status.success());
}

```

```rust
// Connecting with the built-in libpq client (identical to psql)
use libpq::Connection;

fn run_simple_query() -> Result<(), libpq::Error> {
    let mut conn = Connection::new("host=/tmp dbname=postgres user=postgres")?;
    let rows = conn.query("SELECT version(), 1 + 1 AS two", &[])?;
    for row in rows {
        let version: &str = row.get(0);
        let two: i32 = row.get(1);
        println!("{} → {}", version, two);
    }
    Ok(())
}

```

Both snippets use identical command-line arguments and SQL as traditional PostgreSQL deployments, as implemented in [`crates/interfaces/libpq/fe/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/interfaces/libpq/fe/src/lib.rs), ensuring compatibility while gaining the architectural benefits described above.

## Summary

- **Thread-per-connection architecture** replaces PostgreSQL's process-per-connection model, reducing context-switch overhead by approximately 50% on transaction workloads
- **Rust's zero-cost abstractions** enable aggressive compiler optimizations that deliver 300× performance improvements on analytical queries compared to the C implementation
- **Thread-local storage** in files like [`crates/common/wait_error/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/common/wait_error/src/lib.rs) and `crates/backend/rmgrdesc_next/src/*` eliminates inter-process copying and enables efficient cache sharing
- **Binary compatibility** with PostgreSQL 18.3 allows immediate deployment using existing data directories without migration overhead
- **Performance profile** ranges from 50% faster on OLTP to 300× faster on OLAP workloads, with only 2× overhead compared to specialized analytical databases like ClickHouse

## Frequently Asked Questions

### Is pgrust binary-compatible with PostgreSQL?

Yes, pgrust is designed to be binary-compatible with PostgreSQL 18.3. It uses the same on-disk format and network protocol, allowing you to start pgrust with an existing PostgreSQL data directory using standard command-line arguments like `postgres -D <directory>`. The [`crates/interfaces/libpq/fe/src/lib.rs`](https://github.com/malisper/pgrust/blob/main/crates/interfaces/libpq/fe/src/lib.rs) implementation maintains wire-protocol compatibility with existing PostgreSQL clients.

### How does pgrust handle WAL and transaction logs?

pgrust implements WAL (Write-Ahead Logging) and resource-manager descriptors in `crates/backend/rmgrdesc_next/src/*`, utilizing thread-local storage to manage transaction state. This differs from PostgreSQL's process-local static globals, allowing concurrent access to transaction logs without the overhead of inter-process communication or memory copying.

### Can I migrate existing PostgreSQL data to pgrust?

No migration is necessary. Because pgrust maintains the same on-disk binary format as PostgreSQL 18.3, you can point pgrust to an existing PostgreSQL data directory and start the server immediately. This zero-migration path allows you to gain performance benefits—ranging from 50% to 300× depending on workload—without exporting and importing data.

### What workloads benefit most from pgrust's architecture?

**Analytical (OLAP) workloads** benefit most dramatically, with up to 300× performance improvements due to Rust's efficient handling of tight data-processing loops. **Transaction-heavy (OLTP) workloads** see approximately 50% improvements from the thread-per-connection model. Workloads with high connection counts and frequent context switching see the most significant gains compared to traditional PostgreSQL process-based architecture.