Logo

aws s3 cp vs sync: What’s the Difference?

3 min read
S3AWS

Table of Contents

cp vs sync — What’s the deal?

These two AWS CLI commands do very similar things at first glance — but they're built for different use cases.

aws s3 cp

cp (copy) is a direct, one-off file transfer.

https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html

Example

1aws s3 cp ./build s3://my-bucket/path/ --recursive

This just says: “Take everything in ./build and upload it to S3.” No fancy logic.

aws s3 sync

sync is like rsync for S3. It compares source and destination and only updates what's different.

https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html

Example

1aws s3 sync ./build s3://my-bucket/path/

It’ll skip identical files, saving time (and cost). Super useful in CI/CD!

So, when to use what?

Use CaseUse cpUse sync
First-time upload
Re-uploading everything
Incremental deployment (CDN)
Clean up removed files✅ (with --delete)

🏁 Frequently Used Flags (Cheat Sheet)

FlagDescription
--recursiveRecursively copy/sync directories
--acl public-readMakes uploaded files public (⚠️ only use if you really want this!)
--deleteDelete files in destination that don’t exist in source (only in sync)
--exclude "*" --include "*.jpg"Include only certain file types (useful with sync)
--dryrunSimulate the command without actually uploading/changing anything
--exact-timestampsForce exact timestamp matching during sync (not just file size)
--storage-classSet storage class (e.g., STANDARD_IA, GLACIER)

Why --exact-timestamps Didn’t Work for Me

Tried using --exact-timestamps with aws s3 sync to avoid uploading unchanged files… but it didn’t help. Everything still got re-uploaded every single time.

Turns out, it wasn’t sync’s fault — it was the way Docker builds work.

Since I was copying files into the Docker image using COPY . ., every file got a fresh modified timestamp during the build, even if the content hadn’t changed. So from sync’s perspective, every file looked new. In that case, sync behaves basically the same as cp.

So yeah — --exact-timestamps is great if the timestamps are reliable. But with Docker builds, they’re not.

Where I Actually Use Each

Just to keep things clear:

Summary

Related Articles