Compare / Storage placement

NVMe vs USB SSD vs Network Share: Where Home Server Data Should Live

Measured 623 MiB/s NVMe, 301 MiB/s USB SSD and 112 MiB/s gigabit paths. Decide where Docker volumes, media libraries and backups belong.

The short answer

Most home servers have three places to put data: the internal NVMe, an external USB SSD, and a network share on another machine. They are not interchangeable, and the differences are not subtle. On our Beelink EQi12 test unit the fastest path is roughly sixteen times faster than the slowest, and the slowest path looks exactly like the fast ones from the outside.

Here is the placement we recommend, before any of the evidence:

WorkloadPut it hereWhyWatch out for
Docker volumes with a database (PostgreSQL, MariaDB, InfluxDB)Internal NVMeLowest latency, no external link to renegotiate after sleep or rebootThe boot disk is small. Our unit has 512 GB shared with Windows
Docker volumes holding config and static assetsInternal NVMe, or a verified fast USB SSDMostly sequential reads at container startNever assign a port you have not measured
Media library for Jellyfin or PlexFast USB SSDSequential reads dominate; easy to expand without opening the caseOne port on our unit ran at USB 2.0-class speed
Backup targetExternal USB SSD, or a network share on a second machineEither keeps the copy off the boot diskA slow port turns a nightly job into a multi-hour job
Download and transcode scratch spaceInternal NVMeFastest, and scratch data is disposableDo not let it fill the boot volume
Cold archive you rarely readNetwork share on another machineSurvives a failure of the main disk1 GbE caps you near 112 MiB/s

The rest of this page explains what each number is, what it does not measure, and how to reproduce it on your own hardware.

What we actually measured

Every throughput figure below comes from the same EAGET 1 TB external SSD and the same cable, moved across four physical USB-A paths on one machine, plus the internal WD PC SN540 512 GB NVMe and a wired gigabit transfer to a second computer. Large transfers were 50 GiB (53,687,091,200 bytes); the slow-port retests used 4 GiB per round.

PathWriteReadIntegrity
Internal NVMe, sustained 50 GiB~623.29 MiB/s~468.2 MiB/sSHA-256 matched
Three faster USB-A paths (50 GiB each)300.64 鈥?301.91 MiB/s431.80 鈥?432.06 MiB/sSHA-256 matched
One slow rear USB-A path, 3 retests (4 GiB)39.35 鈥?39.75 MiB/s40.95 鈥?43.12 MiB/smatched 3/3
Wired gigabit to a second PC, 4 GiB108.76 MiB/s (~912 Mbit/s)112.2 MiB/s (~941 Mbit/s)complete, no missing bytes
Rear USB-A ports on the Beelink EQi12 used for the four-path storage comparison
Original test capture: the same external SSD and cable were moved across each physical rear port. Three paths behaved like modern USB 3.x storage; one did not.

The full port-by-port breakdown, SMART data and the slow-port diagnosis are on the SSD and USB port performance page. The network figures come from the wired Ethernet and Wi-Fi 6 comparison.

Two things matter more than the peak numbers. First, three of four ports were fine 鈥?so a single bad measurement on one port is not a reason to distrust external storage. Second, the bad port was invisible. It is the same physical connector, in the same row, and copies complete successfully at a fraction of the speed. That is why port-by-port verification belongs in any storage plan.

Sequential throughput is not the whole story

Everything in the table above is a large, sequential, single-stream transfer. That models a media file or a backup archive well. It does not model a database.

A PostgreSQL volume does thousands of small random writes per second. Its performance is governed by IOPS and latency, not by how fast a 50 GiB file copies. Our sustained tests deliberately do not report random IOPS, because we did not run a controlled random-workload benchmark on this unit 鈥?and an invented IOPS number would be worse than no number.

So read the placement table as a statement about bandwidth, and apply these two corrections yourself:

If you want the concurrency side of that equation, the two- versus four-stream QSV test shows where the media server actually runs out of headroom.

Worked example: 500 GB of media and 60 GB of Docker volumes

Assume a 500 GB media library and 60 GB of Docker volumes, and ask what a full copy costs on each path. These are arithmetic conversions of the measured rates above (1 MiB = 1,048,576 bytes; 500 GB = 500 脳 10鈦?bytes), with no filesystem or protocol overhead added:

JobInternal NVMeFast USB SSDSlow USB pathGigabit network
Write 500 GB (full backup)12.8 min26.4 min3.4 h1.22 h
Read 500 GB (restore)17.0 min18.4 min3.2 h1.18 h
Write 60 GB (volume snapshot)1.5 min3.2 min24.2 min8.8 min

The middle two columns are the interesting pair. A fast USB path is entirely adequate for a nightly 500 GB job. The same job on a degraded port takes longer than most overnight windows, and it will still report success 鈥?a backup that finishes at 09:40 is not a backup that finished overnight.

This is exactly the question the Backup Retention and Window Planner answers for your own numbers, and the Network Transfer Time tool does the same for a single transfer with protocol overhead included.

Decision tree: pick a home for each workload

