Performance Benchmarks¶
Real numbers from production load tests — not synthetic benchmarks.
All figures below are from actual production sessions on Render's Starter plan (512 MB RAM, shared CPU) using real files uploaded via the Lenzeye File Transfer feature.
Upload Performance¶
| Metric | Result |
|---|---|
| Files in single session | 2,630+ |
| Session duration | 6 hours 56 minutes |
| Session crashes | 0 |
| File corruption incidents | 0 |
| Chunk size | 10 MB per part |
| Max concurrent encrypt ops | 4 (semaphore-bounded) |
Server Memory Under Load¶
Measured using /upload/ram-status endpoint polling during a sustained 6h 56min upload:
| Phase | RAM Usage |
|---|---|
| Baseline (idle) | ~237 MB |
| Normal upload load | 243–377 MB |
| Peak (4 concurrent encrypted uploads) | 398 MB |
| Plan limit | 512 MB |
| Headroom at peak | ~114 MB |
RAM never exceeded 398 MB, keeping a safe buffer below the 512 MB plan limit throughout the entire session.
Download Performance¶
- Downloads are streamed via Wasabi presigned URLs — browser downloads directly from Wasabi
- For encrypted files, the server streams and decrypts in 10 MB chunks — memory usage is bounded
- 50 concurrent S3 connections configured in the boto3 client for parallel downloads
- Adaptive retry with up to 3 attempts per request handles transient Wasabi errors
S3 Connection Configuration¶
| Parameter | Value | Reason |
|---|---|---|
max_pool_connections |
50 | Parallel downloads for multi-file operations |
connect_timeout |
10s | Fast failure on connection issues |
read_timeout |
60s | Enough for large encrypted chunk streams |
max_attempts |
3 | Retry transient errors |
mode |
adaptive | Back-off automatically on throttling |
Gunicorn Configuration¶
| Parameter | Value | Reason |
|---|---|---|
| Workers | 1 | Avoid per-process RAM duplication |
| Threads | 6 | Handle concurrent requests within one process |
| Worker class | gthread | Thread-based async suitable for I/O-heavy workloads |
| Timeout | 120s | Allow large encrypted uploads to complete |
| Max requests | 1000 + jitter | Prevent memory drift over time |
This configuration was validated under 6h 56min sustained load. Do not increase worker count without re-validating memory usage.