Most load testing tools start every run at full concurrency. You say --c 500, and immediately 500 goroutines fire requests at your target. This works, but it hides something important: how your system behaves as load increases.
GoStress v1.1 introduces the --ramp flag — a simple way to gradually scale from 1 to N workers over a configurable duration, giving you a clearer picture of where your system starts to bend.
The Problem with Instant Concurrency
When you slam a server with 500 simultaneous connections on the first request, several things happen at once:
- Connection pools fill up instantly
- Thread/worker pools saturate before they can warm up
- Rate limiters trigger immediately
- Load balancers may not have time to distribute traffic
The result? Your p50 latency might be 200ms, but that number is measured after the system is already under full stress. You miss the early warning signs — the point where latency starts climbing, where errors first appear, where throughput plateaus.
How Ramp Works
The --ramp flag takes a single integer: the number of seconds over which concurrency scales from 1 to your target --c value.
gostress --url https://api.example.com/health
--c 500 --d 60 --ramp 30
Under the hood, GoStress spawns new workers in small batches every ~100ms, tracked by a delta-based goroutine manager. The progress bar shows your current concurrency level in real time:
Test Progress: 4.3% | Concurrency: 93
Test Progress: 6.5% | Concurrency: 140
Test Progress: 8.7% | Concurrency: 187
...
What You'll See Differently
With ramp enabled, your HTML report tells a richer story:
Latency Curve
Instead of a flat latency number, you'll see p50 climb gradually as concurrency increases. If p50 jumps from 50ms to 500ms between worker 100 and worker 200, you've found your saturation point — without having to guess.
Error Onset
Transport errors (deadline_exceeded, connection refused) often don't appear at low concurrency. Ramp reveals the exact concurrency level where your target starts rejecting connections.
Throughput Plateau
If throughput stops increasing at 300 workers even though you ramp to 500, you know the bottleneck is on the server side, not the client.
When to Use Ramp
| Scenario | Use Ramp? | Why |
|---|---|---|
| CI/CD smoke test | No | Quick pass/fail, full concurrency is fine |
| Capacity planning | Yes | Find the exact concurrency ceiling |
| Pre-production soak test | Yes | Simulate realistic traffic growth |
| Breaking point discovery | Yes | See where errors first appear |
| Comparing two deployments | Yes | Side-by-side latency curves are more informative than single numbers |
Tip: A good rule of thumb is to set ramp to about half your test duration. For a 60-second test, use --ramp 30. This gives you 30 seconds of ramp and 30 seconds at full concurrency.
Validation Rules
GoStress validates ramp input to prevent misuse:
--ramp 0— No ramp, workers start immediately (default)--ramp 5on a--d 3test — Rejected. Ramp must be shorter than duration.--ramp -1— Rejected. Ramp cannot be negative.
Try It Now
If you already have GoStress installed, pull the latest version and try ramp on your own API:
go install github.com/unnivm/gostress@latest
# Ramp test
gostress --url https://your-api.com/endpoint --c 200 --d 45 --ramp 20 --formats html
Open the generated report.html and watch the latency distribution tell the full story.