Buying guide

What makes a good Iran server? How to test VPS performance in 9 hands-on checks

Testing an Iran server's quality in a Linux terminal with vmstat, fio and mtr output on a virtual server

You can't recognize a good Iran server from its ad copy; you have to measure it. This guide shows how to test VPS performance with 9 hands-on tests and real commands — from CPU steal time and true NVMe speed to network quality inside Iran and the health of your IP address — and gives the healthy number for each, so you can document an oversold host before you sign up for anything long term.

What makes a good Iran server? A definition you can measure

A good Iran server gives you the resources you actually paid for, doesn't slow down when its neighbors get busy, and keeps a short, stable network path to users inside the country. Every part of that definition can be checked with a command. Adjectives like "blazing fast" and "professional-grade" have no number behind them, so there's nothing to verify.

The root of nearly every bad experience is an oversold host: the provider has put more customers on one physical server than it can carry, betting that they won't all use their share at the same time. The result is "random slowness" — a database query that takes 20 milliseconds one moment and 2 seconds the next.

Eight of the nine tests in this article take less than two hours; only the stability test needs 48. With hourly cloud server billing you can pay for just those hours and delete the server if it fails. What that evaluation period costs, and the point beyond which hourly stops being worth it, is worked out with a formula in our guide to hourly server costs and the break-even point.

How to test VPS performance: which tools do you need?

You need seven standard tools: sysstat for steal time, fio for the disk, sysbench for CPU consistency, iperf3 for bandwidth, mtr for the network path, dig for rDNS and whois for the IP's history. All of them are in the distributions' official repositories and install in under a minute.

# Ubuntu / Debian
sudo apt update
sudo apt install -y sysstat fio iperf3 mtr-tiny sysbench whois
sudo apt install -y bind9-dnsutils || sudo apt install -y dnsutils   # package name on older releases

# AlmaLinux / Rocky
sudo dnf install -y epel-release
sudo dnf install -y sysstat fio iperf3 mtr bind-utils sysbench whois

Run the tests on a freshly delivered, idle server, and run each one twice: once at a quiet hour and once at peak time. The difference between those two runs is the most important number of all.

Test 1: CPU consistency and VPS steal time — measure the pressure on the host

Steal time is the percentage of time your virtual CPU was ready to run but the hypervisor gave the physical core to another machine. It's the most direct sign of an oversold CPU, and it appears in the st column of vmstat output. The healthy figure is 0 to 1 percent.

vmstat 5 120
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
#  r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
#  1  0      0 1583220  61240 402188    0    0   509    77    6    4   3  2 95  0  0   <- ignore this line
#  0  0      0 1583688  61240 402196    0    0     0     0  312  598   2  1 97  0  0

The first line of vmstat output is an average since boot, not the current state, so ignore it. An interval of 5 seconds and 120 samples gives you 10 minutes of continuous observation — the window you need to judge steal time.

mpstat -P ALL 2 10
# 09:28:45 PM  CPU   %usr  %nice   %sys %iowait   %irq  %soft %steal %guest %gnice  %idle
# 09:28:47 PM  all   1.01   0.00   0.25    0.00   0.00   0.00   0.00   0.00   0.00  98.74
# 09:28:47 PM    0   0.00   0.00   0.00    0.00   0.00   0.00   0.00   0.00   0.00 100.00

mpstat breaks the same figure down core by core; the column you want is %steal, and the all row is the average across cores. In practice, st holding steady below 1 percent means the host has headroom, and short spikes up to 5 percent are nothing to worry about. What you should write down is how long the number stays up, not its momentary peak. If the r column is consistently larger than your number of vCPUs, tasks are queuing for the processor.

The spread of a sysbench CPU test matters more than the score

for i in 1 2 3 4 5; do
  sysbench cpu --cpu-max-prime=20000 --threads=1 run | grep "events per second"
done

The absolute number depends on the CPU generation; what you're looking for is the spread. If the five runs land within a few percent of each other, your share of the CPU is real. If one run drops 30 percent below the others, the core was taken away from you at that moment. Newer kernels offer a complementary indicator as well:

cat /proc/pressure/cpu
# some avg10=0.12 avg60=0.18 avg300=0.15 total=94812733

