1.28x
COPY / asyncpg
100M rows
2.24x
Sequential / asyncpg
single connection
24x
Pipelined / asyncpg
historical snapshot
COPY Bulk Insert Throughput
100 million rows, 10,000 rows per COPY, and 10,000 COPY operations.
| Driver | Implementation | Rows/s | Time (100M) | Relative to asyncpg |
|---|---|---|---|---|
| qail-pg (Rust) | Pure Rust (Tokio) | 1,363,776 | 73.3s | 1.28x |
| qail-py | Python driver plus Rust core | 1,214,141 | 82.4s | 1.14x |
| asyncpg | Python driver plus Cython core | 1,062,942 | 94.1s | baseline |
Workload note
At 100M rows, PostgreSQL server and storage behavior contribute materially to total runtime in addition to client-side encoding. Read this page as a dated system snapshot rather than a transport-only benchmark.
Snapshot Summary
| Benchmark | Rust | qail-py | asyncpg | Normalized ordering |
|---|---|---|---|---|
| COPY bulk insert (100M) | 1.36M r/s | 1.21M r/s | 1.06M r/s | Rust 1.00x, qail-py 0.89x, asyncpg 0.78x |
| Sequential queries | 38.9K q/s | 27.7K q/s | 17.4K q/s | Rust 1.00x, qail-py 0.71x, asyncpg 0.45x |
| Pipelined queries | 384.6K q/s | 122.4K q/s | ~16K q/s | Rust 1.00x, qail-py 0.32x, asyncpg ~0.04x |
Test environment
Hardware
- Apple M3 Pro
- macOS arm64
- localhost PostgreSQL
Software
- PostgreSQL 18
- Python 3.13.7
- Rust stable
Test config
- Single connection
- No pooling
- Prepared statements