Course outline

10.6

S3 Performance

Requests per prefix, multipart upload, Transfer Acceleration and byte-range fetches.

18 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • State S3’s baseline request rates (3,500 PUT/COPY/POST/DELETE and 5,500 GET/HEAD per second per prefix), and calculate how many prefixes a workload needs.
  • Explain what a 503 Slow Down means, why S3 scales a new request rate gradually, and how retries with backoff and well-designed keys handle it.
  • Recognise when SSE-KMS, not S3, is the bottleneck, and name the fixes.
  • Use multipart upload as a performance tool: its three steps, its limits (5 MiB–5 GiB parts, 10,000 parts, 5 GB single PUT), the speed math of parallel parts, and the cleanup of abandoned uploads.
  • Explain how S3 Transfer Acceleration moves data through an edge location, what it requires and costs, and when it does not help.
  • Use byte-range fetches to speed up downloads, retry only a failed piece, resume a download or read just a file’s header.

#Why performance is a design topic for S3

S3 is not a disk you outgrow. You never provision capacity, throughput or IOPS for it, as you did for EBS in lesson 5.2: the service scales by itself to millions of requests per second across all its customers. So why does the exam, and real life, care about S3 performance at all?

Because there are still two kinds of limit, and both are about how you use S3:

  1. Request rate. S3 serves a certain number of requests per second for each prefix in a bucket. One “hot” prefix can be throttled while the bucket as a whole is nowhere near busy.
  2. Bytes per second per transfer. One HTTP request moves data over one TCP connection, and one connection over a long, lossy internet path is slow. Big files and far-away users need several connections, a better path, or both.

Everything in this lesson is a tool for one of those two limits. Each one is simple; the exam tests whether you pick the right one.

ProblemTool
Too many requests per second on the same keysSpread keys over more prefixes
Too many encrypted requests per secondS3 Bucket Keys or a higher KMS quota
Large uploads are slow or keep failingMultipart upload (parallel parts, retry one part)
Uploads from far away are slowS3 Transfer Acceleration (in at the nearest edge)
Large downloads are slow, or you need only part of a fileByte-range fetches

As a reference point, AWS documents that small objects (and the first byte of large ones) usually come back in roughly 100–200 milliseconds. S3 is built for huge throughput and huge scale, not for single-digit-millisecond latency; for that you add a cache or a different storage class (see “Other ways to make S3 faster” below).

#Request rate: counted per prefix

#The baseline numbers

Your application can achieve at least:

  • 3,500 PUT/COPY/POST/DELETE requests per second per prefix (the writes), and
  • 5,500 GET/HEAD requests per second per prefix (the reads).

Three words in that sentence matter:

  • “At least”: this is a floor, not a ceiling. S3 keeps scaling above it when the load stays high; the numbers are what you can count on.
  • “Per prefix”: the rate belongs to a prefix, not to the bucket or the account. A bucket with more prefixes can take more requests in total.
  • “There are no limits to the number of prefixes in a bucket”: so total throughput is, in practice, unlimited if the requests are spread.

#What “prefix” means here

Lesson 10.1 explained that S3 has no real folders: a key such as photos/2026/dhaka.jpg is one flat name, and photos/2026/ is its prefix, the part up to the last /. The slides give four examples:

Object pathPrefix
bucket/folder1/sub1/file/folder1/sub1/
bucket/folder1/sub2/file/folder1/sub2/
bucket/1/file/1/
bucket/2/file/2/

Inside S3, the index of key names is split into partitions by key range, and the documentation’s exact phrase is “per partitioned prefix”. You do not create or see partitions; S3 splits a key range into more partitions when it stays busy. For design and for the exam, the rule is simple: treat each distinct prefix as getting its own 3,500 writes and 5,500 reads per second, and spread busy keys across several prefixes.

#Spreading the load: the arithmetic

The calculation is always the same: divide the request rate by the per-prefix limit and round up. Do it separately for reads and writes, and take the larger answer.

  • The notes’ exam case: 10,000 GET/s on one prefix is over 5,500. Two prefixes give 2 × 5,500 = 11,000, so two is the minimum (each takes about 5,000).
  • The slide’s case: four prefixes read evenly give 4 × 5,500 = 22,000 GET/s.
  • AWS’s own example: 10 prefixes give 10 × 5,500 = 55,000 GET/s.
  • A write-heavy case: payment terminals across the country upload 12,000 log files per second. 12,000 ÷ 3,500 = 3.4, so at least four prefixes.