some avg10 is the percentage of the last 10 seconds during which at least one process was waiting for the CPU; below 10 is healthy. PSI (Pressure Stall Information) measures pressure from the point of view of the guest's own scheduler, so it can't see the host's steal. High st with low PSI means the pressure comes from the host; high PSI with zero st means your own workload is more than your vCPUs can handle.

⚠️ PSI is enabled by default on Ubuntu and Debian, but it's off on AlmaLinux and Rocky, where /proc/pressure doesn't exist. To turn it on, add the kernel parameter and reboot:
sudo grubby --update-kernel=ALL --args="psi=1"
sudo reboot

Test 2: true NVMe speed with an fio benchmark — and why dd misleads

The disk number that matters most for websites and databases isn't sequential bandwidth; it's random 4K read and write IOPS and the latency that comes with them. Your database reads thousands of small, scattered blocks, and that's exactly where genuine NVMe parts ways with a tired shared disk. The right tool is fio with the --direct=1 flag, which bypasses the operating system's page cache:

fio --name=randread --filename=/root/fiotest --rw=randread --bs=4k \
    --ioengine=libaio --direct=1 --iodepth=32 --numjobs=1 \
    --size=2G --runtime=60 --time_based --group_reporting
⚠️ On its first run, fio creates the 2 GB test file itself, so that run takes longer; keep --size below your free space. And never point --filename at a block device such as /dev/vda: a write test will irreversibly destroy whatever is on the disk.

Repeat the same test for writes, because many storage systems are only good at reading:

fio --name=randwrite --filename=/root/fiotest --rw=randwrite --bs=4k \
    --ioengine=libaio --direct=1 --iodepth=32 --numjobs=1 \
    --size=2G --runtime=60 --time_based --group_reporting

# single-request latency — the number closest to how a database really feels
fio --name=lat --filename=/root/fiotest --rw=randread --bs=4k \
    --ioengine=libaio --direct=1 --iodepth=1 --size=2G --runtime=30 \
    --time_based --group_reporting

rm -f /root/fiotest

Reading fio output: IOPS, single-request latency and the 99th percentile

In the output, look for three things: IOPS, the clat percentiles line, and the 99th percentile. Set your yardstick before you read the numbers — these thresholds are for a shared virtual machine tested with --iodepth=32, not for a raw disk on bare metal, whose numbers are several times higher. Below 5,000 IOPS is a fail. From 5,000 to 20,000 is suspicious: probably a heavily loaded shared NVMe or an artificial cap. Above 20,000 is acceptable, and above 50,000 is genuine NVMe under light load. Capping each machine's IOPS isn't a bad sign in itself, and nearly every serious provider does it; what you should reject is a cap that's undisclosed and keeps changing. So run the same test three times at different hours. If the number repeats all three times, the cap is engineered; if it's different every time, you're fighting your neighbors.

Single-request latency should stay at a few hundred microseconds. If it climbs to several milliseconds, what you were sold either isn't NVMe or has been divided so finely that it makes no difference. A 99th percentile far above the median means requests are queuing.

⚠️ Why you should set dd aside: without oflag=direct you're measuring the RAM cache, and because the data it writes is pure zeros, on compressing or thin-provisioned storage it may never reach the disk at all. If a seller shows you only this number, ask for fio output.

The four quality layers of a good Iran server, and how to measure each

Diagram of the four quality layers of a good Iran server — hardware and disk, virtualization, network and provider — with the sign of health and the tool that measures each layer

Server quality isn't one number. It's four independent layers, and each one can fail on its own: the hardware and your real share of it, the virtualization, the network inside Iran, and the provider itself. The table below runs from the symptom you notice to the healthy result.

Symptom you noticeLikely real causeTestHealthy result
Erratic slowness, especially at nightCPU overselling on the hostvmstat 5 120st column below 1%
Database queries sometimes take secondsI/O queuing on a heavily loaded shared diskfio with --direct=1Random 4K reads above 20,000 IOPS
Kernel modules won't loadThe service is really a container, not KVMsystemd-detect-virt and modprobe dummyOutput kvm and the module loads
Services crash at randomLess RAM than you were sold, or OOM killsfree -m and journalctl -kNo oom-killer entries
The site is slow for some of your usersWeak peering with one particular carriermtr -rwzc 100Zero packet loss; latency jump between two hops under 30 ms
Your emails land in spamIP on a blocklist, or no rDNSdig -x IP and blocklist checksValid PTR record, not listed
The server rebooted without warningHost instability or a forced migrationjournalctl --list-bootsOnly reboots you made yourself

