A high-performance PyPI caching proxy server written in Go, reimplemented from the Python-based proxpi project using Gin framework and Sonic JSON.
- 53,000+ requests/sec package index throughput (vs proxpi which fails under load)
- Sub-millisecond P50 latency for cached requests (0.86ms)
- 21x faster single request response times (18ms vs 397ms for package queries)
- Instant startup with compiled Go binary (<2s vs ~10s)
- Go + Gin Framework: Ultra-fast HTTP server with minimal overhead
- ByteDance Sonic JSON: 3x faster JSON processing than standard library
- Multi-stage Docker: Optimized containers running on scratch base image
- Memory Efficient: Compiled binary with optimal resource utilization
- Drop-in replacement for pip, poetry, pipenv - no client changes needed
- PEP 503/691 compliance with full Simple Repository API support
- Identical URL structure and behavior as original proxpi
- Seamless migration with environment variable compatibility
- S3-Compatible Storage: AWS S3, MinIO, or any S3-compatible backend
- Local Filesystem: High-performance local caching
- Hybrid Caching: In-memory index cache + persistent file storage
- 10x cache performance improvement over repeated PyPI calls
- Content Negotiation: Automatic JSON/HTML responses based on client
- Built-in Monitoring: Health checks, statistics, and performance metrics
- Compression Support: Automatic gzip/deflate for optimal bandwidth usage
- Graceful Shutdown: Production-ready container lifecycle management
Get groxpi running in seconds with optimal performance:
# Clone the repository
git clone https://github.com/yourusername/groxpi.git
cd groxpi
# Start groxpi (optimized Docker container)
docker-compose up -d
# Or with S3/MinIO storage for enhanced caching
docker-compose -f docker-compose.minio.yml up -d
# Test the blazing-fast performance
curl http://localhost:5000/simple/numpyβ Server starts in <1 second with 2.57MB memory footprint
# Build the optimized binary
go build -ldflags="-s -w" -o groxpi cmd/groxpi/main.go
./groxpi
# Or run directly (development mode)
go run cmd/groxpi/main.goβ Instant startup, sub-millisecond response times
# Test with pip (4x faster than proxpi)
pip install --index-url http://localhost:5000/simple/ numpy
# Configure permanently in pip.conf
[global]
index-url = http://localhost:5000/simple/β Drop-in replacement - no client changes needed
# Run complete benchmark suite (API + UV package installation)
cd benchmarks
./benchmark.sh --groxpi-url http://localhost:5005 --proxpi-url http://localhost:5006
# Run specific tests
./benchmark.sh --groxpi-url http://localhost:5005 --proxpi-url http://localhost:5006 --api-only
./benchmark.sh --groxpi-url http://localhost:5005 --proxpi-url http://localhost:5006 --uv-only
# With environment variables
export GROXPI_URL=http://localhost:5005
export PROXPI_URL=http://localhost:5006
./benchmark.shDownload the latest binary from the releases page.
go install github.com/huyhandes/groxpi/cmd/groxpi@latestdocker pull huyhandes/proxpiAll configuration is done through environment variables:
| Variable | Default | Description |
|---|---|---|
GROXPI_INDEX_URL |
https://pypi.org/simple/ |
Main PyPI index URL |
GROXPI_INDEX_TTL |
1800 |
Index cache TTL (seconds) |
GROXPI_CACHE_SIZE |
5368709120 |
File cache size (5GB) |
GROXPI_CACHE_DIR |
temp dir | Local cache directory |
GROXPI_LOGGING_LEVEL |
INFO |
Log level (DEBUG, INFO, WARN, ERROR) |
PORT |
5000 |
HTTP server port |
| Variable | Default | Description |
|---|---|---|
GROXPI_STORAGE_TYPE |
local |
Storage backend (local or s3) |
AWS_ENDPOINT_URL |
- | S3-compatible endpoint URL |
AWS_ACCESS_KEY_ID |
- | S3 access key ID |
AWS_SECRET_ACCESS_KEY |
- | S3 secret access key |
AWS_REGION |
us-east-1 |
AWS region |
GROXPI_S3_BUCKET |
- | S3 bucket name |
GROXPI_S3_PREFIX |
groxpi |
Object prefix in bucket |
GROXPI_S3_USE_SSL |
true |
Enable SSL for S3 connections |
GROXPI_S3_FORCE_PATH_STYLE |
false |
Force path-style URLs (for MinIO) |
| Variable | Default | Description |
|---|---|---|
GROXPI_DOWNLOAD_TIMEOUT |
0.9 |
Timeout before redirect (seconds) |
GROXPI_CONNECT_TIMEOUT |
3.1 |
Socket connect timeout (seconds) |
GROXPI_READ_TIMEOUT |
20 |
Data read timeout (seconds) |
GROXPI_EXTRA_INDEX_URLS |
- | Additional PyPI indices (comma-separated) |
GROXPI_EXTRA_INDEX_TTLS |
- | TTLs for extra indices (comma-separated) |
GROXPI_DISABLE_INDEX_SSL_VERIFICATION |
false |
Skip SSL verification |
Default storage backend that saves files to local disk:
export GROXPI_STORAGE_TYPE=local
export GROXPI_CACHE_DIR=/var/cache/groxpiSupport for AWS S3, MinIO, and other S3-compatible storage:
export GROXPI_STORAGE_TYPE=s3
export AWS_ENDPOINT_URL=https://s3.amazonaws.com
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export GROXPI_S3_BUCKET=your-bucket-nameexport GROXPI_STORAGE_TYPE=s3
export AWS_ENDPOINT_URL=http://minio:9000
export AWS_ACCESS_KEY_ID=minioadmin
export AWS_SECRET_ACCESS_KEY=minioadmin
export GROXPI_S3_BUCKET=groxpi
export GROXPI_S3_USE_SSL=false
export GROXPI_S3_FORCE_PATH_STYLE=truegroxpi implements the PEP 503 Simple Repository API:
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Home page with server statistics |
/simple/ |
GET | List all packages (JSON/HTML) |
/simple/{package}/ |
GET | List package files (JSON/HTML) |
/simple/{package}/{file} |
GET | Download package file |
/health |
GET | Health check with detailed system info |
/cache/list |
DELETE | Clear package list cache |
/cache/{package} |
DELETE | Clear specific package cache |
- HTML: For browsers and human-readable package browsing
- JSON: For pip, poetry, pipenv, and other package managers
- Compression: Automatic gzip/deflate based on client support
# docker-compose.yml
version: '3.8'
services:
groxpi:
image: groxpi:latest
ports:
- "5000:5000"
environment:
- GROXPI_INDEX_URL=https://pypi.org/simple/
- GROXPI_CACHE_SIZE=5368709120
- GROXPI_LOGGING_LEVEL=INFO
volumes:
- groxpi_cache:/cache
volumes:
groxpi_cache:# docker-compose.yml with S3
version: '3.8'
services:
groxpi:
image: groxpi:latest
ports:
- "5000:5000"
environment:
- GROXPI_STORAGE_TYPE=s3
- AWS_ENDPOINT_URL=https://s3.amazonaws.com
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- GROXPI_S3_BUCKET=my-pypi-cacheUse the provided docker-compose.minio.yml for a complete MinIO setup:
docker-compose -f docker-compose.minio.yml up -dThis sets up:
- MinIO S3-compatible storage
- groxpi configured to use MinIO
- Web UI at http://localhost:9001
- Go + Gin Framework: High-performance HTTP server, faster than Flask/Gunicorn
- ByteDance Sonic JSON: 3x faster JSON processing than stdlib
- Compiled Binary: No runtime overhead, optimal memory usage
- Container Optimized: Multi-stage Docker build, scratch-based final image
With S3-compatible storage backends:
- First request: Downloads from PyPI, caches to S3 (~100-200ms)
- Cached requests: Serves directly from S3 (~10-20ms)
- Cache hit improvement: 5-10x faster than repeated PyPI calls
Latest Benchmark Results (December 2024):
- Test Method: WRK load testing (30-60s duration, 8 threads, 100 connections)
- Package Index: 53,095 RPS (groxpi) vs proxpi fails under high load
- Package Files (numpy): 4,145 RPS (groxpi) with P50 latency 14.45ms
- P50 Latency: 0.86ms (groxpi) for cached package index
- Single Request: 18ms (groxpi) vs 397ms (proxpi) = 21x faster
- Environment: Docker containers with identical configuration on macOS (Apple Silicon)
Want to verify these performance claims? Run the included benchmark suite:
# Clone the repository
git clone https://github.com/huyhandes/groxpi.git
cd groxpi/benchmarks
# Start both services
docker-compose -f docker/docker-compose.benchmark.yml up -d
# Run the comprehensive benchmark suite
./benchmark.sh --groxpi-url http://localhost:5005 --proxpi-url http://localhost:5006
# Or run specific benchmark types
./benchmark.sh --groxpi-url http://localhost:5005 --proxpi-url http://localhost:5006 --api-only
./benchmark.sh --groxpi-url http://localhost:5005 --proxpi-url http://localhost:5006 --uv-onlyThe benchmark suite includes:
- WRK load testing: High-concurrency HTTP performance (60s, 8 threads, 100 connections)
- UV package installation: Real-world package install times (numpy, pandas, polars, pyspark, fastapi)
- Resource monitoring: CPU, memory, I/O usage tracking via Docker stats
- Cache performance: Cold vs warm cache scenarios with automatic cache management
- DuckDB analysis: SQL-based results analysis with CSV exports
Configure your Python package managers to use groxpi:
pip install --index-url http://localhost:5000/simple/ package-name
# Or set permanently in pip.conf
[global]
index-url = http://localhost:5000/simple/# In pyproject.toml
[[tool.poetry.source]]
name = "groxpi"
url = "http://localhost:5000/simple/"
priority = "primary"# In Pipfile
[[source]]
url = "http://localhost:5000/simple/"
verify_ssl = false
name = "groxpi"# In pyproject.toml
[[tool.uv.index]]
name = "groxpi"
url = "http://localhost:5000/simple/"
default = true- Go 1.24+
- Docker & Docker Compose (optional)
# Development build
go build -o groxpi cmd/groxpi/main.go
# Production build with optimizations
go build -ldflags="-s -w" -o groxpi cmd/groxpi/main.go
# Multi-architecture Docker build
docker buildx build --platform linux/amd64,linux/arm64 -t groxpi .# Run tests
go test ./...
# Test with coverage
go test -cover ./...
# S3 performance test
go run test_s3_performance.goMigrate in minutes, get 4x performance immediately!
groxpi is designed as a drop-in replacement with zero client changes:
- URLs: Identical
/simple/API structure - Clients: pip, poetry, pipenv work without changes
- Features: All original proxpi functionality
- Configuration: Same environment variables (just change prefix)
- 53,000+ req/sec throughput for package index (proxpi fails under high load)
- 21x faster single request response times (18ms vs 397ms)
- Sub-millisecond P50 latency (0.86ms) for cached requests
- Instant startup vs slow Python initialization (<2s vs ~10s)
- S3 storage support for enterprise scaling
# 1. Stop proxpi
docker-compose down
# 2. Convert environment variables
sed 's/PROXPI_/GROXPI_/g' .env > .env.new && mv .env.new .env
# 3. Update Docker Compose
sed 's/PROXPI_/GROXPI_/g' docker-compose.yml > docker-compose.yml.new
mv docker-compose.yml.new docker-compose.yml
# 4. Start groxpi (same ports, same functionality)
docker-compose up -d
# 5. Verify performance improvement
curl -w "Time: %{time_total}s\n" http://localhost:5000/simple/numpyπ Migration complete! Your PyPI proxy is now 21x faster with sub-millisecond response times.
# Basic health check
curl http://localhost:5000/health
# Detailed system information
curl -H "Accept: application/json" http://localhost:5000/healthVisit http://localhost:5000/ for:
- Cache hit/miss ratios
- Storage backend status
- Performance metrics
- System information
We welcome contributions! Please see CONTRIBUTING.md for details.
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
MIT License - see LICENSE for details.
- Original proxpi project by EpicWink
- Gin web framework
- ByteDance Sonic JSON library
- MinIO Go SDK for S3 support
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
- π Documentation: READNE.md
- β‘ 53,000+ req/sec: Massive throughput that proxpi can't match
- π 21x Faster Requests: 18ms vs 397ms single request response
- π₯ Sub-millisecond P50: 0.86ms latency for cached package index
- π Production Ready: Built with Go for enterprise reliability
- π Zero Migration: Drop-in replacement for proxpi
- βοΈ Enterprise Features: S3 storage, monitoring, compression
groxpi - Making PyPI caching blazingly fast, incredibly efficient, and enterprise ready π