S3 actually guarantees strong read-after-write consistency for all operations, not just a subset.
Let’s see it in action. Imagine you have an S3 bucket named my-awesome-bucket. You want to upload a file, then immediately read it back to verify.
# 1. Upload a file
echo "This is the content of my file." > my_file.txt
aws s3 cp my_file.txt s3://my-awesome-bucket/
# 2. Immediately list the object to confirm it exists
aws s3api list-objects-v2 --bucket my-awesome-bucket --prefix my_file.txt
# 3. Immediately get the object to read its content
aws s3 cp s3://my-awesome-bucket/my_file.txt -
If you run these commands in quick succession, you will always see my_file.txt in the list-objects-v2 output, and you will always read "This is the content of my file." back. There’s no waiting, no eventual consistency here.
This strong consistency model means that once an object write (PUT, POST, DELETE) or overwrite is successfully completed, any subsequent read request (GET, HEAD, LIST) for that object or its metadata will return the latest version of that object. This applies to all regions, all storage classes, and all operations.
The problem S3 solves with this model is the fundamental difficulty of distributed systems: how do you ensure that everyone sees the most up-to-date data immediately after it’s changed, especially when data is being replicated across multiple servers and potentially multiple data centers? Most distributed object stores opt for eventual consistency to achieve higher availability and performance, meaning there’s a window where reads might return stale data. S3 chose a different path.
Internally, S3 achieves this by using a sophisticated distributed consensus protocol. When you perform a write operation, S3 doesn’t just write the data to one place and replicate it in the background. Instead, the write operation is coordinated across multiple replicas and metadata stores. The write is only acknowledged as successful after it has been durably committed in a way that guarantees subsequent reads will see it. This coordination involves mechanisms similar to Paxos or Raft, ensuring that all relevant parts of the system agree on the new state before the client receives a success response. When you then perform a read, S3 directs your request to a replica that has already been updated and acknowledged the write.
The exact levers you control are primarily related to object operations themselves. You don’t directly configure S3’s consistency model; it’s a fundamental property of the service. Your interaction is through standard S3 API calls (PUT, GET, DELETE, LIST, etc.). The "strong consistency" is what you get by default for all these operations. The implications are that you can build applications that rely on immediate data visibility without needing to implement complex logic to handle potential read inconsistencies, which is a significant simplification for developers.
What most people don’t realize is that while S3 provides strong read-after-write consistency for new objects and overwritten objects, it does not provide strong consistency for deleted objects. If you delete an object and immediately try to read it, you might still be able to read the old version for a brief period. This is because the delete operation is an overwrite of the object’s metadata to mark it as deleted, and this metadata update, like any other S3 operation, is replicated. However, the actual data might still be accessible from a replica that hasn’t yet processed the delete metadata update.
The next concept you’ll likely grapple with is managing S3 costs, particularly egress charges and the cost implications of different storage classes.