SSD Nodes Learn 🎉 VPS from $4.99/mo
Guides Matt ConnorBy Matt Connor

RAID 10 explained for VPS storage

What RAID 1, 5, 6 and 10 survive, what a rebuild costs, and why VPS hosts pick RAID 10 for NVMe. Plus how to read /proc/mdstat, and why RAID is not a backup.

What RAID 10 is, and why VPS hosts run it

RAID 10 is the storage layout most VPS hosts run under virtualised NVMe (non-volatile memory express) drives. It mirrors every drive onto a partner, then stripes data across those mirrored pairs. One drive can die without the array stopping, and the repair is a plain copy from the surviving partner rather than a recalculation that reads every other drive in the set.

RAID means redundant array of independent disks. It has one job: keep the machine serving while a disk is dead or being replaced. That job is availability, and availability is not safety.

RAID replicates your writes. rm -rf /srv is a write. Both halves of the mirror drop the directory in the same millisecond, and the array still reports itself clean afterwards.

Keep that sentence. The rest of this page covers what each level survives and what each one costs you on every write. The last sections are the commands to read an array's status on a machine you own, and the failure RAID has never covered.

The levels a hosting buyer actually meets: 1, 5, 6 and 10

A plan page names a number and stops there. The number answers two questions: how many drives can die, and what every write costs.

RAID 1 is a mirror. Two drives hold identical blocks. Every write goes to both. Either drive can serve a read. One drive can fail with no data loss, and half the raw capacity is usable. There is no parity to compute, so the write path is short.

RAID 5 is striping with one parity block per stripe. With n drives you get the capacity of n-1 of them, and the array survives exactly one failure. Parity does not sit on one dedicated drive. It rotates across all of them, so every drive carries both data and parity.

RAID 6 adds a second, independent parity block to each stripe, usually written P and Q. It survives any two drives failing at once. That matters more than it sounds, because the second failure most often arrives during the repair of the first.

RAID 10 is a stripe of mirrors. Drives are mirrored in pairs, and data is spread across the pairs. Usable capacity is half the raw total, the same as RAID 1, with the parallelism of striping on top.

You will also see it written RAID 1+0, which is the honest description: mirror first, then stripe across the mirrors. RAID 0+1 is the other order, stripe first and then mirror the two stripes. It is worse, because one drive failure takes a whole stripe out of service and the repair has to copy the entire other side.

Linux is a special case worth knowing. The kernel's raid10 is a single personality rather than two stacked layers, so it runs on an odd number of drives and it has layouts (near, far, offset) that a nested setup cannot express. That is why the status line on a Linux box says 2 near-copies instead of naming two arrays.

ChartEight 1 TB drives: usable capacity and drives lost before data loss
The data behind this chart
[
  {
    "label": "RAID 1 (four mirrored pairs)",
    "usable_tb": 4,
    "worst_case_drives_lost": 1,
    "best_case_drives_lost": 4
  },
  {
    "label": "RAID 5",
    "usable_tb": 7,
    "worst_case_drives_lost": 1,
    "best_case_drives_lost": 1
  },
  {
    "label": "RAID 6",
    "usable_tb": 6,
    "worst_case_drives_lost": 2,
    "best_case_drives_lost": 2
  },
  {
    "label": "RAID 10",
    "usable_tb": 4,
    "worst_case_drives_lost": 1,
    "best_case_drives_lost": 4
  }
]

Eight 1 TB drives give 7 TB of usable space under RAID 5 and 4 TB under RAID 10. That gap is real money, and it is why parity keeps getting proposed. RAID 6 survives 2 failures in any pattern at all. RAID 10 guarantees only 1, because the dangerous second failure is the one that lands on the partner of the drive that already died. It survives up to 4 when no two failures share a pair, which is luck rather than a design property.

What each level costs on every write

A write to a mirror is two writes, issued at the same time to both members. A write to a parity stripe is more work, because the parity block for that stripe is now wrong and has to be recomputed.

The controller cannot recompute parity from the new block alone. It needs the old data block and the old parity block first. So one small random write to RAID 5 becomes read, read, write, write. RAID 6 has a second syndrome to maintain, so the same write becomes read, read, read, write, write, write.

ChartDevice operations per small random write, and drives read during a rebuild
The data behind this chart
[
  {
    "label": "RAID 1 (2 drives)",
    "write_ops_per_host_write": 2,
    "drives_read_to_rebuild": 1
  },
  {
    "label": "RAID 5 (8 drives)",
    "write_ops_per_host_write": 4,
    "drives_read_to_rebuild": 7
  },
  {
    "label": "RAID 6 (8 drives)",
    "write_ops_per_host_write": 6,
    "drives_read_to_rebuild": 7
  },
  {
    "label": "RAID 10 (8 drives)",
    "write_ops_per_host_write": 2,
    "drives_read_to_rebuild": 1
  }
]

