tileserver-rs is designed for high-performance vector tile serving. This page documents benchmark results for both PMTiles and MBTiles sources.
| Source | File | Area | Zoom Range | Size |
|---|---|---|---|---|
| PMTiles | protomaps-sample.pmtiles | Florence, Italy | 0-15 | 6.3 MB |
| MBTiles | zurich_switzerland.mbtiles | Zurich, Switzerland | 0-14 | 34 MB |
| Source | Avg Requests/sec | Avg Throughput | Avg Latency |
|---|---|---|---|
| PMTiles | 1,047 req/s | 93.18 MB/s | 171ms |
| MBTiles | 1,133 req/s | 92.62 MB/s | 181ms |
Both formats deliver ~93 MB/s throughput with 1,000+ requests/second under heavy load (100 concurrent connections).
| Zoom | Location | Requests/sec | Throughput | Avg Latency | P99 Latency |
|---|---|---|---|---|---|
| z0 | World | 236 | 97.88 MB/s | 461ms | 1,190ms |
| z4 | Europe | 403 | 95.51 MB/s | 264ms | 607ms |
| z8 | Italy | 1,071 | 91.72 MB/s | 99ms | 191ms |
| z10 | Tuscany | 1,290 | 89.81 MB/s | 81ms | 158ms |
| z12 | Florence | 1,675 | 93.62 MB/s | 62ms | 119ms |
| z14 | City Center | 1,605 | 90.54 MB/s | 63ms | 121ms |
| Zoom | Location | Requests/sec | Throughput | Avg Latency | P99 Latency |
|---|---|---|---|---|---|
| z0 | World | 3,441 | 89.82 MB/s | 29ms | 55ms |
| z4 | Europe | 990 | 89.84 MB/s | 104ms | 207ms |
| z8 | Switzerland | 426 | 92.90 MB/s | 252ms | 669ms |
| z10 | Zurich Region | 590 | 92.33 MB/s | 180ms | 361ms |
| z12 | Zurich City | 1,088 | 91.47 MB/s | 97ms | 191ms |
| z14 | City Center | 266 | 99.37 MB/s | 425ms | 1,166ms |
| Aspect | PMTiles | MBTiles |
|---|---|---|
| Best for | Production, CDN, cloud | Development, local |
| Consistency | More predictable | Variable by tile size |
| High-zoom perf | Excellent | Good |
| Low-zoom perf | Good | Excellent |
To reproduce these benchmarks with fair Docker-to-Docker comparison:
# Build tileserver-rs Docker image for your platform
docker build -t tileserver-rs:local .
# Update benchmarks/docker-compose.yml to use local image
# Then start all servers
docker compose -f benchmarks/docker-compose.yml up -d
# Run benchmarks
cd benchmarks
bun install
node run-benchmarks.js --duration 10 --connections 100
# Test only PMTiles
node run-benchmarks.js --format pmtiles
# Test only MBTiles
node run-benchmarks.js --format mbtiles
# Test specific server
node run-benchmarks.js --server tileserver-rs
# Longer test with more connections
node run-benchmarks.js --duration 30 --connections 200
# Generate markdown report
node run-benchmarks.js --markdown
We benchmarked tileserver-rs against martin and tileserver-gl using the same test data. All servers ran in Docker containers on ARM64 for a fair apples-to-apples comparison.
| Server | Avg Req/sec | Avg Latency | Throughput |
|---|---|---|---|
| tileserver-rs | 1,372 | 80ms | 90 MB/s |
| tileserver-gl | 1,148 | 93ms | 75 MB/s |
| martin | 78 | 1,252ms | 9 MB/s |
tileserver-rs is ~20% faster than tileserver-gl and ~17x faster than martin for PMTiles serving.
| Server | Avg Req/sec | Avg Latency | Throughput |
|---|---|---|---|
| tileserver-rs | 751 | 188ms | 90 MB/s |
| martin | 722 | 154ms | 155 MB/s |
| tileserver-gl | 712 | 194ms | 85 MB/s |
All three servers perform similarly for MBTiles (within ~5% of each other).
| Feature | tileserver-rs | tileserver-gl | martin |
|---|---|---|---|
| Language | Rust | Node.js | Rust |
| PMTiles | ✅ | ✅ | ✅ |
| MBTiles | ✅ | ✅ | ✅ |
| PostGIS | ❌ | ❌ | ✅ |
| Raster Rendering | ✅ Native | ✅ Node | ❌ |
| Static Images | ✅ | ✅ | ❌ |
| PMTiles Req/sec | 1,372 | 1,148 | 78 |
| MBTiles Req/sec | 751 | 712 | 722 |
tileserver-rs provides the best balance: fastest PMTiles performance (~20% faster than tileserver-gl, 17x faster than martin), native MapLibre rendering for raster tiles, and static image generation - all in a single binary.
cargo build --release is 10-50x faster than debug