Where should this data live?
鈹溾攢鈹€ Is it read or written in many small random operations?
鈹?  鈹溾攢鈹€ Yes (database, index, VM disk image)
鈹?  鈹?  鈹斺攢鈹€ Internal NVMe 鈥?then back it up somewhere else
鈹?  鈹斺攢鈹€ No (large sequential files)
鈹?      鈹溾攢鈹€ Is it the only copy?
鈹?      鈹?  鈹溾攢鈹€ Yes 鈫?This is a backup problem, not a placement problem.
鈹?      鈹?  鈹?        Read the 3-2-1 rule below.
鈹?      鈹?  鈹斺攢鈹€ No 鈫?Continue
鈹?      鈹溾攢鈹€ Does it need to survive failure of the main machine?
鈹?      鈹?  鈹溾攢鈹€ Yes 鈫?Network share on a second machine (accept ~112 MiB/s)
鈹?      鈹?  鈹斺攢鈹€ No 鈫?External USB SSD on a port you have measured
鈹?      鈹斺攢鈹€ Is it disposable (scratch, downloads, transcode temp)?
鈹?          鈹斺攢鈹€ Internal NVMe, with a job that cleans up after itself

The branching that surprises people is the middle one: if a dataset has only one copy, its storage tier is irrelevant. Speed decisions come after the copy decision.

External SSD attached to the Beelink EQi12 during sustained transfer testing
Original test capture of the sustained-transfer setup. Port position, cable and payload size were recorded for every run so results could be repeated.

How to measure your own paths in ten minutes

Do not trust a port because of its colour, its position, or the label printed next to it. Measure it.

On Windows, time a large copy and verify the result:

$src = 'C:\bench\source.bin'
$dst = 'E:\bench\source.bin'

$sw = [System.Diagnostics.Stopwatch]::StartNew()
Copy-Item -Path $src -Destination $dst -Force
$sw.Stop()

$sizeMiB = (Get-Item $dst).Length / 1MB
'Write: {0:N2} MiB/s in {1:N1} s' -f ($sizeMiB / $sw.Elapsed.TotalSeconds), $sw.Elapsed.TotalSeconds

(Get-FileHash $src -Algorithm SHA256).Hash -eq (Get-FileHash $dst -Algorithm SHA256).Hash

On Linux, use direct I/O so the page cache does not flatter the result:

# Write test
dd if=/dev/zero of=/mnt/target/testfile bs=1M count=4096 oflag=direct status=progress

# Read test with caches dropped
sudo sh -c 'echo 3 > /proc/sys/vm/drop_caches'
dd if=/mnt/target/testfile of=/dev/null bs=1M iflag=direct status=progress

# Clean up
rm /mnt/target/testfile

For a network path, measure the link before blaming storage:

iperf3 -c 192.168.5.8 -t 30 -P 4

Paste the result into the iperf3 Result Analyzer to compare both directions and see link efficiency. If the network measures far below ~940 Mbit/s on a gigabit path, fix that before upgrading any disk.

Use at least a few GB, not a few hundred MB. Small transfers stay in cache or in the SSD’s SLC buffer and report speeds you will never see on a real backup.

Three failure modes we hit

A port that looks fine and is not. One rear USB-A path on our unit repeated 39.35 鈥?39.75 MiB/s across three 4 GiB rounds while its neighbours did ten times better. Hashes still matched, so nothing failed loudly. The full isolation procedure is in USB SSD limited to about 40 MB/s.

A boot disk quietly becoming the data disk. The internal NVMe is the fastest place to put things, which makes it the natural dumping ground. On a 512 GB unit, Windows plus a container stack plus a media cache reaches full faster than expected, and a full boot volume takes the whole server down.

Expecting the network to behave like a local bus. At ~112 MiB/s, a gigabit link is roughly a third of a fast USB SSD. That is fine for nightly backups and terrible for running a database over SMB.

Where backups fit

Placement and backup are separate decisions, and only one of them is optional. The 3-2-1 pattern 鈥?three copies, two different media, one copy off-site or at least on a different machine 鈥?is what turns a storage layout into a recovery plan.

On a single mini PC, the practical version is: working data on the internal NVMe, a versioned backup on an external USB SSD on a measured fast port, and a periodic copy to a second machine over the network. The network leg is the slow one, so schedule it weekly rather than nightly.

Use the Backup Retention and Window Planner to check whether your nightly job actually fits inside your window before you trust it, and the ZFS and RAID planning guide if you are building a pool rather than a single disk. To size a media library before you buy drives, start with the Media Storage Calculator.

Frequently asked questions

Can I run Docker entirely from a USB SSD?

You can, and on a measured fast port it works 鈥?but keep the database volumes on the internal NVMe. Random write latency is what a database feels, and our sequential measurements do not capture it. The [Docker Compose starter generator](/tools/docker-compose-generator/) produces a stack with named volumes you can move between paths.

Why is my external SSD slower than the spec sheet?

Usually a link-negotiation or port-identity problem, not a bad drive. Our own unit produced a 39 MiB/s result on one port and 301 MiB/s on the port next to it, with the same drive and cable. Work through the [40 MB/s isolation procedure](/fix/usb-ssd-limited-40mbs/) before replacing hardware.

Should I upgrade to 2.5 GbE for backups?

Only after you have measured a real bottleneck. A 500 GB nightly job takes about 1.22 hours on the 108.76 MiB/s we measured, which fits most overnight windows. If your job does not fit, the [window planner](/tools/backup-retention-planner/) will tell you whether more bandwidth or a longer window is the cheaper fix.

Does the internal NVMe use more power?

In our measurements the whole machine drew about 12 W with four Docker containers idle and about 37 W with all cores loaded. Storage placement did not change the wall-power picture on this unit, and we do not have controlled per-drive power data, so we do not publish one.

Sources and how to reproduce

Every number on this page is either measured on our unit or derived arithmetically from a measured rate, and the arithmetic is shown.

What we did not measure, and therefore do not claim: random IOPS, drive-level power draw, RAID or ZFS pool throughput, and behaviour with a spinning USB hard drive. Where those matter to your build, measure them on your own hardware using the commands above.