HomePlaygroundExpressionsDocsDriversStatusChangelog GitHub
← Back to Benchmarks
50 Million Queries

QAIL Go IPC vs pgx

Unix socket IPC matches pure Go performance

December 27, 2025

🎯 Fair Head-to-Head Comparison

237,561
QAIL IPC q/s
239,794
pgx q/s
99%
Performance Match
🚀 Key Insight: QAIL IPC daemon achieves 99% of pgx performance despite IPC overhead (Go → JSON → Unix Socket → Rust → PostgreSQL). The prepared statement caching in the Rust daemon compensates for the extra hop.

Architecture Comparison

pgx (Pure Go)

Go App
  ↓ (direct)
pgx driver
  ↓ (TCP)
PostgreSQL
                

Zero overhead, optimized for years

QAIL IPC Daemon

Go App
  ↓ (Unix socket + JSON)
qail-daemon (Rust/Tokio)
  ↓ (TCP, pipeline_prepared_fast)
PostgreSQL
                

Extra hop, but prepared stmt caching!

50 Million Query Results

Driver Queries/sec Total Time Per Query
pgx (SendBatch) 239,794 208.5s 4,170ns
QAIL IPC (PreparedPipeline) 237,561 210.5s 4,210ns
Native Rust (baseline) 355,000 141s 2,817ns

Test Configuration

Parameter Value
Total Queries 50,000,000
Batch Size 10,000 queries
Query Type SELECT id, name FROM harbors LIMIT $1
Protocol Prepared statement + pipeline mode
Connection Single connection (no pooling)

Evolution: From CGO to IPC Daemon

Mode Queries/sec vs pgx Notes
QAIL CGO (original) 126,000 53% CGO overhead, Go I/O
QAIL IPC (PipelineFast) 42,000 18% Full Query struct per batch
QAIL IPC (PreparedPipeline) 237,561 99% Prepared stmt caching

Why PreparedPipeline Matches pgx

The Secret: Parse once, Bind+Execute many.

The Rust daemon caches the prepared statement after a single Prepare call. Subsequent PreparedPipeline calls only send parameter values, not the full query structure. This eliminates the JSON overhead for the SQL template.

┌─────────────────────────────────────────────────────────┐
│ Go Client                                                │
├─────────────────────────────────────────────────────────┤
│ 1. Prepare("SELECT ... LIMIT $1") → handle              │
│ 2. PreparedPipeline(handle, [["5"],["3"],["1"],...])    │
│    ↓ (small JSON: just params)                          │
├─────────────────────────────────────────────────────────┤
│ qail-daemon (Rust)                                       │
├─────────────────────────────────────────────────────────┤
│ - Lookup cached PreparedStatement by handle             │
│ - Call pipeline_prepared_fast() → Bind+Execute × 10,000 │
│ - Return count (no row parsing overhead)                │
└─────────────────────────────────────────────────────────┘
            

Potential Optimizations (Not Yet Tuned)

Optimization Estimated Gain Status
MessagePack instead of JSON +10-15% Planned
Pre-encoded params in Go +5-10% Planned
Connection pooling in daemon +5% Planned
Total Potential 260K+ q/s Could beat pgx

Conclusion

QAIL's IPC daemon architecture proves that language-agnostic database access doesn't have to sacrifice performance. With prepared statement caching, the Rust daemon achieves 99% of pure Go pgx performance while offering:

🎯 Bottom Line

99%
of pgx performance
237K
queries/second
0
CGO overhead

← All Benchmarks