← All posts
2 min read

Understand S3 delete markers through CLI

#aws#cli#s3#storage#versioning
📑 On this page

Part 23 of AWS from Zero. Today a deleted object is not necessarily gone.

What we are learning

In a versioning-enabled bucket, deleting a key without specifying a version ID creates a delete marker. The marker becomes current, so normal reads behave as if the object is missing while older versions remain stored.

Before you run it

REGION="ap-south-1"
BUCKET="aws-zero-delete-marker-12345"
KEY="message.txt"
 
aws s3api create-bucket \
  --bucket "$BUCKET" \
  --region "$REGION" \
  --create-bucket-configuration LocationConstraint="$REGION"
 
aws s3api put-bucket-versioning \
  --bucket "$BUCKET" \
  --versioning-configuration Status=Enabled
 
echo "still recoverable" > message.txt
OBJECT_VERSION=$(aws s3api put-object \
  --bucket "$BUCKET" \
  --key "$KEY" \
  --body message.txt \
  --query VersionId \
  --output text)

Create a delete marker

MARKER_VERSION=$(aws s3api delete-object \
  --bucket "$BUCKET" \
  --key "$KEY" \
  --query VersionId \
  --output text)

Inspect the result

aws s3api list-object-versions \
  --bucket "$BUCKET" \
  --prefix "$KEY" \
  --query "{Versions:Versions[].{Version:VersionId,Latest:IsLatest},DeleteMarkers:DeleteMarkers[].{Version:VersionId,Latest:IsLatest}}" \
  --output json

The delete marker should be latest. A normal head-object request now fails because the current version is a delete marker.

Remove the marker

Delete the marker by its version ID:

aws s3api delete-object \
  --bucket "$BUCKET" \
  --key "$KEY" \
  --version-id "$MARKER_VERSION"

Now the earlier object version becomes visible again:

aws s3api head-object --bucket "$BUCKET" --key "$KEY"

Common mistake

Running another delete without --version-id does not remove the old object version. It can create another delete marker. Permanent deletion requires the exact version ID and s3:DeleteObjectVersion permission.

Cleanup

aws s3api delete-object \
  --bucket "$BUCKET" \
  --key "$KEY" \
  --version-id "$OBJECT_VERSION"
 
aws s3api delete-bucket --bucket "$BUCKET" --region "$REGION"
rm message.txt

Next, we will restore any chosen older version by copying it into place.

AWS guide to delete markers