Problem Running long-lived services, databases or game servers raises the question of renting elastic cloud VMs or whole dedicated servers. This guide answers which to pick for cost, latency and control.
Rented virtual machines and dedicated servers: instance families, local NVMe vs network disks, spot pricing, and when a $100 bare-metal box beats a $1000 VM.
ec2compute-enginehetznerbare-metalnvmespot
Overview
A VM is a slice of a server with network-attached disks; bare metal is the whole server with its local NVMe. Hyperscaler VMs are elastic (seconds to boot, any size, autoscaling) but expensive per core; dedicated servers from Hetzner or OVH cost 5-10x less per core and give full local NVMe speed, but take minutes to hours to provision and fail like real hardware.
Key facts
vCPU = one hyperthread, not a core. 2 vCPU ≈ 1 physical core.
Network block storage (EBS gp3, PD, Managed Disk): order of 3k-16k IOPS default, ~0.5-1 ms latency. Local NVMe: 500k-1M+ IOPS, ~0.1 ms.
Spot/preemptible VMs: 60-90 % off, can be reclaimed with 30 s (GCP) to 2 min (AWS) notice.
Arm (Graviton, Axion, Cobalt, Ampere): order of 20 % cheaper per vCPU for equal or better throughput on most server code.
Use when
Running long-lived services, databases, game servers or anything needing predictable latency and full control.
Avoid when
Load is idle most of the time (Serverless functions) or you need only containers without managing hosts.
Deep dive
Instance families (AWS names; GCP/Azure have equivalents)
Family
Ratio
For
t (burstable)
small, CPU credits
Dev boxes, tiny services; throttled when credits run out
Cost: a gp3 volume includes 3,000 IOPS and 125 MiB/s, can be provisioned to 80,000 IOPS and 2,000 MiB/s, and has single-digit ms latency (EBS docs, as of 2026-10); local NVMe is order of 500k-1M+ IOPS at about 0.1 ms. Spot Instances are up to 90 % cheaper, with a two-minute interruption notice (AWS Spot page and EC2 User Guide). Bound: IOPS and latency for databases, vCPU price for compute.
Levers:
local NVMe instead of a network volume — order of 100x the IOPS (Key facts) — databases, Kafka, search
provision gp3 IOPS and throughput independent of size — up to 80,000 and 2,000 MiB/s (EBS docs) — I/O-bound services on network disks
Spot for stateless work — up to 90 % off (AWS Spot page) — CI, batch
Arm instances — order of 20 % cheaper per vCPU (Key facts) — code that rebuilds for arm64
measure with fio using io_uring and O_DIRECT — know the real device limit before sizing (Code above) — every new box
Naive → standard → state of the art:
burstable VM, default volume, on demand · 3,000 IOPS, throttles when credits end
right family, provisioned volume, commitments, Spot for batch · IOPS and price match the load
bare metal with local NVMe, pinned threads, private network · full device IOPS, no CPU steal
Implementation notes
Use ioengine=io_uring or libaio and O_DIRECT for databases on NVMe; see io_uring.
Local NVMe on cloud VMs is ephemeral: stop/terminate wipes it. Replicate or back up continuously.
Bare metal: order RAID1 for the OS, monitor SMART, keep one spare server or a cloud fallback; disk failure is a when, not if.
Set CPU governor to performance and pin hot threads on latency-critical boxes; check steal in top on VMs.
Hetzner/OVH private networks (vSwitch, vRack) keep server-to-server traffic off the public link and free.
Pitfalls
Burstable (t-family, B-series, e2-micro/shared core) instances throttle to a fraction of a core once credits are spent; load tests pass, production stalls.
gp2/gp3 baseline IOPS and throughput are per volume; a database on one default volume caps near 3k IOPS / 125 MB/s.
Spot instances in one instance type and one AZ get reclaimed together; diversify types and zones.
Bandwidth on a "1 Gbit/s" server is shared at the switch on some budget offers; measure with iperf3.
Forgetting IPv4 cost and stopped-but-not-terminated volumes, which keep billing.