skip to content

Amazon S3 has provided strong read-after-write consistency since December 2020. What exactly does that guarantee cover, and which S3 behaviours are still not covered by it?

level: middleimportance: must knowfreq 55%

answer

  1. the 2020 change nobody updated their notes for
  2. overwrites and deletes too, not just new keys
  3. LIST is included
  4. bucket configuration is a different animal
  5. consistency is not a lock

basics

~20 s

Since December 2020, any successful S3 PUT or DELETE is immediately visible to every subsequent GET, HEAD and LIST, in all regions, at no extra cost. Bucket configuration changes and replication to another bucket remain eventually consistent.

solid answer

~40 s

After a `PutObject` or `DeleteObject` returns success, every later `GetObject`, `HeadObject` and `ListObjects` request against that bucket sees the new state — including overwrites and deletes, which used to be eventually consistent. It is on by default everywhere, costs nothing, and needs no client change. Three things are still outside it. First, **bucket-level configuration** — bucket policies, ACLs, lifecycle rules, notification and replication configuration — is eventually consistent, so a policy change may take a moment to take effect everywhere. Second, **replication** to another bucket (CRR/SRR) is asynchronous by design; strong consistency is per bucket, not across a replicated pair. Third, strong consistency is not mutual exclusion: two concurrent PUTs to the same key still race, and the winner is undefined. For write-once semantics you need a conditional write, not a re-read.

go deeper

for a junior

Know the headline: a successful S3 write is immediately visible to the next read or listing, and the old advice about eventual consistency for overwrites is out of date.

for a middle

Explain what is inside the guarantee (new PUTs, overwrites, DELETEs, LIST, all regions, free) and what is outside it (bucket configuration, replication), and why the old S3-index-table pattern is now unnecessary.

for a senior

Demonstrate the design consequence: remove retry-until-visible loops, but recognise that consistency is not concurrency control and reach for If-None-Match or If-Match when a workflow needs a single winner.

for a principal

Own the migration argument: which legacy compensations — index tables, sleeps, immutable-key naming schemes — can now be retired across the estate, and where a workflow genuinely needs a coordination primitive that object storage will never provide.

## What changed in December 2020 Before December 2020, S3's contract was mixed. A PUT of a **brand-new** key was read-after-write consistent, but an **overwrite** PUT or a DELETE was only *eventually* consistent: a GET issued straight after could legitimately return the old object, or an object you had just deleted, and a LIST could omit a key you had just written. Applications compensated with retry loops, artificial sleeps, a database or DynamoDB table used as an index of "what should exist", or naming schemes that made every write a new key. Since December 2020 all of that is gone. Every S3 bucket in every AWS region gives **strong read-after-write consistency** for PUTs of new objects, overwrite PUTs, DELETEs, and for LIST operations. There is no flag to turn on, no extra charge, and AWS states there is no availability or performance penalty. Once a write returns 200, a subsequent read from any client, in any process, sees it. ```text PUT /bucket/key (overwrite) -> 200 GET /bucket/key -> the new body, always DELETE /bucket/key -> 204 LIST /bucket?prefix=key -> key absent (or shadowed by a marker), always ``` The practical consequence for design is large: the "S3 index table" pattern, where a separate database recorded object existence because listings could not be trusted, is now legacy. New code should read S3 directly. ## What the guarantee does *not* cover **Bucket configuration is eventually consistent.** Object data is strongly consistent; the bucket's *metadata* — bucket policy, ACLs, Block Public Access, lifecycle configuration, event notification configuration, replication configuration — is not. After changing a bucket policy you can briefly observe the old behaviour, and reading the configuration back can return the previous document. Automation that flips a policy and immediately asserts the new outcome will flake. **Replication is asynchronous.** Cross-Region and Same-Region Replication copy objects to the destination bucket after the fact. Strong consistency is a property of a single bucket, so an object readable in the source region may not exist yet in the destination. Any design that fails reads over to a replica must tolerate that gap. **Concurrency is not serialization.** Strong consistency says a read after a completed write sees that write. It says nothing about two writers racing. If two clients PUT different bodies to the same key at the same time, both may succeed; on an unversioned bucket one body survives and which one is undefined. On a versioned bucket both bodies are stored as separate versions and one of them becomes current. S3 is not a lock service and there is no transaction across keys. The modern remedy is a **conditional write**: S3 supports `If-None-Match: *` on PutObject, which fails with `412 PreconditionFailed` if the key already exists, giving a genuine create-if-absent primitive; `If-Match` against an ETag gives compare-and-swap on overwrite. These were added in 2024 and are the right tool for "exactly one writer wins", replacing the older habit of a GET-then-PUT check, which was never safe under any consistency model. **Versioning interacts, but does not weaken it.** In a versioned bucket, reads of the *current* version are strongly consistent too. What some teams mistake for stale reads is actually a delete marker: the object is unchanged, but a marker now shadows it. ## How to talk about it in an interview Three beats are enough. First, state the guarantee crisply: strong read-after-write for object PUTs, overwrites, DELETEs and LIST, everywhere, free, since December 2020. Second, name the boundary: bucket configuration and replication are still eventually consistent, and consistency is not concurrency control. Third, show the design consequence: you can delete the index table and the retry-until-visible loop, but if you need write-once you reach for `If-None-Match: *`, not for a re-read. The common failure is to answer from a book written before 2021 and say "S3 is eventually consistent" — that is a dated answer and interviewers notice. The opposite failure is to over-claim: strong consistency does not make S3 a database, does not give cross-key atomicity, and does not make replicas instantly readable.

  • A team still keeps a DynamoDB table listing which objects exist in their bucket. Would you keep it?
    Not for consistency reasons — S3 LIST has been strongly consistent since 2020, so the table no longer prevents stale or missing reads. It may still earn its place as a queryable index: filtering by business attributes, joining metadata, or avoiding expensive prefix scans over millions of keys. Keep it as an index, not as a correctness crutch.
  • How would you implement "only the first writer of this key wins" on S3?
    Use a conditional write: `PutObject` with `If-None-Match: *` succeeds only if the key does not exist and otherwise fails with 412 PreconditionFailed. For safe overwrite, use `If-Match` with the current ETag so a concurrent change causes a 412 instead of silent clobbering. A GET-then-PUT check is not equivalent — it races.
  • Your automation updates a bucket policy and immediately asserts that a request is denied, and the assertion is flaky. Why?
    Bucket configuration is outside the strong-consistency guarantee. Policies, ACLs, lifecycle and notification configuration propagate eventually, so the old policy can still be enforced for a short window after the API call succeeds. Poll for the effect with a bounded retry rather than asserting immediately after the configuration call returns.

saying these in an interview costs you the question

  • Says S3 is eventually consistent, quoting pre-2021 material
  • Thinks strong consistency must be enabled or paid for
  • Believes only new-object PUTs are strongly consistent
  • Assumes replicated copies appear synchronously in the other region
  • Treats strong consistency as protection against concurrent writers

context