Skip to main content

SFTP vs SCP vs rsync: Which to Use for Speed, Resume, Safety

SFTP vs SCP vs rsync compared on speed, resume and safety, with real Ubuntu commands, the OpenSSH 9.0 scp change and a clear rule for when to use each.

Use rsync for anything large, anything you copy more than once, and any sync or deploy. It resumes, skips unchanged files and only replaces a file once the new copy is complete. Use sftp when you want to browse a server and pick files by hand, or for simple scripted puts and gets. Use scp only for quick one-off copies. Since OpenSSH 9.0 it uses the SFTP protocol anyway. In DockLab we keep an SFTP pane for browsing open next to a terminal for rsync.

Quick answer

  • rsync: the default for directories, big files, repeat syncs and deploys. It sends only what changed, --partial lets it resume, --dry-run previews changes, and it writes to a temp file and then renames it. It needs rsync installed on both ends.
  • sftp: for interactive browsing and simple file operations. It can resume single files (reget, reput, sftp -a) and runs batch files, but it does no delta sync.
  • scp: one command for a one-off copy. It cannot resume, and since OpenSSH 9.0 it uses SFTP by default. Use -O only for old servers that have no SFTP subsystem.
  • All three use the same SSH authentication, encryption and ~/.ssh/config aliases, so the choice is about how each one behaves, not about security of the connection.

The thing most comparisons get wrong about scp

Many articles still say scp is "faster but less secure" than SFTP because it uses its own protocol. That stopped being true by default with OpenSSH 9.0. The release notes say: "This release switches scp(1) from using the legacy scp/rcp protocol to using the SFTP protocol by default." You can still get the old behavior with -O.

The reason was quoting. The legacy protocol asks the remote shell to expand wildcards, so shell characters in filenames had to be quoted twice, or "they could be interpreted as shell commands on the remote side." The scp man page still warns that the legacy protocol "requires execution of the remote user's shell to perform glob(3) pattern matching."

Which version you have depends on your OS:

ssh -V
# Ubuntu 24.04 LTS ships OpenSSH 9.x: scp uses SFTP by default
# Ubuntu 22.04 LTS ships OpenSSH 8.9: scp still uses the legacy protocol by default

The scp client decides which protocol to use, so the version on your laptop is what counts. On a modern client, scp and sftp are mostly two interfaces to the same protocol. What separates the three tools is resume, delta transfer and how each one writes files.

Side-by-side comparison

scpsftprsync (over SSH)
Wire protocolSFTP (OpenSSH 9.0+), legacy with -OSFTPrsync protocol inside SSH
Needs on serversshd with SFTP subsystemsshd with SFTP subsystemsshd plus rsync binary
Resume interrupted copyNoYes, per file (reget, reput, -a)Yes (--partial, --partial-dir)
Skip unchanged filesNo, copies everythingNoYes, by size and mtime (or --checksum)
Delta transfer inside a fileNoNoYes
Preview before copyingNoNo--dry-run
Delete files missing on sourceNoNo--delete
How the destination is writtenWritten in placeWritten in placeTemp file, then rename
Interactive browsingNoYesNo
Bandwidth limit-l (Kbit/s)-l (Kbit/s)--bwlimit

Speed: what actually makes a difference

We are not going to give you benchmark numbers, because your results depend on latency, disk and file mix far more than on which tool you pick. Here is what decides speed in practice:

The first copy of a single large file comes out about the same with all three. Each one is limited by the SSH cipher, your network and the disks. sftp keeps several requests in flight (the -R option in the sftp man page sets how many), which helps on high-latency links.

The second copy is where rsync wins clearly. Its default "quick check" skips files whose size and modification time have not changed, according to the rsync manual. For changed files it sends only the differing blocks. scp and sftp send the whole tree again.

Thousands of small files are slow with all three because each file has its own overhead. rsync does better on later runs because it skips most of them. For a one-time bulk copy, a tar stream over SSH avoids the per-file round trips:

tar -C /srv/app/uploads -cf - . | ssh web1 'tar -C /srv/app/uploads -xf -'

Compression (rsync -z, scp -C) only helps with compressible data on slow links. It does nothing for JPEGs, .gz backups or video, and it costs CPU on fast networks.

Delta transfer is not free. rsync reads the file on both sides to compute checksums. On a fast LAN with large files that changed completely, --whole-file (-W) can be quicker.

Resume: what happens when the connection drops

This is the most practical difference between the three.

scp cannot resume. The scp man page has no resume option. When a 20 GB copy fails at 90 percent, you start again from zero.

sftp can resume single files. sftp -a will "attempt to continue interrupted transfers rather than overwriting existing partial or complete copies of files", and the interactive reget and reput commands do the same for downloads and uploads:

sftp web1
sftp> reget /var/backups/db-2026-10-17.sql.gz
sftp> reput ./release.tar.zst /srv/app/incoming/release.tar.zst

sftp's resume appends to whatever partial file already exists. It does not check that the existing bytes are correct.

rsync keeps partial files when you ask it to. Without --partial, an interrupted file is deleted. We use --partial-dir so half-written files never sit at the real path:

rsync -a --partial-dir=.rsync-partial --info=progress2 \
  ./backups/ web1:/var/backups/app/

Run the same command again after a drop and rsync continues from the partial data. -P is shorthand for --partial --progress if you prefer per-file progress. For files that only grow, such as logs, use --append-verify. The manual calls plain --append "dangerous" unless you are sure every file in the transfer only grows.