A small random write costs 6 device operations on RAID 6 and 2 on RAID 10. The counts understate the difference in latency. The two mirror writes go out in parallel, so the guest waits for the slower of the two. The parity path contains a read that must finish before the new parity can be computed, so the guest waits for a read and then a write, one after the other. On a busy host that read queues behind everyone else's I/O.

There is an important exception. A write large enough to fill a whole stripe needs no old data, because every block in the stripe is being replaced. Parity is computed from what is already in memory, and the cost falls to one extra write. This is why RAID 5 looks fine in a sequential benchmark and behaves badly under a mixed load of small writes from many tenants. Test the pattern you actually run: benchmarking a VPS disk properly means random I/O at a realistic queue depth, not one large dd.

Why the rebuild is the dangerous part

A parity rebuild has to reconstruct the missing drive from everything else, so it reads 7 surviving drives from the first block to the last. A RAID 10 rebuild reads 1: the dead drive's mirror partner, and nothing else.

Two costs follow from that. The first is time, because the rebuild is bounded by the slowest surviving drive and by the parity maths on top. The second is load. Every drive in a parity set is busy for the whole window, so every guest on that node sees higher latency until it ends. On RAID 10 one pair is busy and the other pairs serve at their normal speed.

There is a correctness risk in the same window. A RAID 5 array with one dead drive has no redundancy left, so an unreadable sector anywhere on a surviving drive is now unrecoverable. A rebuild is the one operation that reads every sector, including the ones nobody has touched in a year. Published datasheet figures put a consumer hard drive near one unrecoverable read error per 10^14 bits read, and an enterprise NVMe drive at one per 10^17 or better. Those are vendor specifications rather than measurements, but the ratio explains why the old warning that a RAID 5 rebuild will fail was written about large spinning disks, and why it is much weaker on NVMe. The load argument holds on any medium.

Find the latent errors before a rebuild does, by scrubbing. Debian and Ubuntu ship a periodic scrub for md arrays, and the mechanism differs between releases, so check which one you have and then trigger a pass by hand.

systemctl list-timers --all | grep -i mdcheck
ls -l /etc/cron.d/mdadm
echo check | sudo tee /sys/block/md0/md/sync_action
cat /sys/block/md0/md/mismatch_cnt

sync_action goes back to idle when the pass finishes, and mismatch_cnt should read 0. A number above zero on a mirror means the two halves disagree and the kernel cannot say which one is right, because neither copy carries a checksum. Some mismatches are harmless, and swap partitions are the usual source: the kernel may write a page that changes underneath it. A rising count on a data array is a drive to replace.

Why VPS providers standardise on RAID 10 for NVMe

A hypervisor node does not run one workload. It runs dozens of unrelated guests, and their I/O arrives interleaved as a stream of small writes with no locality between them. That is the exact pattern where the parity read-modify-write cycle costs the most, and it is the pattern a shared node has all day.

Add the rebuild behaviour and the choice makes itself. A failed drive on a parity node slows every guest on the box for hours. A failed drive on a RAID 10 node slows one pair, and the copy runs sequentially at drive speed. Providers are selling latency that does not spike, so they buy it with capacity: half the raw NVMe goes to the mirror.

Drive sizes push the same way. As drives get larger the rebuild window gets longer, and on parity that window is the one where everything is slow and nothing is protected. It is the same reason ZFS deployments for virtualisation use pools of mirrored vdevs instead of wide raidz: a mirror resilver copies only the blocks actually in use, on one pair.

None of this makes RAID 10 correct everywhere. A backup target is written in long sequential runs and read rarely, so RAID 6 is the better deal there. It survives two failures and gives most of the capacity back. The workload decides, not the number. For a plan you are choosing today, the medium usually matters more than the layout on top of it, and the jump from SATA SSD to NVMe is larger than any RAID difference on either.

How to read /proc/mdstat

Run these on a machine where you own the array: a dedicated server, a box at home, or a VPS with two attached volumes you assembled yourself. Read your own output. The blocks below are examples, written out so you can match the shape of what you get.

cat /proc/mdstat
sudo mdadm --detail /dev/md0
lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS

A healthy four drive RAID 10 prints something close to this.

Personalities : [raid1] [raid10]
md0 : active raid10 nvme3n1p3[3] nvme2n1p3[2] nvme1n1p3[1] nvme0n1p3[0]
      3906764800 blocks super 1.2 512K chunks 2 near-copies [4/4] [UUUU]
      bitmap: 0/30 pages [0KB], 65536KB chunk

unused devices: <none>