Test 3: check if a VPS is really KVM or just a container

Many services sold as a "virtual server" are actually containers: you don't get your own kernel, and kernel modules won't load. The healthy answer is exactly kvm, and take the difference from qemu seriously: the latter means hardware acceleration is not enabled.

systemd-detect-virt
# kvm   -> full virtualization with hardware acceleration
# qemu  -> software emulation without KVM (slow)
# lxc / openvz -> a container, not a virtual machine

ls /proc/user_beancounters 2>/dev/null && echo "OpenVZ container"
sudo modprobe dummy && lsmod | grep dummy && sudo modprobe -r dummy   # succeeds only on KVM
grep -c -E "vmx|svm" /proc/cpuinfo    # zero means no nested virtualization
rpm -q kernel 2>/dev/null || dpkg -l | grep -c '^ii  linux-image'   # is a kernel package installed?

The presence of /proc/user_beancounters is a sure signature of an OpenVZ container, but loading a kernel module is the more conclusive test: if modprobe dummy comes back with Operation not permitted, the kernel isn't yours, and whatever you were sold isn't KVM. uname -r proves nothing, because inside a container you see the host's kernel too; a more telling sign is whether a kernel package is installed and can be upgraded. Successfully running Docker on a cloud server isn't proof of KVM either, since it also runs inside a nested container. We explain the concepts in KVM and NVMe in plain language; what this article adds is the pass-or-fail threshold. And if you plan to bring up a layer-3 tunnel on this server, repeat the module test with modprobe ip_gre — our guide to choosing a tunnel server explains why.

Test 4: real RAM, swap and traces of the OOM killer

RAM is the second place where overselling shows itself — not as slowness, but as services that suddenly get killed. First check how much RAM you actually received, then look at the history: if the kernel has killed a process to save the system, the trace is still in the log.

free -m
swapon --show
grep -E "MemTotal|MemAvailable" /proc/meminfo
lsmod | grep -i balloon

journalctl -k | grep -iE "out of memory|oom-killer|killed process"
cat /proc/pressure/memory

MemTotal is always lower than the figure you bought, and that's normal: gigabytes versus gibibytes, the kernel's own reservation, and on AlmaLinux and Rocky the crashkernel reservation. On an 8 GB machine, free -m shows about 7,500, which is nothing to worry about. What's abnormal is a gap of more than 10 percent — or MemTotal changing during the day, which means the host is ballooning, that is, reclaiming memory from your guest.

On a freshly delivered server, the OOM search should return nothing (if /proc/pressure/memory is missing, the PSI note above applies). An OOM record on a new server means either the real RAM is smaller than what was sold, or the server is second-hand and was never wiped. We explain how to tell a real RAM shortage from cache in our Linux server monitoring guide.

Test 5: measure network quality inside Iran from all three carriers

You buy an Iran server for its network, so test the network more seriously than anything else. The golden rule: test from all three of Iran's main carriers — MCI (Hamrah-e Aval) and Irancell, the two big mobile operators, and TCI (Mokhaberat), the fixed-line incumbent — because every datacenter peers differently with each carrier, and your visitors come from all three.

Don't run the commands below on the server; run them from the user's side toward the server. The easiest way is to tether a laptop to a phone hotspot: once on MCI, once on Irancell, and once on a fixed line.

ping -c 100 SERVER_IP | tail -3
# --- 203.0.113.10 ping statistics ---
# 100 packets transmitted, 100 received, 0% packet loss, time 99143ms
# rtt min/avg/max/mdev = 11.4/14.8/38.1/3.2 ms

mtr -rwzc 100 SERVER_IP