How do you spread keys? Put a short, evenly distributed component near the start of the key that the reader can compute again:

  • a shard number from the ID: photos/<id mod 4>/<id>.jpg;
  • a short hash: logs/a3f9/2026-10-24-12-00-01.json;
  • a natural spread that already exists: one prefix per customer, per device or per source system.

The reader must be able to rebuild the key from what it knows (the photo ID, the device), otherwise it would have to list prefixes to find the object.

Requests per prefix

A news site keeps its photos in one bucket. Every prefix can take at least 5,500 GET/HEAD and 3,500 PUT/COPY/POST/DELETE requests per second. Watch what happens when one prefix gets more.

Scenario

A normal morning: 3,000 photo reads per second, all under one prefix.

Bucket news-photos-example
Readers
Web app
KMS
photos/
pages
Step 1 of 3
1

Readers open articles; each page pulls a few photos. The web app fetches them from S3, all with keys that start with photos/.

#When you go over: 503 Slow Down

When a prefix receives more than it can handle, S3 answers the excess with HTTP 503 Slow Down. Three things to know:

  • It is throttling, not an outage. The data is safe; S3 is telling the client to send less.
  • Scaling is gradual. When a prefix stays busy, S3 splits its key range into more partitions, but not instantly. While it adjusts to a new, higher rate, some requests get 503s; when it has finished, they stop. A launch that jumps from zero to 20,000 requests per second can see errors for a while even with good key design.
  • The AWS SDKs and CLI retry 503s automatically with exponential backoff (wait a little, then longer, then longer). If you call the REST API yourself, implement the same retry.

So the playbook for high request rates is: design keys across enough prefixes, ramp traffic up gradually for a big launch when you can, retry with backoff, and watch the 5xx metrics. To see where the 503s come from, use CloudWatch request metrics for the bucket (they include a 5xx count; you enable them per bucket, and they are billed as custom metrics), the 503 count in S3 Storage Lens advanced metrics (lesson 10.7), or server access logs (lesson 10.9), which name the exact keys and prefixes being throttled.

#The ceiling outside S3: SSE-KMS

There is one bottleneck that more prefixes cannot fix. When objects are encrypted with SSE-KMS (lesson 10.8), S3 calls AWS KMS on your behalf:

  • every upload makes S3 ask KMS for a new data key (GenerateDataKey);
  • every download makes S3 ask KMS to decrypt the object’s data key (Decrypt).

Those calls count against your account’s KMS request quota for cryptographic operations, a single quota shared by everything in the account and Region. Today the default is 10,000 requests per second, raised to 20,000 in some Regions and 100,000 in the largest ones (US East (N. Virginia), US West (Oregon), Europe (Ireland)). Older material, including the slides of many courses, quotes 5,500, 10,000 and 30,000. All of them are adjustable.

So a workload that reads 12,000 SSE-KMS objects per second, spread perfectly over four prefixes, can still fail in a Region with a 10,000 quota, because KMS throttles. The fixes:

  • S3 Bucket Keys: S3 creates a short-lived bucket-level key from your KMS key and uses it to encrypt data keys, so it calls KMS far less often (AWS says up to 99% fewer requests, which also cuts the KMS bill). This is usually the first answer.
  • Request a quota increase in the Service Quotas console.
  • Use SSE-S3 when you do not need KMS’s key policies and audit trail.

Lesson 10.8 covers SSE-KMS, Bucket Keys and the quotas in depth. For this lesson, remember the exam pattern: “S3 throughput dropped after enabling SSE-KMS” → KMS quota, not S3.

Try the arithmetic yourself, including the KMS ceiling:

Prefix throughput calculator

Set the request rate and the number of prefixes your keys are spread over. Each prefix gets its own 5,500 GET/HEAD and 3,500 PUT/COPY/POST/DELETE per second.

Encryption:
KMS quota (per account, per Region):
S3 Bucket Key:
Try:

Each prefix (1):

reads10,000 / 5,500
writes500 / 3,500

Bucket capacity at this spread

5,500 GET/s