Every part of that carries information.

  • Personalities lists the md modules the running kernel has loaded. raid10 appearing there means the code is available, and nothing more.
  • md0 : active raid10 is the array device, its state, and its level.
  • The names after that are the members. The number in square brackets is the device's index in the array metadata, not its position on the line and not always its slot.
  • After a drive replacement the new member usually keeps a higher index than the slot it fills, so nvme4n1p3[4] can be sitting in slot 2. mdadm --detail prints the real slot in its RaidDevice column, so use that when the difference matters.
  • (F) after a member means faulty. (S) means spare: present, idle, waiting for something to fail.
  • 3906764800 blocks super 1.2 is the usable size in 1 KiB blocks, then the metadata format.
  • 512K chunks 2 near-copies is the stripe chunk size and the RAID 10 layout, which here keeps two copies of each block next to each other.
  • [4/4] is the number of members the array expects, then the number currently in sync.
  • [UUUU] is one character per slot, in slot order. U is a slot that is up and in sync. _ is a slot with nothing working in it.
  • bitmap: is the write intent bitmap. It records which regions were being written, so a member that drops out and comes back resyncs those regions instead of the whole drive.

What [4/3] and [UU_U] mean when something is wrong

A degraded array looks like this.

md0 : active raid10 nvme3n1p3[3] nvme2n1p3[2](F) nvme1n1p3[1] nvme0n1p3[0]
      3906764800 blocks super 1.2 512K chunks 2 near-copies [4/3] [UU_U]

Read the two brackets together. [4/3] says one of four slots is not contributing. [UU_U] says which one, because the underscore is the third character and the slots are numbered from zero, so slot 2 is down. The (F) flag names the device only while the failed drive is still attached. Pull it out of the machine and the name vanishes from the line, while the underscore stays.

The array keeps serving through all of this, and on RAID 10 it often serves at close to full speed, which is why nobody notices by feel. Something has to tell you.

grep -i mailaddr /etc/mdadm/mdadm.conf
sudo mdadm --monitor --scan --oneshot --test
systemctl list-units --all | grep -i md

The mdadm package installs a monitor daemon that reads MAILADDR from /etc/mdadm/mdadm.conf, and the unit name has changed between releases, so find it with the last command rather than guessing. The --test run sends one message per array immediately. An empty inbox after it means the mail path is broken, so the message you actually care about would have been lost the same way.

When a replacement is rebuilding, a progress line appears under the array.

md0 : active raid10 nvme4n1p3[4] nvme3n1p3[3] nvme1n1p3[1] nvme0n1p3[0]
      3906764800 blocks super 1.2 512K chunks 2 near-copies [4/3] [UU_U]
      [==>..................]  recovery = 12.4% (242012928/1953382400) finish=63.1min speed=452000K/sec

recovery is a rebuild onto a replacement drive. resync is the first consistency pass over a newly created array. check is the scrub you triggered above. The pair in parentheses is progress in 1 KiB blocks against the per-device total, and finish is the kernel's estimate at the current speed. That speed is capped by /proc/sys/dev/raid/speed_limit_min and speed_limit_max, and the caps exist so a rebuild does not starve production I/O.

