Every provider’s order page sells the same four numbers: vCPU count, RAM, disk size and port speed. Three of those four are measurable in under ten minutes with tools that ship in every distro’s repositories. The fourth — port speed — is the number that is most often rounded up, and the one most buyers never check.
This is a measurement protocol, not a list of tools. Each test has a stated pass criterion, so the output is a verdict rather than a screenshot of a number. If you have not decided which tier to rent yet, our VPS plan sizing guide by workload explains what each spec tier is actually for; this page covers how to verify you received it.
What Each Test Can and Cannot Prove
| Test | Measures | Can prove | Cannot prove |
|---|---|---|---|
iperf3 TCP single stream | Bulk throughput | Port speed floor, shaping | Small-packet performance |
iperf3 -P 8 | Aggregate throughput | Whether a quota is per-flow | Per-connection latency |
iperf3 -u -b | Loss and jitter at a rate | UDP shaping, policer drop | TCP fairness behaviour |
ping -f / flent | Latency under load | Bufferbloat depth | Route quality |
mtr -rwzc | Per-hop loss and RTT | Where loss enters the path | Why that hop is slow |
sysbench cpu | Single-core speed | CPU generation class | Sustained multi-core (needs 5 min) |
fio with --iodepth=32 | 4K IOPS at depth | Provisioned IOPS tier | Cross-tenant variance over hours |
Step 1: Establish the Reference Endpoint
Throughput between your VPS and an arbitrary public server measures the internet, not the VPS. Use a second host you control, or accept that public iperf3 servers are shared and often rate-limited. Pick a target within 200 km of the provider’s region — a transatlantic test cannot validate a 1 Gbps port because a single TCP stream will not fill it.
# On the reference host
apt install -y iperf3
iperf3 -s -p 5201 --forceflush
# On the VPS, start with the baseline
sudo apt install -y iperf3 mtr-tiny sysbench fio
iperf3 -c ref.example.net -p 5201 -P 1 -t 20 -O 3 -J > /tmp/iperf_p1.json
-O 3 skips the first three seconds, which are dominated by slow start and will make a healthy link look 20% short. -J gives you JSON so you can compare runs rather than eyeballing Mbit/s.
The pass criterion: single-stream throughput within 80% of the advertised port speed, and no more than 15% variance across three runs. A 1 Gbps port that delivers 620 Mbit/s per stream usually indicates a 700 Mbit/s shaping ceiling or a CPU-bound iperf3 on a small instance — not necessarily a dishonest provider. Repeat with -P 4 before drawing a conclusion.
Step 2: Separate “Per-Flow Limit” from “Total Limit”
This is the single most useful network test on a cheap VPS. Many providers police per-flow rather than in aggregate. If 1 stream gives 250 Mbit/s and 8 streams still give 250 Mbit/s, you have a total cap. If 8 streams give 1,000 Mbit/s, you have a per-flow policer and your bulk transfer tools should use more than one connection.
for p in 1 4 8; do
iperf3 -c ref.example.net -P $p -t 20 -O 3 -f m | awk -v p=$p '/sender/{print "P="p, $7, $8}' | tail -1
done
| P=1 result | P=8 result | Interpretation | Action |
|---|---|---|---|
| 940 Mbit/s | 945 Mbit/s | Genuine 1 Gbps port | None |
| 250 Mbit/s | 260 Mbit/s | Hard aggregate cap | Tune for latency, not bulk |
| 250 Mbit/s | 900 Mbit/s | Per-flow policer | Parallelise backup and migration transfers |
| 400 Mbit/s | 410 Mbit/s | CPU-bound at ~400 Mbit/s | Check top: iperf3 at 100% of one core |
The last row is common on 1-vCPU instances. iperf3 in userspace saturates a single core at roughly 500–700 Mbit/s depending on MTU and whether checksums are offloaded. Before blaming the provider, confirm with mpstat -P ALL 1 5 that you were not CPU-bound on the test itself.
Step 3: Prove or Disprove a UDP Policer
Providers that advertise “1 Gbps” while selling a 100 Mbps plan often rate-limit UDP differently from TCP. Run a fixed-rate UDP test and read the loss column; a policer shows up as loss that climbs in a step at a specific rate.
for b in 50M 150M 400M; do
echo "=== offered $b"
iperf3 -c ref.example.net -u -b $b -t 10 -O 2 | grep -E 'receiver|Lost'
done
Zero loss at 400 Mbit/s offered with 380 Mbit/s delivered means no UDP policing below 400. Loss appearing between 150 M and 400 M locates the ceiling within that band. Bisect once more to narrow it — the exact number is useful evidence if you need to open a support ticket.
Step 4: Measure Latency Under Load, Not Idle
A link that pings at 12 ms idle and 180 ms while saturated is worse than one that pings at 30 ms idle and 35 ms loaded, for anything interactive. Run the RTT measurement concurrently with the bulk transfer.
# Terminal 1: saturate the link
iperf3 -c ref.example.net -t 60 -P 4 >/dev/null
# Terminal 2: sample RTT during saturation
ping -i 0.2 -c 150 ref.example.net | tail -3
Compare mdev and max RTT against the idle baseline. A jump of more than 5× indicates a deep buffer on the path with no active queue management. fq_codel on the VPS’s egress can help your own outbound traffic, but it cannot fix bufferbloat in the provider’s uplink — that is a reason to change providers, not a tuning task.
Step 5: Read the Route with mtr, Correctly
The standard misreading of mtr is treating loss at an intermediate hop as a fault. Many routers deprioritise ICMP TTL-expired replies to their own address while forwarding traffic perfectly. The rule: only loss that persists to the final hop matters.
mtr -rwzc 200 -i 0.2 ref.example.net
-rreport mode,-wwide,-zshow AS numbers,-c 200enough samples for a stable loss figure.- Loss at hop 4 of 8% and 0% at hop 8: the hop is rate-limiting ICMP. Ignore it.
- Loss that starts at hop 6 and continues at 8: real loss on that segment. Note the AS on hop 6 and 7 — that is who to talk to.
- RTT that steps up 40 ms at a hop and stays up: a real long-haul segment, not congestion. Check whether it matches the physical distance.
Step 6: The Disk and CPU Floor
Network numbers mean little if the instance cannot feed the NIC. Two short tests set the floor. Run sysbench cpu for a full five minutes to catch the burst-credit collapse that many providers apply to the first minute of CPU usage.
sysbench cpu --threads=1 --time=300 run | grep 'events per second'
fio --name=randread --ioengine=libaio --direct=1 --bs=4k --iodepth=32 \
--rw=randread --size=1G --runtime=60 --time_based --group_reporting
Compare the first 60-second window against the fifth. A drop of more than 30% in events per second means you are on a burst plan, and the sustained number is the one to plan capacity around. For fio, look at the clat p99 rather than the average — a 4K read average of 0.4 ms with a p99 of 9 ms describes a shared backing store with a noisy neighbour on it.
Recording the Result So It Means Something in Six Months
Store one line per run in a file you keep outside the VPS, so it survives a provider migration:
echo "$(date -Is),$(hostname),$(iperf3 -c ref.example.net -P 4 -t 15 -O 3 -f m | awk '/sender/{print $7}'),\
$(mtr -rwzc 100 -i 0.2 ref.example.net | tail -1 | awk '{print $6}')" >> ~/baseline.csv
Re-run quarterly and after every plan change. The value is in the delta. Our VPS benchmark reference lists the ranges these tests should land in per tier.



Leave a Reply
You must be logged in to post a comment.