3,500 PUT/s

Prefixes needed

2

max(⌈10,000 ÷ 5,500⌉, ⌈500 ÷ 3,500⌉)

KMS calls per second

0

/ 10,000

≈ 4,500 requests per second over the limit. S3 answers the excess with 503 Slow Down. The SDK retries with backoff, but until the load is spread, readers and writers see errors.

Assumes an even spread and a prefix S3 has already scaled. A brand-new high rate ramps up gradually, with some temporary 503s on the way.

Self-checkQuestion

An image service must handle 18,000 GET requests per second and 5,000 PUT requests per second. Keys are spread evenly over prefixes. What is the minimum number of prefixes?

#Multipart upload: speed and resilience for big uploads

#How it works

Lesson 10.1 introduced multipart upload as the way to upload large objects. Here it is a performance tool. A multipart upload has three steps:

  1. Initiate (CreateMultipartUpload): you name the bucket and key, and set the storage class, encryption and metadata. S3 returns an upload ID.
  2. Upload parts (UploadPart): you send the object as numbered parts, each with the upload ID and a part number from 1 to 10,000. Parts can be sent in parallel and in any order, and a part can be sent again. S3 returns an ETag for every part.
  3. Complete (CompleteMultipartUpload): you send the list of part numbers and ETags. S3 joins the parts in part-number order into one object. Before this call the object does not exist for readers, and after it the separate parts are gone.

At any time you can abort (AbortMultipartUpload), which deletes the parts, or list what is in progress (ListMultipartUploads, ListParts).

#The limits

ItemLimit
Single PUT (one request)Up to 5 GB
When to use multipartRecommended from about 100 MB; required above 5 GB
Part size5 MiB to 5 GiB; the last part can be smaller than 5 MiB
Number of parts1 to 10,000
Maximum object size5 TB in the exam and most courses; 50 TB since December 2025 (48.8 TiB = 10,000 × 5 GiB)

The 10,000-part limit connects file size and part size: part size ≥ file size ÷ 10,000. A 1 TB file needs parts of at least 100 MB; with the CLI’s default 8 MB parts it would need 125,000 parts, so the CLI raises the part size by itself.

#The speed math

Why does multipart make uploads faster, not just possible? Because each part is a separate request on its own connection.

One TCP connection reaches only a certain speed, limited by the round-trip time and packet loss on its path, often far below what your line can carry. A single PUT is one connection, so it moves at one connection’s speed no matter how fast your office link is. With multipart, N connections move about N times as much, until something else becomes the bottleneck: your uplink, the client’s CPU or disk, or the network.

A worked example: a 4 GB file, one connection reaches 10 MB/s, the office has a 1 Gbps uplink (about 125 MB/s).

  • One PUT: 4,000 MB ÷ 10 MB/s = 400 seconds.
  • Multipart with 10 parts in parallel: 10 × 10 = 100 MB/s → 40 seconds.
  • With 20 in parallel: 200 MB/s is more than the link, so the link caps it at 125 MB/s → 32 seconds. More parallelism no longer helps; a faster link would.

Parallelism also changes what a failure costs. A single PUT that fails at 90% has to start again from zero. A multipart upload that loses one 100 MB part resends 100 MB. That is the notes’ exam trick: when uploads fail because of network problems, multipart upload gives you resume capability, because only the failed part is re-uploaded.

Multipart upload, step by step

A television channel in Dhaka uploads a 6 GB recording of last night’s talk show. Compare one big request with many small ones.

Scenario

One request for the whole object, the way a simple script uploads.

Uploader6 GB file
S3tv-archive-example
Lifecycle rulecleanup
PUT 6 GB
Step 1 of 3
1

A single PUT can carry at most 5 GB. S3 rejects this one outright with an error: above 5 GB, multipart upload is mandatory.

#Failures, retries and forgotten parts

  • Retry a part, not the file. Send the failed part again with the same upload ID and part number; the new copy replaces the old one. The SDKs and CLI do this automatically.
  • Parts are invisible but billed. Parts of an upload that is never completed or aborted stay in the bucket, do not show up as objects in a normal listing, and are charged as storage. A crashed script can leave gigabytes behind for years.
  • Clean up with a lifecycle rule. Add a rule to every bucket that receives large uploads: “delete incomplete multipart uploads” (AbortIncompleteMultipartUpload) a number of days after initiation, for example 7. Lesson 10.5 covers lifecycle rules; this is the exam answer to “save cost on failed or incomplete multipart uploads”.