Record three numbers. Packet loss must be zero (even a steady 1 percent costs TCP dearly), mdev should stay below 10 ms on a domestic route, and max shouldn't be several times min. Take the same three numbers at 6 a.m. and at 11 p.m.; the difference between the two runs is your evidence of an oversold network. We look at the causes of latency separately in our guide to reducing server ping.

Reading mtr correctly: which packet loss is real?

mtr breaks the route down hop by hop and shows where the latency jump begins. An important caveat: some intermediate routers give low priority to ICMP and don't answer it, so the Loss column shows them in red. Only worry when the loss starts at one hop and continues all the way to the last hop.

Test 6: what is the server's real bandwidth? An iperf3 bandwidth test

Measure real bandwidth only with iperf3 between two endpoints you control, not by the advertising phrase "1 Gbps port". A single stream won't reach the port's ceiling, so use several parallel streams, and repeat the test in both directions to expose an asymmetric cap on upload or download.

# port 5201 must be open — Ubuntu/Debian:
sudo ufw allow 5201/tcp
# AlmaLinux/Rocky:
sudo firewall-cmd --add-port=5201/tcp

# on the server
iperf3 -s

# from the client or a second server
iperf3 -c SERVER_IP -t 30 -P 4        # upload to the server
iperf3 -c SERVER_IP -t 30 -P 4 -R     # download from the server

If you're testing from a home connection, the bottleneck is probably your own line. When you're done, stop iperf3 -s with Ctrl+C and close the port again. Ookla's official Speedtest client (which isn't in the default repositories) gives a rough figure but doesn't replace iperf3, because the bottleneck may be the speed-test server at the other end. Monthly traffic volume is the subject of our VPS bandwidth guide.

Test 7: IP address health and history

The IP address is part of what makes a good Iran server too, and it can be second-hand and burned. If your IP was used to send spam in the past, your emails will land in spam folders and some services will block you — without any of the earlier tests showing a thing.

dig -x 203.0.113.10 +short          # the PTR record, i.e. rDNS
whois 203.0.113.10 | grep -iE "netname|descr|country|org"

Check three things. First, rDNS: the IP must have a PTR record, and the provider must let you change it; without one, sending email from the server is pointless. Second, range registration: the whois output should show a clear netname and org, not an anonymous block. The country field in a RIPE record is administrative and doesn't prove where the server really is; services look at commercial geolocation databases instead, so check the IP's geolocation separately. If it doesn't match the datacenter's location, domestic Iranian services will refuse access, and your site's analytics will count Iranian visitors as foreign. Third, blocklists: if the IP is on one, ask for a replacement on day one.

Test 8: stability over time — does the server reboot without warning?

No snapshot of a single moment proves stability. Keep the server running for at least 48 hours, then look at the boot history and the kernel log. The pass criterion is simple: every recorded reboot must be one you made yourself, and dmesg must show no disk errors or long I/O stalls.

The prerequisite is a persistent journal; otherwise the logs are wiped on every reboot. On AlmaLinux and Rocky, turn it on in the first hour:

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

uptime -p
journalctl --list-boots | tail -5
last -x reboot | head
journalctl -k -p err -b -1 | tail -20
dmesg -T | grep -iE "I/O error|hung task|clocksource|blk_update_request"

With a volatile journal, -b -1 is always empty, and an empty result is no sign of health; in that case rely on last -x reboot, which reads from wtmp. A reboot you didn't make means the host crashed or the server was migrated. I/O error and blk_update_request messages are traces of failing storage, and hung task means a process was stuck in uninterruptible sleep for at least 120 seconds — the default of kernel.hung_task_timeout_secs — in other words, an I/O request never came back.

Test 9: test the provider itself

The fourth layer is human, and no command measures it, so you have to test it on purpose.

Four things to ask of a provider before a long-term commitment

  • Put a number on ticket response time, not a feeling. Send two real technical tickets — for example, a request to change the rDNS of this very IP — one in the middle of a working day and one after midnight, and record how long each takes to get its first human reply. The number that matters is the second one; a server failure doesn't keep office hours.
  • Billing transparency. You should be able to see every deduction from your wallet itemized, and understand which hour and which resource each amount was for.
  • VNC console. Test it before you need it: if you ever break your SSH configuration or your firewall, the console is your only way back in.
  • OS reinstall. Reinstall once and time it; a reinstall that takes a few minutes means any risky experiment can be undone.

