What S3 latency testing actually measures
S3 latency testing measures how long an application takes to complete object-storage operations under realistic network, region, authentication, and concurrency conditions. The useful result is not one nearly perfect number from a speed-test website; it is a distribution of request timings for the exact operation that matters to your platform, such as a 1 KiB metadata lookup, a 10 MiB upload, a multipart part transfer, or the first byte of a ranged download. AWS documentation includes guidance on measuring network latency to an AWS Region before deployment, but that measurement establishes the network floor rather than the complete S3 service time. For a B2B data plane, test both control-path operations and bulk-data paths because authentication, request parsing, service processing, and transfer time contribute differently to each request. Results should be recorded from the production client location, not from a convenient laptop close to an AWS edge point. The practical objective is to identify whether latency, throughput, error rates, or egress cost will determine the storage design.
Also worth reading: How Do You Measure and Reduce Cross-Cloud Data Plane Latency for Object Storage in 2026? · S3 cross region replication pricing 2026: what does CRR actually cost on AWS and how should platform teams budget it? · How Should Platform Teams Design S3-Compatible Object Storage in 2026?
Build a representative test before collecting numbers
A defensible test begins with a workload specification that records Region, source network, protocol, payload size, object count, concurrency, authentication mode, and expected production duration. Select at least two AWS Regions and include the incumbent location as a baseline, but choose Regions based on users, compute, compliance boundaries, and disaster-recovery requirements rather than advertised ping alone. Use a small set of common sizes: 1 KiB for metadata-like reads, 1 MiB for ordinary application objects, 64 MiB or 100 MiB for larger files, and a multipart size for bulk ingestion. Keep TLS enabled and use SigV4 or the AWS SDK because testing an anonymous public bucket measures a different system. Run warm-up requests first, then collect a steady sample long enough to expose variability rather than a brief favorable interval.
| Test dimension | Small object request | Bulk transfer | Multipart workload |
|---|---|---|---|
| Representative size | 1 KiB-1 MiB | 10 MiB-1 GiB | 8-100 MiB per part |
| Primary metric | p50 and p95 latency | Sustained throughput | Completion time and retry rate |
| Initial threshold | p95 under 100 ms | At least 90% of link target | 99% completion without throttling |
| Useful sample | 10,000 requests | At least 10 minutes | At least 1,000 parts or 1 hour |
| Common confound | Warm caches | TCP ramp-up | Concurrency and part scheduling |
Execute the test without measuring your own application accidentally
Run the benchmark from the same subnet, region, operating system, and runtime that will issue production S3 requests. An EC2 client in the destination AWS Region can expose storage processing time, but it can conceal consumer internet latency and may be unusually favorable for cross-Availability-Zone traffic. A remote client provides a more realistic hybrid-cloud result, while an on-premises host captures corporate proxy, firewall, routing, and WAN behavior. For each location, pin the SDK to a specific S3 Regional endpoint and record the resolved endpoint IP addresses; disabling retries can reveal raw behavior, but production testing must repeat with SDK defaults because retries are part of actual completion time. Avoid placing the load generator and storage client behind the same constrained egress connection if the goal is to measure S3 independently.
Use concurrent workers rather than serial requests when the application will operate concurrently, but increase concurrency in controlled stages such as 1, 8, 32, 128, and 256 workers. Each stage should run long enough to distinguish connection setup from steady-state performance, preferably 5-15 minutes, and should record completed operations, failed operations, transferred bytes, and 5xx responses. A sequential transfer is appropriate only for a genuinely serial pipeline. For uploads, distinguish PutObject from multipart upload and include the create, upload, and complete phases. For downloads, distinguish a whole-object GET from a ranged read because a range request can benefit from different cache and network behavior. If a CDN fronts the content, test S3 origin performance and CDN-delivered performance as separate systems.
Interpret latency, throughput, and failures together
Median latency answers only whether the typical request was fast; percentiles reveal whether users experienced tail delays. Report p50, p95, p99, and maximum latency for each operation, but do not publish a p99 calculated from a sample too small to contain at least 100 observations beyond the target percentile. A p50 of 40 ms with a p95 of 180 ms and a 0.2% retry rate presents a different production problem from a steady p50 of 60 ms with no failures. Throughput should be expressed as MiB per second per worker and aggregate MiB per second, then compared with the capacity available on the source link. Latency and throughput can trade off: increasing concurrency may raise aggregate throughput while worsening queueing latency, and reducing concurrency may improve individual response time while limiting the application’s ingestion capacity.
Use service and application metrics to locate the delay. DNS and TLS setup can dominate small requests, connection limits can stall concurrency, and SDK retries can convert a short transient error into a multi-second completion time. HTTP 503 responses require investigation rather than automatic acceptance as “normal cloud behavior”; common causes include throttling, connection reuse defects, or overloaded dependencies, although the response body and AWS service metrics should determine the actual cause. A client-side timeout is not proof that S3 exceeded an SLA because the timeout may occur in DNS, a proxy, the network, or the client itself. Repeat suspect tests from a second network and against a known-good AWS compute client. If only one path is slow, the storage Region may not be the main issue.
Compare Regions, clouds, and hybrid designs fairly
The best Region is rarely the one with the lowest empty-network ping. Compare end-to-end S3 request duration, bulk throughput, availability, data-transfer cost, data residency, service compatibility, and operational complexity together. For example, a Region with 85 ms p95 reads may be preferable to one with 55 ms if it avoids a cross-cloud processing layer or halves transfer charges for a high-volume workload. Cross-cloud object gateways and data-plane SaaS can add policy checks, encryption, indexing, replication, or protocol translation that must be included in the test; do not attribute the complete gateway latency to the underlying S3 request. Run the same payload and client configuration through each option, and label origin-only, gateway-inclusive, and end-user measurements clearly.
| Decision criterion | AWS S3 Region test | R2 or another object store | Cross-cloud data-plane gateway |
|---|---|---|---|
| Small-request result | Direct S3 p50, p95, p99 | Repeat identical object operations | Include gateway and policy overhead |
| Bulk transfer | Direct connection throughput | Provider-specific protocol behavior | Include fan-out and transformation |
| Data movement | Standard S3 and AWS transfer paths | Cloudflare-specific transfer conditions | Provider-to-provider replication and egress |
| Main strength | Broad AWS integration and Region choice | Potentially favorable public egress economics | One interface across multiple backends |
| Main risk | Region distance and AWS service charges | Feature, residency, and support differences | Added failure modes and cost layers |
Avoid common benchmarking errors
One common error is using ICMP ping as the result. ICMP may help identify a rough path characteristic, but it does not execute TLS, authenticate an S3 request, process an HTTP request, or transfer an object. Another error is testing one cached object and generalizing the result to millions of objects. Repetition can reveal SDK connection reuse, while randomized object names better approximate production access patterns. Do not compare a first multipart upload against a resumed transfer, or test acceleration only after TCP has already converged. Compression, checksums, encryption, and application serialization should remain consistent across options if they exist in production.
Another error is running too little traffic for too little time. A ten-request test can be corrupted by DNS, TLS, routing changes, or a transient service event; a stress test can instead overwhelm the client and say little about normal operation. Separate baseline, production-load, peak-load, and fault-recovery phases, and preserve raw measurements for later comparison. Avoid changing Region, SDK version, operating system, packet size, or source network in the middle of a run without labeling the change. Finally, do not delete and recreate every test object at full scale, because cleanup can create a second storage workload and inadvertently test the wrong path. Use lifecycle expiration or a controlled cleanup period, while ensuring the benchmark does not violate lifecycle or retention policies.
Decide whether to migrate, adjust, or keep the current Region
Act on the data when several runs show that a storage decision conflicts with a documented requirement. If direct S3 p95 exceeds the application target by more than 20% in two or more locations, investigate the network, Region distance, gateway, or concurrency before changing vendors. If throughput is below 80% of the available link target while latency remains low, inspect stream sizing, SDK buffers, multipart concurrency, CPU utilization, and packet loss. For high-volume migration, compare the cost of leaving data in place, moving it to a nearby Region, introducing a read-through gateway, or changing the application’s compute location. A slower storage service can still be the rational choice when it removes repeated cross-cloud processing or reduces network charges enough to offset the latency difference.
Set a review date rather than treating one benchmark as permanent infrastructure truth. Internet routing, provider capacity, software defaults, and prices can change after the test, so repeat the benchmark after a major SDK upgrade, network change, Region launch, or contract negotiation. Retain Region, endpoint, client version, object sizes, concurrency, and percentile results with the report; without those details, a future reader cannot reproduce the conclusion. For a platform team managing multiple object stores, automate the test as a periodic canary and alert on p95 regression, throughput loss, and error-rate changes. The best outcome is not a universally fast storage layer, but a documented data plane whose latency and cost fit the workloads it actually serves.