#Let the tools do it

You rarely call the multipart APIs by hand. The high-level aws s3 cp and aws s3 sync commands, and the Transfer Manager in the AWS SDKs, split, parallelise, retry and complete for you. The CLI’s defaults:

  • multipart_threshold 8 MB: files above it are uploaded in parts;
  • multipart_chunksize 8 MB: the part size (raised automatically for very large files);
  • max_concurrent_requests 10: parts in flight at once.

Raise the concurrency and the part size on a fast link. The newer AWS Common Runtime (CRT) transfer client, written in C, goes further: it measures your network and picks the parallelism itself. In the AWS CLI v2 the preferred_transfer_client setting decides; crt forces it, and the default auto uses it for most transfers on many systems. AWS recommends the CRT-based clients for the new 50 TB objects.

Downloads work the same way in reverse: the same tools fetch large objects as parallel byte ranges (see the section on byte-range fetches below).

This is the lesson’s second calculator. Change the part size and parallelism, and watch the limits and the speed:

Multipart upload calculator

Choose a file, a part size and how many parts go at once. See whether the upload is allowed, how many parts it makes, and how long one PUT takes compared with parallel parts.

File size

Part size

Your uplink

Parts

58

last part: 23 MB

If one transfer fails

One PUT: resend up to the whole file (6.0 GB)

Multipart, parallel: resend one part (105 MB)

One PUT✕

not allowed above 5 GB

Multipart, parallel1 min

100 MB/s · limited by connections

Valid multipart upload.

Multipart upload is also one of the thirteen “paths to S3” collected in lesson 10.12, where it sits next to pre-signed URLs (including pre-signed parts, so a browser can upload a big file straight to S3) and Batch Operations.

#S3 Transfer Acceleration

#The path through the edge

Multipart fixes “one connection is slow”. It does not fix “the whole path is long and lossy”. When a client is on another continent from the bucket, every connection crosses many networks that nobody optimises for you, and packet loss on a long round trip slows TCP down badly.

S3 Transfer Acceleration changes the path:

  1. The client sends to a special endpoint, bucketname.s3-accelerate.amazonaws.com.
  2. DNS resolves it to the nearest CloudFront edge location, usually a short hop from the client.
  3. From the edge, data travels to the bucket’s Region over the AWS global network, an optimised, well-provisioned path, instead of the public internet.

The slide’s picture is exactly this: a file in the United States goes over the public internet only as far as an edge location in the United States, and from there over the private AWS network to a bucket in Australia. It works for uploads and downloads, and it is compatible with multipart upload: the parts each take the fast path, so the two improvements multiply.

#Turning it on

  • Enable it per bucket (console, PutBucketAccelerateConfiguration, or the CLI). Only the bucket owner, or someone with s3:PutAccelerateConfiguration, can.
  • The bucket name must be DNS-compliant and must not contain dots (.). A bucket called tv.footage.example cannot use it; create a new bucket without dots.
  • Clients must use the accelerate endpoint (or bucketname.s3-accelerate.dualstack.amazonaws.com for IPv6) with virtual-hosted-style requests. The normal endpoint keeps working at normal speed, so you can choose per request. SDKs and the CLI have a flag (use_accelerate_endpoint) for it.
  • It can take up to 20 minutes after enabling before transfers actually get faster, although the endpoint works at once.
  • Everything except ListBuckets, CreateBucket and DeleteBucket works through the endpoint, and cross-Region copies with CopyObject are not supported: it is for moving data between clients and the bucket.
  • It is supported for general purpose buckets in a list of fifteen Regions (October 2026), including US East and West, several European Regions, Tokyo, Seoul, Mumbai, Singapore, Sydney, Canada (Central) and São Paulo. Check the list before you design around it.

#Cost, and when it does not help

Transfer Acceleration has its own per-GB price on top of normal data transfer prices: $0.04 per GB when the work is done by edge locations in the United States, Europe or Japan, and $0.08 per GB at all other edge locations (data in from the internet). For a 20 GB delivery from Dhaka through an Asian edge, that is about $1.60 extra.

