Immutable backups with S3 Object Lock
An attacker who gets into a cloud account often deletes the backups before touching the database, so there is nothing to restore from. A cleanup script with the wrong prefix does the same by accident. If the credentials that reach your database can also delete its backups, one stolen key loses both. With S3 Object Lock, the storage provider refuses to delete or overwrite a locked object before its retention date, whoever asks.
How Object Lock works
Object Lock is a bucket setting that needs versioning on. Each object version can carry a retention date. Until that date, no request can delete that version or shorten its date. It can only be extended. A bucket can also have a default retention, which locks every new object for a fixed number of days without the writer asking.
There are two modes:
| Mode | Who can remove the lock early | Use it for |
|---|---|---|
| Compliance | Nobody, including the account's root user. | Backups that have to survive stolen administrator credentials. |
| Governance | Anyone with the s3:BypassGovernanceRetention permission. | Guarding against accidents while keeping an escape hatch. |
A legal hold is a separate flag with no date. It blocks deletion until someone with permission removes it, and is meant for litigation rather than routine backups.
Set up a locked bucket on AWS
In us-east-1, leave out --create-bucket-configuration. Try a
short retention on a test bucket first. A compliance lock set by mistake cannot be undone,
and you pay for the storage until it expires.
Then take away the delete permission from every key that writes backups. The lock stops
early deletion, and a key without s3:DeleteObject cannot even add a delete
marker that hides a backup from normal listings.
What retention costs
Every locked copy is stored until its date, so the lock length multiplies with backup frequency. Hourly backups locked for 30 days means about 720 copies stored at any time. The usual answer is tiers: lock every backup for a short time, and keep the first backup of each day, week and month for longer.
| Schedule | Copies kept at once |
|---|---|
| Hourly, every copy locked 30 days | About 720 |
| Hourly locked 2 days, plus 14 daily, 4 weekly and 12 monthly | About 78 |
A lifecycle rule cannot tell a daily copy from an hourly one, so the tier has to be decided when each backup is written, by setting its retention date on upload.
Which providers support it
| Provider | Object Lock |
|---|---|
| AWS S3 | Yes, compliance and governance modes. |
| Backblaze B2 | Yes, through its S3-compatible API. Turn it on when you create the bucket. |
| Wasabi | Yes, when turned on for the bucket. |
| MinIO | Yes, on a bucket created with mc mb --with-lock. |
| DigitalOcean Spaces | No. |
| Cloudflare R2 | Check R2's current documentation for your bucket before relying on it. |
Whatever the provider, test it: write an object with a retention date, try to delete that version, and confirm the request is refused.
What a lock does not protect
- A bad backup. A lock keeps whatever was written. A dump taken after a migration dropped a table is locked just as firmly as a good one. Compare each backup with the one before it, and restore them on a schedule (how to test a restore).
- The encryption key. A locked backup you cannot decrypt is lost. Keep the key somewhere the attacker who reached the bucket cannot also reach.
- Reading. Object Lock stops deletion, not access. Encrypt before upload.
- The account. If the provider closes the account, locked objects go with it. Keep billing current, and consider a second copy with another provider.
- A bucket beside production. A backup is air-gapped from production only when its bucket refuses deletes under Object Lock in compliance mode and sits in an account whose credentials production does not hold; a locked bucket in the production account is still reachable with production's keys.
How SafeGrd does it
SafeGrd writes every backup under compliance-mode Object Lock, in your bucket or in its
hosted storage, and sets each backup's retention date on upload so daily, weekly and
monthly copies can be kept longer (tiers). The console's
setup wizard writes a host key policy that cannot delete, and safegrd doctor
checks that the bucket really has Object Lock on. For a provider without it, you have to
set worm_mode: "NONE" on purpose, and SafeGrd then shows those backups as
deletable. Threat Shield flags a backup that lost most of
its rows, and Fire Drills restore the newest one on a schedule.