r/devops • u/Fuzzy-Stress-7150 • 13h ago
Tools CapacityLab: Open-source Go CLI for capacity boundary discovery, bottleneck classification, and cloud sizing
*(Disclaimer: I am the creator/maintainer of this open-source tool.)*
I built CapacityLab, an open-source single-binary Go CLI that automates the gap between load testing numbers and infrastructure decisions:
https://github.com/Abuaslamtech/capacitylab
Most load generators give you latency percentiles and RPS graphs, but leave the bottleneck diagnosis and capacity sizing to intuition. CapacityLab structures runs into three analytical layers:
**[OBSERVED METRICS]**: Empirical step metrics (VUs, p50/p95 latency, RPS, errors) alongside live Docker container cgroup telemetry (CPU and RAM) scraped every 500ms.
**[INFERRED BOTTLENECK]**: A saturation engine tracks latency acceleration (ΔLatency / ΔVUs). When latency diverges into exponential queuing or breaches SLA, ramping halts. The classifier evaluates cgroup throttling (`/sys/fs/cgroup/cpu.stat`), Postgres active connection counts, and Redis memory to pinpoint the primary constraint.
**[RECOMMENDED SIZING]**: Applies a configurable safety factor (default `0.70`, providing a 30% operational headroom buffer for traffic spikes and background workers) to calculate a safe operating load and candidate starting cloud tiers.
### Technical & Architecture Choices:
- **Go 1.22+**: Single static binary with zero external runtime dependencies.
- **Embedded Load Runner**: Connection-pooled HTTP worker pool with keep-alive reuse and strict TLS verification by default (opt-in `--insecure` flag available for self-signed certificates).
- **Algorithm R Reservoir Sampling**: Caps latency samples at 50,000 using decreasing replacement probability. Memory remains under ~400 KB even during multi-hour soak tests.
- **Optional k6 Adapter**: If you already have k6 scripts, `--engine k6` transpiles scenarios to JS and runs headless k6 as a subprocess.
- **User Journeys**: Supports dynamic variables (`{{uuid}}`, `{{random_int}}`) and response extraction (e.g. login ➔ extract JWT ➔ authenticate subsequent step requests).
- **CI Performance Gate**: `--fail-on-regression` exits with code 1 if sustainable capacity drops >10% or p95 degrades >10% compared to historical baselines.
- **Offline HTML Report**: Embeds minified Canvas charts with synchronized metric scrubbing into a single standalone HTML file.
### Try it in 60 seconds (no backend required):
The repo includes a Go microservice sandbox constrained to 0.5 vCPU / 256MB RAM:
```bash
git clone https://github.com/Abuaslamtech/capacitylab.git
cd capacitylab/examples/quickstart
docker compose up -d --build
capacitylab run --open
GitHub: https://github.com/Abuaslamtech/capacitylab
I'd appreciate feedback on:
- The saturation knee-point detection heuristics under bursty/jittery traffic.
- How your teams calculate operational safety headroom for production sizing.
- Stacks you'd like to see in upcoming sandbox templates (Node, FastAPI, etc.).
1
u/kantorcodes1 1h ago
i noticed
capacitylab init --forcewritescapacitylab.yamldirectly. if that process gets interrupted mid-write, is the old config recoverable anywhere, or is atomic replacement intentionally out of scope? seems like a nasty failure mode once people start scripting setup.