Hi everyone,
I recently set up a load-testing environment using Apache JMeter to benchmark the login endpoint performance of Frappe. While Frappe’s baseline performance is fantastic (vastly outperforming my baseline Django tests), I am looking for community advice on how we can tune the framework to eliminate bottlenecks and achieve a 100% success rate—while keeping response times low—even under brutal concurrency spikes.
System & Environment Specs
All tests were run locally (native execution, no virtualization):
- Hardware: Apple Macbook Air M2 (8 CPU cores), 16 GB LPDDR5 RAM
- OS: macOS Sequoia 15.7.7
- Python: 3.14.4 (Homebrew build)
- WSGI: Gunicorn (4 workers,
syncclass,--preloadenabled). - Databases: MariaDB for Frappe (with Redis cache/sessions).
- Frappe Version: 17.0.0-dev (Production Mode)
The Bottleneck: Extreme Concurrency & Response Times
Under high load with a gradual ramp-up (e.g., 2,000 to 4,000 threads spread over 30–50 seconds), Frappe easily maintains a 100% success rate with average latencies well under 50ms.
However, when testing aggressive traffic spikes (a short 10-second ramp-up), not only does the success rate drop significantly, but response times become a major concern. Given that all tests were run locally—meaning zero external network latency—the spike to ~4000ms average response time at 4K threads indicates a severe internal bottleneck.
| Threads | Ramp-up | Success Rate | Avg Latency | 95th Percentile | Throughput |
|---|---|---|---|---|---|
| 500 | 10s | 100.00% | ~26 ms | ~69 ms | ~100/s |
| 1000 | 10s | ~99.9% | ~780 ms | ~1224 ms | ~166/s |
| 2000 | 10s | ~80.0% | ~2764 ms | ~7774 ms | ~251/s |
| 4000 | 10s | ~59.1% | ~4016 ms | ~7776 ms | ~404/s |
(Test Config: GET to /login –> POST to /api/method/login submitting credentials)
The Goal: Reaching Maximum Efficiency
I want to figure out how to push those 2K and 4K (10s ramp-up) numbers to a 100% success rate and bring the response times back down to acceptable levels.
- Gunicorn Tweaks: Should I move away from the default
syncworkers togthreadorgeventworkers for Frappe to handle concurrent connections better? - Database Pooling: Are there specific MariaDB connection limits or timeout configurations that usually cause these dropped requests and delayed response times during a spike?
- OS/Environment Limits: Given this is running locally, could this primarily be macOS socket/file descriptor limits (
ulimit) bottlenecking the test, rather than the framework itself?
For those who want to dig deeper into the exact JMeter HTML reports, test plans, and the Django comparison data, you can find my full repository here:
Frappe_and_Django_Framework_LoadTests
I’d love to collaborate on finding the optimal configuration to squeeze every bit of performance out of Frappe under heavy load!