Skip to content

Benchmarks

API readslist, detail, stats, nodes · ↑ requests/s
GoWave1,169
Remnawave555
SubscriptionsXray JSON, Mihomo, sing-box · ↑ requests/s
GoWave561
Remnawave400
Memory under loadpanel container, median · ↓ MiB
GoWave60
Remnawave1,036
Startupuntil the API answers · ↓ ms
GoWave209
Remnawave7,061

GitHub Actions (4 vCPU), Docker, 2 CPU and 2 GiB per panel, PostgreSQL 17 (1 CPU) each, 1,000 users, 32 concurrent clients. Median of 3 20 s runs. Remnawave 3.4.5.

  • Remnawave 3.4.5 (remnawave/backend:3.4.5) versus GoWave at commit 349f8ed.
  • Run on GitHub Actions on a runner with 4 vCPU (AMD EPYC 7763) and 16 GB RAM. Logs, raw results and the workflow are public, so the run can be repeated.
  • Docker, each panel limited to 2 CPU and 2 GiB, each with its own PostgreSQL 17 on 1 CPU and identical settings. Remnawave also gets Valkey (0.5 CPU), which it requires.
  • The same data, created through each panel’s API: 1,000 users, 20 hosts, a profile and a squad.
  • Load is generated by k6 1.6.1: each iteration is one HTTP request. Responses are validated: an error, an empty subscription or HTML counts as a failure.
  • Run order alternates and is shuffled; every run has a warmup. Each run lasts 20 seconds, three repetitions, tables show the median.
  • Before every run both panels’ databases get CHECKPOINT and VACUUM ANALYZE, so one run does not slow down the next.
  • Latency is server response time (k6 timings.duration); p99 is the median across runs.

Concurrency mode: a fixed number of clients send requests back to back, each one right after the previous response. This shows how many requests per second a panel actually sustains.

WorkloadClientsGoWave, requests/sp99, msRemnawave, requests/sp99, msGoWave / Remnawave
Reads (mix)14724.02827.11.67×
Reads (mix)81,08415.857338.41.89×
Reads (mix)321,16962.6555122.02.11×
Reads (mix)1281,181254.1553 †556.82.14×
Subscriptions12704.62254.81.20×
Subscriptions855725.637033.41.51×
Subscriptions32561109.5400131.11.40×
Subscriptions128555451.6395 †579.41.40×
Mixed13604.12517.01.44×
Mixed877920.546332.41.68×
Mixed3283380.2470134.31.77×
Mixed128823359.1475 †540.91.73×
Writes14952.72855.01.74×
Writes81,44911.263419.82.28×
Writes321,46751.865276.52.25×
Writes1281,450225.7670288.92.16×
User list12424.51578.61.54×
User list850728.022776.92.23×
User list32508119.1213324.62.39×
User list128500513.4211 †1,111.82.38×
User detail18271.75642.61.46×
User detail82,2427.81,17010.91.92×
User detail322,35132.21,20640.61.95×
User detail1282,333125.21,193165.31.95×
Dashboard stats16632.12875.02.31×
Dashboard stats83,0465.563722.34.78×
Dashboard stats324,15521.165078.46.39×
Dashboard stats1284,30370.7649294.16.63×

† marks runs where Remnawave failed the SLO: p99 under 500 ms and under 1% errors.

Rate mode: exactly 100 or 500 requests per second. Both panels keep up, so the comparison is about response times.

WorkloadRequests/sGoWave p50 / p99, msRemnawave p50 / p99, ms
Reads (mix)1001.4 / 4.33.2 / 8.1
Reads (mix)5001.5 / 10.415.8 / 487.4
Subscriptions1002.4 / 5.12.9 / 7.2
Subscriptions5008.3 / 131.8584.3 / 10,000.7
  • Memory (median across all runs, whole panel container including workers): GoWave about 60 MiB, Remnawave about 1,036 MiB.
  • Startup until the first authenticated API response (median of 10 trials): GoWave 209 ms, Remnawave 7.1 s.
  • Dashboard stats at 32 clients and more (up to 6.4×) comes from coalescing concurrent requests: while one computation runs in the database, the others wait for its result. Such a stampede on one endpoint is rare; the everyday difference shows with a single client: 2.3×.
  • Writes from 32 clients up are limited by GoWave’s PostgreSQL, not by the application: the database, capped at 1 CPU, is throttled in 81-85% of periods, the panel container is not.
  • Nodes are not part of the test. Node management, traffic collection, HWID and real VPN clients were not measured, only the panel API.
  • This is a shared GitHub Actions virtual machine, not a capacity study: the active panel, its database and k6 share 4 cores, and runs are short. The numbers show the ratio, not absolute limits.

Full comparison

The tests live in the public gowave-bench repository: k6 scenarios, both panels in Docker, data preparation and charts. Runs happen on GitHub Actions: the workflow builds GoWave from source, pulls the Remnawave image and compares them on the same virtual machine.

Every run’s logs, machine details and raw results (in the artifacts) are public. The numbers on this page come from run 40386568113. To check them, fork the repository and run the Benchmark workflow with the full profile.