It helps most when the client is far from the Region, has a fast connection, sends large objects or a lot of data, regularly, across continents. It helps little or not at all when:

  • the client is near the Region already (an office in Sydney uploading to a Sydney bucket);
  • objects are small, so connection setup dominates, not transfer;
  • the bottleneck is the client’s own slow last mile (a weak mobile connection stays weak);
  • the client is inside AWS in the same Region (an EC2 instance next to the bucket).

AWS will not charge the acceleration fee for a transfer when it determines that acceleration was unlikely to be faster. Before you enable it, run the Transfer Acceleration Speed Comparison tool in a browser at your users’ locations; it uploads with and without acceleration to several Regions and shows the difference.

Transfer Acceleration: in at the nearest edge

A film studio in Dhaka delivers 20 GB of footage to a client’s bucket in Sydney. Compare the public internet with the AWS edge network.

Scenario

The normal endpoint: tv-footage-example.s3.ap-southeast-2.amazonaws.com.

Studio, Dhaka
ISP
Transit
Transit
Edge location
Bucket, Sydney
Office, Sydney
part 1
Step 1 of 3
1

The upload leaves Dhaka through the local ISP. From here it crosses several networks that AWS does not control, each with its own congestion.

#Transfer Acceleration or something else?

NeedUse
Users worldwide upload to one bucket, fastS3 Transfer Acceleration (plus multipart)
Users worldwide download the same popular filesCloudFront caching in front of the bucket (chapter 11)
Many terabytes to move once, slow or no networkSnowball (lesson 12.1)
Ongoing sync from on-premises storageAWS DataSync and Storage Gateway (chapter 12)
Private access from a VPCGateway or interface endpoints (lesson 10.10)

Lesson 10.11 places Transfer Acceleration among the bulk “paths to S3” and compares it with these alternatives in detail.

#Byte-range fetches

#Parallel downloads

A normal GET returns the whole object. With the HTTP Range header, a GET returns only the bytes you ask for: Range: bytes=0-8388607 returns the first 8 MiB, and S3 answers 206 Partial Content. That is a byte-range fetch, and it is the download-side twin of multipart upload:

  • Speed: split a large object into ranges and request them in parallel on several connections. Four ranges of a 1 GB video finish in roughly a quarter of the time, as long as the client’s network can carry them. AWS suggests ranges such as 8 MB or 16 MB; if the object was uploaded with multipart, align the ranges with the original part boundaries, or ask for a part directly with partNumber.
  • Resilience: if one range fails, retry only that range. AWS advises retrying slow requests on a new connection with a fresh DNS lookup, because the retry is then likely to take a different, faster path.
  • Resume: a download cut off at 600 MB continues with an open-ended range, Range: bytes=600000000-, instead of starting again. Send If-Match with the original ETag so the resume fails cleanly if the object changed meanwhile.

Each range is a normal GET request, so it counts toward the prefix’s 5,500 GET/s. Fetching a 1 GB object as 128 ranges of 8 MB is 128 requests.

#Fetching only what you need

The second use is to download part of a file and nothing else. Many formats put what you need first (or last): a video’s header with its format and duration, an image’s dimensions, a Parquet file’s footer with its schema. A byte-range fetch of the first (or last) few bytes reads it without downloading the whole object, and you pay data transfer only for those bytes.

Both of the notes’ exam triggers point here: “speed up the download of large video files” and “download only the first 50 bytes to read the header of a file” → byte-range fetches. A HEAD request is a tempting wrong answer: it returns the object’s metadata (size, ETag, content type, user metadata), never any bytes of its content.

Byte-range fetches

A video app reads a 1 GB file from S3. The HTTP Range header lets it ask for just a slice of the object.

Scenario

Four 250 MB ranges downloaded at the same time.

Video app
S3movies-example
Range: bytes=0-249999999
Step 1 of 4
1

Instead of one GET for 1 GB, the app opens four connections. The first asks for bytes 0 to 249,999,999.

#Other ways to make S3 faster

