Enabling S3 Versioning on an Existing Bucket: Protect Files from Accidental Overwrites
You have an S3 bucket already holding production data, and one bad PUT or DELETE call could silently destroy a file forever. Enabling versioning is the surgical fix — it turns S3 into a time-machine for every object, without touching a single existing file.
TL;DR
| Aspect | Detail |
|---|---|
| What changes for existing objects? | Nothing. Pre-existing objects get a null version ID until they are overwritten. |
| What changes for new writes? | Every PUT/DELETE creates a new version with a unique version ID. |
| Is it reversible? | Versioning can be suspended, not deleted. Once enabled, it cannot be fully disabled. |
| Cost impact? | You pay for storage of every version. Use Lifecycle rules to manage costs. |
| Required permission | s3:PutBucketVersioning on the bucket. |
How S3 Versioning Works
Think of an unversioned S3 bucket like a whiteboard — writing a new value erases the old one. Enabling versioning converts it into a stack of sticky notes: every write adds a new note on top, and the old ones remain underneath, retrievable by their unique version ID.
Real-world analogy: S3 versioning is like Google Docs revision history. The document you see is always the latest version, but every prior save is preserved and can be restored at any time. The difference: S3 charges you for every "revision" stored.
Version States Explained
- Unversioned (default): Bucket starts here. Objects have no version ID.
- Versioning-Enabled: After you run the enable command. All new writes get a unique version ID. Existing objects retain a
nullversion ID. - Versioning-Suspended: New writes get a
nullversion ID again, overwriting the previousnull-versioned object. Existing versioned objects are preserved.
What Happens to Existing Objects?
- Before versioning:
report.csvexists with no version ID. - After enabling versioning: the object is untouched. Its implicit version ID is
null. - First overwrite after enabling: S3 preserves the
null-versioned original and creates a new version with a real version ID (e.g.,abc123). - A DELETE without specifying a version ID inserts a Delete Marker — the object appears deleted but all versions remain recoverable.
Step-by-Step: Enable Versioning
Option 1 — AWS Console
- Open the S3 Console → select your bucket.
- Go to the Properties tab.
- Scroll to Bucket Versioning → click Edit.
- Select Enable → click Save changes.
Option 2 — AWS CLI
# Enable versioning on an existing bucket
aws s3api put-bucket-versioning \
--bucket your-bucket-name \
--versioning-configuration Status=Enabled
# Verify the versioning status
aws s3api get-bucket-versioning \
--bucket your-bucket-name
Expected output:
{
"Status": "Enabled"
}
Option 3 — AWS CloudFormation / IaC
🔽 Click to expand — CloudFormation snippet
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyVersionedBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: your-bucket-name
VersioningConfiguration:
Status: Enabled
LifecycleConfiguration:
Rules:
- Id: ExpireOldVersions
Status: Enabled
NoncurrentVersionExpiration:
NoncurrentDays: 90
Option 4 — Terraform
🔽 Click to expand — Terraform snippet
resource "aws_s3_bucket" "example" {
bucket = "your-bucket-name"
}
resource "aws_s3_bucket_versioning" "example" {
bucket = aws_s3_bucket.example.id
versioning_configuration {
status = "Enabled"
}
}
IAM: Least-Privilege Permission
The principal enabling versioning needs only one permission on the target bucket:
🔽 Click to expand — IAM Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowEnableVersioning",
"Effect": "Allow",
"Action": "s3:PutBucketVersioning",
"Resource": "arn:aws:s3:::your-bucket-name"
}
]
}
Recovering a Previous Version
Once versioning is active, recovering an overwritten file is a two-step operation:
# Step 1: List all versions of an object
aws s3api list-object-versions \
--bucket your-bucket-name \
--prefix report.csv
# Step 2: Restore a specific version by copying it back as the latest
aws s3api copy-object \
--bucket your-bucket-name \
--copy-source "your-bucket-name/report.csv?versionId=abc123XYZ" \
--key report.csv
Cost Control: Lifecycle Rules for Old Versions
Versioning without a Lifecycle policy is a silent cost leak. Every overwrite accumulates storage charges. Apply a NoncurrentVersionExpiration rule to automatically expire old versions after N days.
# Apply a lifecycle rule via CLI to expire noncurrent versions after 90 days
aws s3api put-bucket-lifecycle-configuration \
--bucket your-bucket-name \
--lifecycle-configuration '{
"Rules": [
{
"ID": "ExpireOldVersions",
"Status": "Enabled",
"Filter": { "Prefix": "" },
"NoncurrentVersionExpiration": {
"NoncurrentDays": 90
}
}
]
}'
Key Considerations & Gotchas
| Gotcha | Explanation |
|---|---|
| MFA Delete | For highest protection, enable MFA Delete to require multi-factor authentication before permanently deleting a version. Requires root credentials to configure. |
| Bucket replication | If you use S3 Cross-Region Replication, versioning must be enabled on both source and destination buckets. |
| Delete Markers accumulate | Add a DeleteMarkerExpiration lifecycle rule to clean up expired delete markers automatically. |
| Suspension ≠ Deletion | Suspending versioning stops creating new versions but does NOT delete existing ones. Storage costs continue. |
Glossary
| Term | Definition |
|---|---|
| Version ID | A unique string S3 assigns to each object version when versioning is enabled. |
| null version | The implicit version ID assigned to objects that existed before versioning was enabled. |
| Delete Marker | A placeholder object inserted by S3 when you delete a versioned object without specifying a version ID. Makes the object appear deleted without removing any version. |
| NoncurrentVersionExpiration | A Lifecycle rule action that expires object versions that are no longer the current (latest) version. |
| MFA Delete | An additional security layer requiring MFA authentication to permanently delete object versions or change versioning state. |
Next Steps
- 📖 Official Docs: Using versioning in S3 buckets — AWS Documentation
- 🔒 Enable MFA Delete for buckets holding critical or compliance-sensitive data.
- 💰 Set up a Lifecycle policy immediately after enabling versioning to cap storage costs.
- 🔁 If you need cross-region durability, configure S3 Cross-Region Replication — versioning is a prerequisite.
Comments
Post a Comment