A full mdadm --detail during a rebuild
/dev/md0:
           Version : 1.2
     Creation Time : Tue Mar 10 09:14:22 2026
        Raid Level : raid10
        Array Size : 3906764800 (3.64 TiB 4.00 TB)
     Used Dev Size : 1953382400 (1.82 TiB 2.00 TB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Wed Aug  5 11:02:41 2026
             State : clean, degraded, recovering
    Active Devices : 3
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 1

            Layout : near=2
        Chunk Size : 512K

    Rebuild Status : 12% complete

              Name : storage:0
            Events : 4184

    Number   Major   Minor   RaidDevice State
       0     259        3        0      active sync set-A   /dev/nvme0n1p3
       1     259        7        1      active sync set-B   /dev/nvme1n1p3
       4     259       11        2      spare rebuilding    /dev/nvme4n1p3
       3     259       15        3      active sync set-B   /dev/nvme3n1p3

The Number column is the metadata index printed in the brackets in /proc/mdstat. The RaidDevice column is the slot, which is the position in the [UU_U] string. They differ here because device 4 replaced the drive that held slot 2. set-A and set-B name the two halves of each mirror, so a member of set-A and a member of set-B in the same pair holding the same data is the thing you must not lose together.

Replacing a drive on an array you own is four commands, and the last one is the check.

sudo mdadm --manage /dev/md0 --fail /dev/nvme2n1p3
sudo mdadm --manage /dev/md0 --remove /dev/nvme2n1p3
sudo mdadm --manage /dev/md0 --add /dev/nvme4n1p3
cat /proc/mdstat

The recovery line should appear within a second or two. The replacement partition must be at least as large as Used Dev Size from mdadm --detail, and a partition even slightly smaller is rejected with a message of the form not large enough to join array. Partition the new drive to match the old one before you add it.

What you can and cannot see from inside a VPS

Most guests cannot see the host's RAID, and that is by design. The hypervisor hands you one virtual disk. Whether that disk is carved out of a RAID 10 pool of NVMe drives or is sitting on one drive is a property of the host, and it does not show up inside your guest.

systemd-detect-virt
lsblk -d -o NAME,SIZE,ROTA,MODEL
cat /proc/mdstat

systemd-detect-virt prints kvm on a KVM guest, a container type such as lxc on a container, and none on bare metal. On a KVM guest you normally see a single vda or sda in lsblk, and no arrays in /proc/mdstat, because there are none inside the guest.

On a container based VPS the reading is not trustworthy. Containers share the host kernel and parts of /proc are not namespaced, so what you read there can describe the host rather than your slice of it. Treat none of it as a fact about your own storage. Ask the provider what the layout is, and get the answer in writing if it matters to you.

What you can check from inside is the behaviour of the disk you were given. Checking whether your VPS disk is really NVMe covers the commands that report something real, and what an SSD VPS actually includes covers what the label on the plan page is claiming.

Should you run RAID inside your VPS?

Usually not, and the reason is failure domains. If you attach two volumes to one VPS and mirror them with mdadm, both volumes may live on the same physical array, on the same node, behind the same power supply. You would double the cost of every write for redundancy you already had, and you would still lose both copies to the one failure that matters.

It is worth doing when the provider documents that the volumes sit in separate failure domains, or when you are on a dedicated server with drives you can point at. Otherwise the effort goes further on copies that leave the machine.

What RAID does not protect you from

RAID covers one event: a drive that stops working correctly. Everything below is a valid write, so the array applies it to every copy and reports itself healthy.

  • Deletion. rm -rf in the wrong directory, or a deploy script with an unset variable in a path. The array sees a legal write and does it twice.
  • Ransomware. Encryption is writing. A healthy array stores the encrypted version on both halves of the mirror.
  • A broken application. A bug that writes garbage into your database writes the same garbage to the redundant drive.
  • The whole node. A host that fails, or an account suspended by mistake. An array can be perfect and unreachable at the same time.
  • Yourself, a week later. The file you deleted on Monday is gone from every drive on Monday. Only a copy taken before then brings it back.

Snapshots on the same storage are not the fix either. They help against deletion, and they die with the array they live on. The property that makes a backup a backup is that it is somewhere else. Encrypted off-server backups with restic is the other half of this page: the array keeps you serving through a dead drive, and restic gets your data back when the damage was a write the array was happy to make.

FAQ

Does RAID 10 mean I do not need backups?

No. RAID 10 protects against a drive that stops working. It applies every valid write to both halves of a mirror, so a deletion or a ransomware run reaches the redundant drive in the same instant. The array reports itself clean afterwards, because from its point of view nothing failed. You still need copies that live off the machine, and you still need to restore one occasionally to prove they work.

Why do VPS providers choose RAID 10 over RAID 5 or RAID 6?

Two reasons, both about small random writes. A parity write needs the old data and the old parity read back before the new parity can be computed, so a small write costs 4 operations on RAID 5 and 6 on RAID 6, against 2 on a mirror. A parity rebuild then reads every surviving drive from end to end, which slows every guest on the node for hours, while a RAID 10 rebuild copies one drive to one drive and leaves the other pairs alone. Providers pay for that with capacity: half the raw NVMe.

What does [U_] or [UU_U] mean in /proc/mdstat?

Each character is one slot in the array, in slot order, with one character per slot. U means that slot holds a member which is up and in sync. _ means the slot has nothing working in it. [U_] on a two drive mirror means the second slot is down and there is no redundancy left. Read it together with the pair in front of it, where [4/3] says the array expects four members and has three. The slot order matches the RaidDevice column of mdadm --detail, not the order the device names appear on the line.

How many drives can a RAID 10 array lose?

One, in any pattern. Past that it depends where the failures land. Each mirror pair can lose one of its two members, so an eight drive array survives up to four failures if no two share a pair, and it dies at two failures if both hit the same pair. Plan around the guaranteed number, which is one, and treat anything beyond it as luck rather than protection.

Should I mirror two volumes inside my VPS with mdadm?

Usually no. Two volumes attached to one VPS often live on the same physical array on the same host, so mirroring them doubles the cost of every write and protects against nothing the host's own RAID did not already cover. It is worth doing only when the provider documents that the volumes sit in separate failure domains. Otherwise put that effort into backups that leave the machine.