Measured, not marketed.
Every number below was produced by the load tools that ship in the repository, on a single machine running the entire stack — both gateway edges, MySQL, Redis and the load generators — at once. Nothing is extrapolated, and a message only counts when it is durably enqueued. Targets: 10,000 segments/s per process at p95 < 30 ms — both met on both edges. Dedicated hardware should expect better, not worse.
The accept path, end to end.
Client submit → authentication → the full 18-stage pipeline → durable queue write. These are not echo-server numbers: acceptance was 100% in every run, every count was cross-checked against the queue store afterwards, and each worker sends sequentially — so latency is a true per-submit round trip.
Machine B — the current reference (2026-08-18 runs)
Deliberately not a tuned server — one developer machine carrying the whole stack and the load generation together.
Machine A — the 2026-07/08 reference
The earlier runs (both-edges mix, endurance, batching) were measured here; identical tools and methodology.
One machine, one edge at a time.
Machine B, sequential-per-connection methodology — a stricter measure than a pipelined generator, since throughput = concurrency ÷ real latency. Zero failed submits at every concurrency level. (Machine A's earlier peaks — 9,290 SMPP / 3,674 HTTP submit/s, 13,435 seg/s multi-segment — are retained in the full report.)
Concurrency sweep — single segment, GSM-7 (Machine B)
| Concurrency | SMPP submit/s | SMPP p95 | HTTP submit/s | HTTP p95 |
|---|---|---|---|---|
| 25 | — | — | 9,512 | 3.2 ms |
| 50 | 19,505 | 3.5 ms | 9,848 | 6.0 ms |
| 75 | — | — | 9,592 | 9.5 ms |
| 100 | 19,692 | 7.1 ms | 10,461 | 10.9 ms |
| 150 | 16,457 | 11.9 ms | 10,539 | 15.9 ms |
SMPP holds ~19.5k submit/s through 50–100 binds, then collapses at 200 as 18 cores oversubscribe — cap binds near 100 on this class of hardware. HTTP is processing-bound at ~9.5–10.5k submit/s across every worker count — past the knee, extra workers only add latency.
9,196 msg/s with every budget met.
Machine A serving HTTP and SMPP simultaneously. The best mix — modest HTTP concurrency plus more binds — nearly matched the sum of that machine's single-edge peaks.
| Configuration | HTTP TPS | SMPP TPS | Aggregate | HTTP p95 | SMPP p95 |
|---|---|---|---|---|---|
| 100 conn + 10 binds (saturated) | 2,700 | 3,346 | 6,046 | 61.5 ms | 10.0 ms |
| 50 conn + 5 binds | 3,168 | 3,454 | 6,622 | 29.3 ms | 3.7 ms |
| 50 conn + 10 binds | 2,769 | 3,964 | 6,733 | 26.3 ms | 5.3 ms |
| 50 conn + 25 binds | 2,588 | 6,608 | 9,196 | 27.6 ms | 6.3 ms |
Endurance — 1.6 million messages (Machine A)
600,000 messages over HTTP and 1,000,000 over SMPP, concurrently: ~4,880 msg/s sustained during full overlap, 100% accepted on both edges. A separate single-recipient run held HTTP p95 at 45.3 ms for the entire five-minute run. Storage cost measured at ~1.6 KB per queued message, reclaimed as the queue drains.
Observations worth knowing.
Both targets met, single-segment, on both edges
Machine B clears the 10,000 seg/s-per-process target on HTTP alone and doubles it on SMPP, with p95 inside the 30 ms budget. Multi-segment SMPP moves ~58k seg/s at 7.3 ms — 5.8× the target.
The ceiling moves with the silicon; the shape holds
Machine A was processing-bound at ~270 µs per HTTP submit (flat ~3.4–3.7k); Machine B at ~95 µs (flat ~9.5–10.5k). Same plateau-shaped curve, ~2.9× the throughput — vertical scaling works.
Each protocol has a different concurrency dial
HTTP past the queueing knee only adds latency — fewer connections can mean more throughput. SMPP serializes per bind, so bind count is the throughput dial — but oversubscription bites: on 18 cores, SMPP holds ~19.5k through 100 binds then collapses at 200. Cap binds near 100 on this class of hardware.
Quote throughput at the latency budget
Every headline number is taken where p95 stays inside budget — not at maximum saturation. Endurance figures (not burst peaks) are the ones to use for capacity planning. The compiled Go generators behind every number ship in the repository — an interpreted generator would under-report by ~45%.
Don't take our word for it.
The compiled load generators ship in the repo, and the gateway measures itself — live counters at GET /status, fleet-wide at /status/cluster. Sweep the concurrency, find the knee, quote throughput at the latency budget.
The full BENCHMARKS.md report and the compiled load tools ship with the public repository — launching soon.