Safety: the failure modes we actually see

All three encrypt traffic the same way and check the host key against known_hosts. The risks are in what each tool does to your files.

Half-written files on a live server

scp and sftp write directly to the destination path. If nginx serves /srv/app/public/app.js while you upload it, a visitor can get a truncated file. rsync's default is the opposite: the manual describes it as "creating a new copy of the file and moving it into place when it is complete." Do not add --inplace on live paths unless you need it, because an interrupted --inplace transfer leaves the file inconsistent.

The rsync trailing slash

rsync -a src dest/ creates dest/src. rsync -a src/ dest/ copies the contents of src into dest. Combined with --delete, a missing slash can wipe a directory. The manual itself warns --delete "can be dangerous if used incorrectly."

Keeping rsync patched

In January 2025, rsync 3.4.0 fixed six vulnerabilities. Two of them (CVE-2024-12087 and CVE-2024-12088) affect the client: a malicious server could write files outside the destination directory, according to Help Net Security's summary. Distributions backported the fixes, so apt update && apt upgrade is enough. Be careful about pulling with rsync from servers you do not control. Also avoid exposing an rsyncd daemon on rsync://: it is unencrypted, and most of those bugs were on the server side. rsync over SSH is what you want.

Legacy scp and filenames

If you have to use scp -O against an old box, quote remote paths that contain spaces or shell characters. That remote shell expansion is exactly what the SFTP switch removed.

A safe deploy sync with rsync

This is the procedure we use to push a built site or app directory to a server. It assumes your SSH alias web1 is set up as in our SSH config examples.

  1. Check both ends have rsync

    rsync --version | head -1
    ssh web1 'rsync --version | head -1'
    

    If the server is missing it: sudo apt install rsync.

  2. Preview the change set

    rsync -an --delete --itemize-changes \
      --exclude='.env' --exclude='storage/' \
      ./build/ web1:/srv/app/current/
    

    The excludes protect server-only files that --delete would otherwise remove.

  3. Run it for real, keeping a backup of anything replaced

    rsync -a --delete --partial-dir=.rsync-partial \
      --backup --backup-dir=/srv/app/backup-$(date +%F-%H%M) \
      --exclude='.env' --exclude='storage/' \
      ./build/ web1:/srv/app/current/
    

    Files that get overwritten or deleted are moved into the dated backup directory instead of being lost.

  4. Root-owned destinations

    If the target belongs to root, add --rsync-path="sudo rsync". This needs passwordless sudo for rsync on the server, because there is no terminal to type a password into.

For containerized apps the same pattern works for copying the compose project; see deploying a Docker Compose app to a VPS.

Scripting sftp when rsync is not available

Some hosts, such as locked-down shared hosting and SFTP-only chroot accounts, do not let you run rsync on the server. In that case use sftp batch mode:

cat > upload.batch <<'EOF'
cd /uploads
-mkdir 2026-10
put -p report.pdf 2026-10/
EOF
sftp -b upload.batch web1

In batch mode sftp stops at the first failing command. A leading - (as on mkdir above) tells it to keep going if that command fails, which is handy when the directory may already exist. put -p keeps permissions and times, and put -f asks the server to fsync after the upload.

Where a GUI fits

The command line wins for repeatable jobs. For "what is actually in this directory, and is that the file I think it is", a file browser is faster. That is how we split it in DockLab: the SFTP pane is for browsing, downloading a log or dropping a config file onto the server, and the terminal next to it runs the rsync commands above against the same host. DockLab is not a sync engine, though. For scheduled, repeatable syncs, rsync from cron or CI is the better tool. If you mostly need a dedicated transfer client, our comparison of SFTP clients for Mac is fair about where WinSCP-style tools do more. The compare page covers how DockLab stacks up against Termius, Warp and MobaXterm. For editing in place rather than copying, see editing files on a remote server.

Frequently Asked Questions

Is scp deprecated?

The legacy scp protocol is the part being phased out, not the scp command. Since OpenSSH 9.0 the command uses the SFTP protocol by default, and -O brings back the legacy protocol for servers without SFTP. You can keep using scp for quick copies on a current system.

Is rsync faster than sftp?

For the first copy of a single file they are close, because both are limited by SSH and the network. On repeat transfers rsync is much faster because it skips unchanged files and sends only changed blocks. For one large, already-compressed file that changed completely, the difference is small.

Can I resume an interrupted scp transfer?

No, scp has no resume option. Re-run the copy with rsync -a --partial and rsync will reuse what is already on disk where it can. You can also use sftp with reget or reput for a single file.

Does rsync over SSH need any extra ports or a daemon?

No. rsync -a src/ host:/dest/ starts rsync on the server through your normal SSH connection on port 22, or on whatever port is set in ~/.ssh/config. The only requirement is that the rsync binary is installed on the server. Avoid running the separate rsyncd daemon on public networks.

Which one should I use in CI pipelines?

Use rsync with --delete, explicit excludes and a dry run checked into the pipeline logs. It is idempotent, only touches what changed and never leaves half-written files at the real path. Use sftp batch mode only when the target does not allow running rsync.

Remote files, no round trip

Browse with SFTP, edit in Monaco, save straight to the server.

DockLab puts the file tree, the editor and the terminal side by side, so a config change is one window, not three apps.

About the author

Alexandru Talnaci · Co-founder, Legacies

Alexandru works on DockLab product and operations, with a focus on how technical teams run their servers day to day.