Track record matters too: a company that has spent years in shared web hosting usually has a more mature support process.

Iran VPS benchmark checklist: eight steps in an hour, the ninth in 48 hours

The order of the steps deliberately doesn't follow the test numbers; it's arranged fastest first:

  1. Virtualization — Test 3 (1 minute): systemd-detect-virt must return kvm; any other output means you can stop right here.
  2. Resources and RAM — Test 4 (3 minutes): lscpu, free -m and df -h should match what you bought, and journalctl -k | grep -i oom should be empty.
  3. Steal time — Test 1 (10 minutes): vmstat 5 120 and mpstat -P ALL 2 10; st below 1%.
  4. CPU consistency — Test 1 (5 minutes): five sysbench runs within a few percent of each other.
  5. Disk — Test 2 (5 minutes): three fio runs: random read, random write and single-request latency.
  6. Network — Test 5 (10 minutes): ping and mtr from all three carriers, with no packet loss.
  7. Bandwidth — Test 6 (5 minutes): iperf3 in both directions with several parallel streams.
  8. IP health — Test 7 (5 minutes): PTR record, whois and blocklists.
  9. Stability and provider — Tests 8 and 9 (48 hours): leave the server running, send your tickets, try the VNC console and an OS reinstall, and finally check journalctl --list-boots.
💡 Tip: The first eight steps take less than an hour of work, and the ninth is just waiting. See what your chosen configuration costs in the calculator on our homepage.

Frequently asked questions

What is the fastest way to tell whether an Iran server is good?

Run three commands in ten minutes: systemd-detect-virt must return kvm, vmstat 5 120 must show the st column below 1 percent, and one fio run with --direct=1 must pass 20,000 IOPS on random 4K reads. If all three pass, the hardware and virtualization layers are sound, and the network and stability tests are worth your time.

How much steal time means a VPS is oversold?

Steal time that stays above 5 percent for ten minutes straight means you're competing with neighboring machines for the CPU, and above 10 percent means the host has been sold beyond its capacity. On a healthy server, the st column in vmstat stays between 0 and 1 percent, and short spikes up to 5 percent are normal. Repeat the test during the evening peak as well, when the neighbors are busiest.

Why can't dd measure the real speed of an NVMe disk?

Because dd measures sequential writes, not the real load of a website or database, which is random reads and writes of small blocks. Unless you add oflag=direct or conv=fdatasync, you're effectively measuring the speed of the RAM cache, and because the input is pure zeros, compressing storage may write almost nothing to the disk. The right tool is fio with --direct=1.

Why does my server have less RAM than I paid for?

Part of the gap is normal: gigabytes versus gibibytes, memory the kernel reserves for itself and its memory-management structures, and on the RHEL family the crashkernel reservation. On an 8 GB machine, free -m shows about 7,500, which is fine; a gap of more than 10 percent is not. If MemTotal changes during the day, virtio_balloon is taking RAM back, and an oom-killer record on a new server means the real RAM is smaller than what was sold.

Does a 60 ms ping over mobile internet mean the server is bad?

Not necessarily. On mobile, much of the latency is added by the radio network, and 30 to 70 ms is normal for a server inside Iran; from a fixed line, the same server usually gives 5 to 30 ms. What should worry you is packet loss and high jitter, not the average. If mtr shows loss that starts at one hop and continues all the way to the destination, the problem is the route.

Next step

No ad copy can replace these nine numbers. A good Iran server isn't something you pick from a comparison table; it's what comes out of a numeric filter — and building that filter takes one afternoon. Our suggestion is simple: create an hourly cloud server at Mehran Host — it's usually ready in under 60 seconds — run the checklist above, and compare the results with any other server you have. If the numbers convince you, keep it; if not, delete it, and you've only paid for a few hours. We've collected the criteria to weigh before you buy in our VPS buying guide.

Related tutorials

Ready for some hands-on practice?

A Mehran Host hourly cloud server is ready in under 60 seconds. Practice as much as you like and pay only for the hours you use. Estimate the cost with the pricing calculator before you sign up.