dm-crypt and LUKS Encryption Overhead on a VPS: Measuring the Real Cost of AES-NI

Encrypting a VPS disk used to mean paying a heavy performance tax. With AES-NI hardware acceleration present, that tax is often under five percent for throughput and near zero for large-block sequential I/O — but only if the crypto is configured correctly and the CPU actually has the instructions. This article shows how to measure the real overhead of dm-crypt and LUKS on your specific instance, and how to configure it so you neither lose performance nor weaken security.

Disk encryption sits alongside the storage topics in our VPS performance tuning guides. The method is identical: benchmark unencrypted, benchmark encrypted, and let the delta — not intuition — decide your configuration.

Confirm AES-NI and the Kernel Crypto Path

Before anything else, verify that your CPU exposes the AES instructions and that the kernel is using the accelerated path. Without AES-NI, encryption becomes a significant CPU cost and changes every calculation below.

grep -m1 -o 'aes' /proc/cpuinfo
cryptsetup benchmark

# kernel crypto self-test and available implementations
ls /sys/crypto
grep -i aes /proc/crypto | head

cryptsetup benchmark reports throughput for different cipher and key-size combinations. Compare the AES-XTS numbers with the ChaCha20 numbers; on a CPU with AES-NI, AES-XTS will be dramatically faster, which tells you to use it. If AES-NI is missing, XTS on CPU is slow and you should reconsider the design entirely.

Benchmark the Unencrypted Baseline First

You cannot measure overhead without a reference. Use fio against a file or partition on unencrypted storage, with both random and sequential profiles, and save the results.

fio --name=seq --ioengine=libaio --direct=1 --rw=write --bs=1M \
  --size=2G --numjobs=1 --runtime=60 --time_based --group_reporting

fio --name=rand --ioengine=libaio --direct=1 --rw=randrw \
  --bs=4k --iodepth=16 --numjobs=4 --size=1G --runtime=60 --time_based --group_reporting
  • Sequential 1M write isolates raw bandwidth and is the friendliest case for encryption
  • Random 4k rw at depth 16 is the CPU-heaviest case for the crypto layer
  • Record p99 latency as well as IOPS, because encryption adds per-I/O CPU time that shows up in tail latency
  • Run each test twice to rule out page-cache warm-up effects

Create the Encrypted Volume and Re-run the Same Tests

Set up a LUKS2 volume, open it, and run exactly the same fio commands against it. Keeping the test identical is what makes the comparison meaningful.

cryptsetup luksFormat --type luks2 /dev/vdb
cryptsetup luksOpen /dev/vdb cryptdata
mkfs.ext4 /dev/mapper/cryptdata
mount /dev/mapper/cryptdata /mnt/crypt

# verify the active cipher
cryptsetup status cryptdata
dmsetup table cryptdata

dmsetup table shows the exact cipher specification in use, for example aes-xts-plain64 with a 512-bit key. What you configure and what is actually active are not always the same, so always confirm with the table output.

Now rerun both fio profiles. Expect sequential write throughput to drop only slightly, perhaps a few percent. Random 4k I/O is where the CPU cost is most visible, because every I/O pays the crypto fixed expense. Compare IOPS, bandwidth and p99 latency side by side.

Interpret the Numbers Correctly

A modern VPS with AES-NI usually shows single-digit percentage throughput loss on sequential I/O and a modest IOPS reduction on random 4k. If you see twenty or thirty percent loss, something is wrong: the crypto is running on the generic (non-accelerated) path, or you sized the volume with a weaker but slower configuration.

perf stat -e cycles,instructions -a sleep 10
perf top --sort cpu | grep -i -E 'aes|crypt|xts'

Watch CPU during the encrypted test. If a core is pinned near 100 percent while disk utilisation is low, the crypto is the bottleneck — not the disk. This is common on single-vCPU instances where cryptography and I/O share one core. On such instances, consider a larger instance rather than fighting the ceiling.

Tuning Options That Actually Reduce Overhead

Enabling queue-based or asynchronous crypto, and choosing the right sector size, both reduce the cost. These are the levers worth pulling.

  • --sector-size 4096 on ext4 aligns encryption to the filesystem and cuts per-sector overhead
  • Use aes-xts-plain64 with 512-bit key on AES-NI hardware, the fastest mainstream choice
  • Enable the kernel’s crypto API async path / AF_ALG if your workload benefits
  • Align partitions to 1 MiB so encryption never straddles physical blocks unnecessarily
  • Keep noatime and an appropriate discard policy to avoid metadata writes

Sector size deserves emphasis. Modern disks and filesystems work in 4 KiB units; LUKS defaulting to 512-byte sectors adds overhead per sector. Formatting with --sector-size 4096 on a fresh volume measurably improves random I/O and reduces CPU per byte.

Keys, Backups and the Operational Cost

Encryption changes your recovery story, and that is a real cost even when performance is not. If the LUKS header is lost, the data is gone. If the passphrase is forgotten, so is the data. Plan for both before you commit.

# back up the LUKS header, it is irreplaceable
cryptsetup luksHeaderBackup /dev/vdb --header-backup-file /root/luks-header.img

# automate unlock in cloud-init if you must, and understand the risk

Automated unlocking at boot via a keyfile stored on the same disk defeats the purpose; automation usually means storing the key with the system, which protects against disk theft but not against a compromised host. Decide which threat you are actually defending against, and check the broader security guidance in our VPS comparison table on our main site for which providers give you encrypted-at-rest options before you build your own.

When the Overhead Is Worth It

Encrypt the volume when compliance requires it, when the disk may be physically removed or the host decommissioned, or when you handle secrets that must survive a stolen disk. Skip it when the threat model does not include physical access and the CPU cost is better spent elsewhere. For most web workloads with AES-NI, the overhead is small enough that compliance and peace of mind win the argument.

Whatever you choose, measure it on your own instance. The AES-NI performance claim is true on modern hardware and false on old hardware, and only your benchmark tells you which side of that line you fall on. Benchmark, configure, verify, and keep the numbers in your runbook.

Leave a Reply