The notes and slides cover the four tools above. A few more come up in real designs and in exam answers:

  • Keep compute in the same Region as the bucket. EC2 instances in the bucket’s Region get lower latency and no inter-Region data transfer charge. A single EC2 instance can reach up to 100 Gbps to S3 with enough parallel requests; data-lake jobs then add instances for terabits per second.
  • Cache hot objects. If the same objects are read again and again, put CloudFront in front of the bucket (chapter 11) for users on the internet, or ElastiCache (lesson 7.5) for an application that needs sub-millisecond reads. Fewer requests reach S3, which also lowers the request bill.
  • Need single-digit-millisecond latency? S3 Express One Zone (lesson 10.5) stores data in one Availability Zone in a directory bucket, with single-digit-millisecond access and hundreds of thousands of requests per second. Place compute in the same AZ.
  • Retry slow requests, not just failed ones. For latency-sensitive apps, AWS suggests retrying a small request that has not finished after about 2 seconds, then backing off, and for large requests, retrying the slowest few percent. A retry usually takes a different path and succeeds quickly.
  • Reuse connections. Keep a pool of HTTP connections instead of opening a new TCP and TLS session for every request, and do not pin one S3 IP address: S3’s DNS returns many addresses for a reason.
  • Use a current SDK. It already retries 503s with backoff and includes the Transfer Manager.

#Exam patterns at a glance

#S3 performance in system design

  • Design keys for the rate you expect. Put the spread near the front of the key (a shard, a hash, a tenant or device ID) and make sure every reader can compute the key. Do the arithmetic for the peak: election night, a sale, a month-end batch, not an average day.
  • Do not build the time into the front of hot keys. Keys like 2026-10-24-12-00-01.json put all of today’s writes under one ever-moving range. logs/<device-shard>/2026/10/24/… spreads the writes and still lets you list by day within a shard.
  • Count KMS in your capacity plan. Every SSE-KMS request is also a KMS request. Turn on S3 Bucket Keys for busy buckets from the start.
  • Big objects: parallelise both directions. Multipart up, byte ranges down, with the SDK’s Transfer Manager or the CRT client doing the work. Size parts so that 10,000 parts cover your largest object.
  • Far-away writers: Transfer Acceleration; far-away readers: CloudFront. Measure with the Speed Comparison tool before paying for acceleration.
  • Expect and observe 503s. Retries with backoff are normal behaviour; a steady stream of 503s on one prefix is a key-design problem. Watch the 5xx metric, and let a big launch ramp up.
  • Clean up after failures. A lifecycle rule for incomplete multipart uploads belongs in every bucket template.

#Try it yourself

Watch the request rate and the 503s for a bucket (CloudWatch request metrics are optional and billed):

# Enable request metrics for the whole bucket (one filter called EntireBucket)
aws s3api put-bucket-metrics-configuration --bucket news-photos-example \
  --id EntireBucket --metrics-configuration Id=EntireBucket

# After traffic flows: 5xx errors per minute for the last hour
aws cloudwatch get-metric-statistics --namespace AWS/S3 --metric-name 5xxErrors \
  --dimensions Name=BucketName,Value=news-photos-example Name=FilterId,Value=EntireBucket \
  --start-time 2026-10-24T18:00:00Z --end-time 2026-10-24T19:00:00Z \
  --period 60 --statistics Sum

A multipart upload by hand, step by step:

# 1. Initiate: S3 returns an UploadId
aws s3api create-multipart-upload --bucket tv-archive-example --key shows/2026-10-24.mp4

# 2. Split the file into 100 MB parts and upload them (these can run in parallel)
split -b 100M talkshow.mp4 part-
aws s3api upload-part --bucket tv-archive-example --key shows/2026-10-24.mp4 \
  --part-number 1 --body part-aa --upload-id "$UPLOAD_ID"     # returns an ETag
aws s3api upload-part --bucket tv-archive-example --key shows/2026-10-24.mp4 \
  --part-number 2 --body part-ab --upload-id "$UPLOAD_ID"
# ... one call per part

# 3. See what S3 has, then complete with the list of part numbers and ETags
aws s3api list-parts --bucket tv-archive-example --key shows/2026-10-24.mp4 --upload-id "$UPLOAD_ID"
aws s3api complete-multipart-upload --bucket tv-archive-example --key shows/2026-10-24.mp4 \
  --upload-id "$UPLOAD_ID" --multipart-upload file://parts.json
