---
title: "Is S3 versioning a backup?"
description: "Versioning protects you from overwriting a file. It does not protect you from anyone holding the credentials that can delete it, which is the threat that actually takes companies down."
url: "https://saved.sh/blog/is-s3-versioning-a-backup"
date: "2026-08-08"
author: "saved.sh"
tag: "Security"
---

S3 versioning keeps the old copy when you overwrite an object, and keeps a
delete marker instead of really deleting when you call delete. It costs almost
nothing, it takes one click, and everybody should turn it on.

It is also not a backup, and the difference is not pedantic. It is the difference
between surviving a bad afternoon and surviving a bad actor.

## What versioning is genuinely good at [#what-versioning-is-genuinely-good-at]

Real problems it solves, today, with no further work:

* Someone overwrote `config.json` with an empty file.
* A deploy script uploaded the wrong build over the right one.
* An `aws s3 rm` removed objects that turned out to matter.
* A sync job with a bad `--delete` flag cleared a prefix.

All four are recoverable in minutes. That is a good day's return on one click,
and if versioning is off on a bucket you care about, stop reading and go turn it
on.

## What it cannot do [#what-it-cannot-do]

Versioning lives inside the same bucket, in the same account, behind the same
credentials as the data it protects.

<Figure caption="Versioning keeps a second copy inside the boundary. Every threat that reaches the boundary reaches both copies.">
  <BlastRadius />
</Figure>

| Threat                                                                 | Versioning                          |
| ---------------------------------------------------------------------- | ----------------------------------- |
| Overwrote a file                                                       | Recovers it                         |
| Deleted a file                                                         | Recovers it                         |
| Attacker with your credentials runs a permanent delete of all versions | Everything is gone                  |
| Lifecycle rule expires noncurrent versions after 30 days               | They are gone, on schedule, quietly |
| Bucket deleted, or account closed for non-payment                      | Gone                                |
| Region-wide failure                                                    | Unavailable                         |
| You need a copy an auditor can verify is outside the vendor            | Cannot produce one                  |

The third row is the one that matters, and it is worth being blunt about it.
`s3:DeleteObjectVersion` permanently removes a specific version. An attacker who
has your credentials has that permission, and ransomware tooling has automated
this for years. Versioning is a feature your credentials control, so it defends
against accidents by people who are trying to be careful, and not at all against
someone who is not.

<Stats>
  <Stat value="1" label="API call that erases every version" />

  <Stat value="0" label="Extra credentials it needs beyond yours" />

  <Stat value="30" unit="days" label="Typical noncurrent expiry that deletes your history for you" />
</Stats>

## The lifecycle rule nobody remembers writing [#the-lifecycle-rule-nobody-remembers-writing]

There is a quieter failure here that catches careful teams.

Versioning without a lifecycle rule grows forever, so somebody eventually adds
"expire noncurrent versions after 30 days" to control the bill. That is
reasonable. It also means your versioning-based recovery window is now 30 days,
enforced automatically, and nobody wrote that down as a retention decision. It
was a cost decision that silently became a data policy.

## What actually closes the gap [#what-actually-closes-the-gap]

Three things, in order of effort:

1. **Object Lock**, which is enforced below the permission layer, so a credential
   holder cannot delete a locked version. This is the one that stops the
   ransomware case.
2. **A copy in a different account**, with different credentials, so a total
   compromise of the first account leaves the second intact.
3. **A copy in an open format you can open without the vendor**, so recovery does
   not depend on anyone's continued cooperation.

Versioning is a good first layer. It was never meant to be the only one.

## Where we sit [#where-we-sit]

Our position is that the copy should land in a bucket you own, encrypted before
it leaves the machine that produced it, and that we should hold none of the
things required to read it.

That does mean the credential question lands on you, so we make the useful part
easy: expiry that understands whether a newer good copy exists before it removes
an older one, immutability expressed as its own setting rather than folded into
retention, and a record per run of exactly where each copy went.

<Aside title="Five minutes, today" tone="accent">
  Open your backup bucket. Check three things: is versioning on, is there a
  noncurrent-version lifecycle rule quietly setting your recovery window, and
  could the credentials in your CI runner delete every version in it right now. The
  third answer is usually yes, and it is usually a surprise.
</Aside>

## So, is it a backup? [#so-is-it-a-backup]

Versioning is an undo button. A backup is a copy somewhere the thing that just
went wrong cannot reach.

Keep the undo button. It is excellent and nearly free. Just do not let it be the
reason you never built the second thing.