# parts.json: {"Parts":[{"PartNumber":1,"ETag":"\"etag-1\""},{"PartNumber":2,"ETag":"\"etag-2\""}]}

# Find and remove forgotten uploads
aws s3api list-multipart-uploads --bucket tv-archive-example
aws s3api abort-multipart-upload --bucket tv-archive-example --key shows/2026-10-24.mp4 \
  --upload-id "$UPLOAD_ID"

Let the CLI do it, tuned for a fast link, and add the cleanup rule:

aws configure set default.s3.multipart_chunksize 64MB
aws configure set default.s3.max_concurrent_requests 20
aws configure set default.s3.preferred_transfer_client crt   # the C-based CRT client
aws s3 cp talkshow.mp4 s3://tv-archive-example/shows/2026-10-24.mp4

# Lifecycle: abort multipart uploads that are not finished within 7 days
aws s3api put-bucket-lifecycle-configuration --bucket tv-archive-example \
  --lifecycle-configuration '{"Rules":[{"ID":"abort-incomplete-mpu","Status":"Enabled",
    "Filter":{},"AbortIncompleteMultipartUpload":{"DaysAfterInitiation":7}}]}'

Transfer Acceleration:

# Enable it (bucket name without dots), then check the status
aws s3api put-bucket-accelerate-configuration --bucket tv-footage-example \
  --accelerate-configuration Status=Enabled
aws s3api get-bucket-accelerate-configuration --bucket tv-footage-example

# Use the accelerate endpoint for one command...
aws s3 cp footage.mov s3://tv-footage-example/2026/ --endpoint-url https://s3-accelerate.amazonaws.com
# ...or for every s3 command
aws configure set default.s3.use_accelerate_endpoint true

Byte-range fetches:

# Only the first 50 bytes (the header)
aws s3api get-object --bucket movies-example --key films/river.mp4 --range bytes=0-49 header.bin

# One range of a large object, and one original multipart part
aws s3api get-object --bucket movies-example --key films/river.mp4 \
  --range bytes=8388608-16777215 piece-2.bin
aws s3api get-object --bucket movies-example --key films/river.mp4 --part-number 3 part-3.bin

And the Bucket Key that keeps SSE-KMS from hitting the KMS quota:

aws s3api put-bucket-encryption --bucket news-photos-example --server-side-encryption-configuration \
  '{"Rules":[{"ApplyServerSideEncryptionByDefault":{"SSEAlgorithm":"aws:kms",
    "KMSMasterKeyID":"arn:aws:kms:ap-southeast-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"},
    "BucketKeyEnabled":true}]}'

#Summary

Key takeaways

  • S3 scales automatically; first-byte latency is about 100–200 ms. Performance design is about request rate per prefix and bytes per second per transfer.
  • At least 3,500 PUT/COPY/POST/DELETE and 5,500 GET/HEAD per second per prefix; no limit on prefixes. Prefixes needed = rate ÷ limit, rounded up, for reads and writes separately. 4 prefixes → 22,000 GET/s; 10 → 55,000.
  • Over the limit → 503 Slow Down: throttling, retried with exponential backoff by the SDKs. S3 scales a new rate gradually. Random key prefixes are no longer needed just for speed (since 2018).
  • SSE-KMS adds a KMS call to every upload (GenerateDataKey) and download (Decrypt), limited by a shared per-Region KMS quota (10,000, 20,000 or 100,000 per second by default today). Fix: S3 Bucket Keys, a quota increase, or SSE-S3.
  • Multipart upload: initiate → upload parts in parallel (any order) → complete. Recommended from 100 MB, required above 5 GB. Parts 5 MiB–5 GiB (last can be smaller), 10,000 max. Max object 5 TB for the exam, 50 TB since December 2025.
  • Multipart is faster because N connections ≈ N × one connection, up to your link; and a failure costs one part, not the file. Abort leftovers with a lifecycle rule.
  • Transfer Acceleration: bucket.s3-accelerate.amazonaws.com → nearest edge location → AWS network → bucket. Works with multipart, uploads and downloads. Needs a DNS-compliant name without dots, extra $0.04–$0.08/GB, no charge when not faster. No help near the Region or for small files.
  • Byte-range fetches (Range header, 206): parallel downloads, retry or resume one range, read only a header. HEAD returns metadata, not content.