

# Retaining multiple versions of objects with S3 Versioning
<a name="Versioning"></a>

Versioning in Amazon S3 is a means of keeping multiple variants of an object in the same bucket. You can use the S3 Versioning feature to preserve, retrieve, and restore every version of every object stored in your buckets. With versioning you can recover more easily from both unintended user actions and application failures. After versioning is enabled for a bucket, if Amazon S3 receives multiple write requests for the same object simultaneously, it stores all of those objects.

Versioning-enabled buckets can help you recover objects from accidental deletion or overwrite. For example, if you delete an object, Amazon S3 inserts a delete marker instead of removing the object permanently. The delete marker becomes the current object version. If you overwrite an object, it results in a new object version in the bucket. You can always restore the previous version. For more information, see [Deleting object versions from a versioning-enabled bucket](DeletingObjectVersions.md). 

By default, S3 Versioning is disabled on buckets, and you must explicitly enable it. For more information, see [Enabling versioning on buckets](manage-versioning-examples.md).

**Note**  
The SOAP API does not support S3 Versioning. SOAP support over HTTP is deprecated, but it is still available over HTTPS. New Amazon S3 features are not supported for SOAP.
Normal Amazon S3 rates apply for every version of an object stored and transferred. Each version of an object is the entire object; it is not just a diff from the previous version. Thus, if you have three versions of an object stored, you are charged for three objects. 

## Unversioned, versioning-enabled, and versioning-suspended buckets
<a name="versioning-states"></a>

Buckets can be in one of three states: 
+ Unversioned (the default)
+ Versioning-enabled
+ Versioning-suspended

You enable and suspend versioning at the bucket level. After you version-enable a bucket, it can never return to an unversioned state. But you can *suspend* versioning on that bucket.

The versioning state applies to all (never some) of the objects in that bucket. When you enable versioning in a bucket, all new objects are versioned and given a unique version ID. Objects that already existed in the bucket at the time versioning was enabled will thereafter *always* be versioned and given a unique version ID when they are modified by future requests. Note the following: 
+ Objects that are stored in your bucket before you set the versioning state have a version ID of `null`. When you enable versioning, existing objects in your bucket do not change. What changes is how Amazon S3 handles the objects in future requests. For more information, see [Working with objects in a versioning-enabled bucket](manage-objects-versioned-bucket.md).
+ The bucket owner (or any user with appropriate permissions) can suspend versioning to stop accruing object versions. When you suspend versioning, existing objects in your bucket do not change. What changes is how Amazon S3 handles objects in future requests. For more information, see [Working with objects in a versioning-suspended bucket](VersionSuspendedBehavior.md).

## Using S3 Versioning with S3 Lifecycle
<a name="versioning-lifecycle"></a>

To customize your data retention approach and control storage costs, use object versioning with S3 Lifecycle. For more information, see [Managing the lifecycle of objects](object-lifecycle-mgmt.md). For information about creating S3 Lifecycle configurations using the AWS Management Console, AWS CLI, AWS SDKs, or the REST API, see [Setting an S3 Lifecycle configuration on a bucket](how-to-set-lifecycle-configuration-intro.md).

**Important**  
If you have an object expiration lifecycle configuration in your unversioned bucket and you want to maintain the same permanent delete behavior when you enable versioning, you must add a noncurrent expiration configuration. The noncurrent expiration lifecycle configuration manages the deletes of the noncurrent object versions in the versioning-enabled bucket. (A versioning-enabled bucket maintains one current, and zero or more noncurrent, object versions.) For more information, see [Setting an S3 Lifecycle configuration on a bucket](how-to-set-lifecycle-configuration-intro.md).

For information about working with S3 Versioning, see the following topics.

**Topics**
+ [

## Unversioned, versioning-enabled, and versioning-suspended buckets
](#versioning-states)
+ [

## Using S3 Versioning with S3 Lifecycle
](#versioning-lifecycle)
+ [

# How S3 Versioning works
](versioning-workflows.md)
+ [

# Enabling versioning on buckets
](manage-versioning-examples.md)
+ [

# Configuring MFA delete
](MultiFactorAuthenticationDelete.md)
+ [

# Working with objects in a versioning-enabled bucket
](manage-objects-versioned-bucket.md)
+ [

# Working with objects in a versioning-suspended bucket
](VersionSuspendedBehavior.md)
+ [

# Troubleshooting versioning
](troubleshooting-versioning.md)

# How S3 Versioning works
<a name="versioning-workflows"></a>

You can use S3 Versioning to keep multiple versions of an object in one bucket so that you can restore objects that are accidentally deleted or overwritten. For example, if you apply S3 Versioning to a bucket, the following changes occur: 
+ If you delete an object, instead of removing the object permanently, Amazon S3 inserts a delete marker, which becomes the current object version. You can then restore the previous version. For more information, see [Deleting object versions from a versioning-enabled bucket](DeletingObjectVersions.md).
+ If you overwrite an object, Amazon S3 adds a new object version in the bucket. The previous version remains in the bucket and becomes a noncurrent version. You can restore the previous version.

**Note**  
Normal Amazon S3 rates apply for every version of an object that is stored and transferred. Each version of an object is the entire object; it is not a diff from the previous version. Thus, if you have three versions of an object stored, you are charged for three objects.

Each S3 bucket that you create has a *versioning* subresource associated with it. (For more information, see [General purpose buckets configuration options](UsingBucket.md#bucket-config-options-intro).) By default, your bucket is *unversioned*, and the versioning subresource stores the empty versioning configuration, as follows.

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
</VersioningConfiguration>
```

To enable versioning, you can send a request to Amazon S3 with a versioning configuration that includes an `Enabled` status. 

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
  <Status>Enabled</Status> 
</VersioningConfiguration>
```

To suspend versioning, you set the status value to `Suspended`.

**Note**  
When you enable versioning on a bucket for the first time, it might take a short amount of time for the change to be fully propagated. While this change is propagating, you may encounter intermittent `HTTP 404 NoSuchKey` errors for requests to objects created or updated after enabling versioning. We recommend that you wait for 15 minutes after enabling versioning before issuing write operations (`PUT` or `DELETE`) on objects in the bucket. 

The bucket owner and all authorized AWS Identity and Access Management (IAM) users can enable versioning. The bucket owner is the AWS account that created the bucket. For more information about permissions, see [Identity and Access Management for Amazon S3](security-iam.md).

For more information about enabling and disabling S3 Versioning by using the AWS Management Console, AWS Command Line Interface (AWS CLI), or REST API, see [Enabling versioning on buckets](manage-versioning-examples.md).

**Topics**
+ [

## Version IDs
](#version-ids)
+ [

## Versioning workflows
](#versioning-workflows-examples)

## Version IDs
<a name="version-ids"></a>

If you enable versioning for a bucket, Amazon S3 automatically generates a unique version ID for the object that is being stored. For example, in one bucket you can have two objects with the same key (object name) but different version IDs, such as `photo.gif` (version 111111) and `photo.gif` (version 121212).

![\[Diagram depicting a versioning-enabled bucket that has two objects with the same key but different version IDs.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_Enabled.png)


Each object has a version ID, whether or not S3 Versioning is enabled. If S3 Versioning is not enabled, Amazon S3 sets the value of the version ID to `null`. If you enable S3 Versioning, Amazon S3 assigns a version ID value for the object. This value distinguishes that object from other versions of the same key.

When you enable S3 Versioning on an existing bucket, objects that are already stored in the bucket are unchanged. Their version IDs (`null`), contents, and permissions remain the same. After you enable S3 Versioning, each object that is added to the bucket gets a version ID, which distinguishes it from other versions of the same key. 

Only Amazon S3 generates version IDs, and they cannot be edited. Version IDs are Unicode, UTF-8 encoded, URL-ready, opaque strings that are no more than 1,024 bytes long. The following is an example:

`3sL4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo`

**Note**  
For simplicity, the other examples in this topic use much shorter IDs.



## Versioning workflows
<a name="versioning-workflows-examples"></a>

When you `PUT` an object in a versioning-enabled bucket, the noncurrent version is not overwritten. As shown in the following figure, when a new version of `photo.gif` is `PUT` into a bucket that already contains an object with the same name, the following behavior occurs:
+ The original object (ID = 111111) remains in the bucket.
+ Amazon S3 generates a new version ID (121212), and adds this newer version of the object to the bucket.

![\[Diagram depicting how S3 Versioning works when you PUT an object in a versioning-enabled bucket.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_PUT_versionEnabled3.png)


With this functionality, you can retrieve a previous version of an object if an object has been accidentally overwritten or deleted.

When you `DELETE` an object, all versions remain in the bucket, and Amazon S3 inserts a delete marker, as shown in the following figure.

![\[Illustration that shows a delete marker insertion.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled.png)


The delete marker becomes the current version of the object. By default, `GET` requests retrieve the most recently stored version. Performing a `GET Object` request when the current version is a delete marker returns a `404 Not Found` error, as shown in the following figure.

![\[Illustration that shows a GetObject call for a delete marker returning a 404 (Not Found) error.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_NoObjectFound.png)


However, you can `GET` a noncurrent version of an object by specifying its version ID. In the following figure, you `GET` a specific object version, 111111. Amazon S3 returns that object version even though it's not the current version.

For more information, see [Retrieving object versions from a versioning-enabled bucket](RetrievingObjectVersions.md).

![\[Diagram depicting how S3 Versioning works when you GET a noncurrent version in a versioning-enabled bucket.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_GET_Versioned3.png)


You can permanently delete an object by specifying the version that you want to delete. Only the owner of an Amazon S3 bucket or an authorized IAM user can permanently delete a version. If your `DELETE` operation specifies the `versionId`, that object version is permanently deleted, and Amazon S3 doesn't insert a delete marker.

![\[Diagram that shows how DELETE versionId permanently deletes a specific object version.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled2.png)


You can add more security by configuring a bucket to enable multi-factor authentication (MFA) delete. When you enable MFA delete for a bucket, the bucket owner must include two forms of authentication in any request to delete a version or change the versioning state of the bucket. For more information, see [Configuring MFA delete](MultiFactorAuthenticationDelete.md).

### When are new versions created for an object?
<a name="versioning-workflows-new-versions"></a>

New versions of objects are created only when you `PUT` a new object. Be aware that certain actions, such as `CopyObject`, work by implementing a `PUT` operation.

Some actions that modify the current object don't create a new version because they don't `PUT` a new object. This includes actions such as changing the tags on an object. 

**Important**  
If you notice a significant increase in the number of HTTP 503 (Service Unavailable) responses received for Amazon S3 `PUT` or `DELETE` object requests to a bucket that has S3 Versioning enabled, you might have one or more objects in the bucket for which there are millions of versions. For more information, see the S3 Versioning section of [Troubleshooting versioning](troubleshooting-versioning.md).

# Enabling versioning on buckets
<a name="manage-versioning-examples"></a>

You can use S3 Versioning to keep multiple versions of an object in one bucket. This section provides examples of how to enable versioning on a bucket using the console, REST API, AWS SDKs, and AWS Command Line Interface (AWS CLI). 

**Note**  
After enabling versioning on a bucket for the first time, it may take up to 15 minutes for the change to fully propagate across the S3 system. During this time, `GET` requests for objects created or updated after enabling versioning may result in `HTTP 404 NoSuchKey` errors. We recommend waiting 15 minutes after enabling versioning before performing any write operations (`PUT` or `DELETE`) on objects in the bucket. This waiting period helps avoid potential issues with object visibility and version tracking.

For more information about S3 Versioning, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md). For information about working with objects that are in versioning-enabled buckets, see [Working with objects in a versioning-enabled bucket](manage-objects-versioned-bucket.md).

To learn more about how to use S3 Versioning to protect data, see [Tutorial: Protecting data on Amazon S3 against accidental deletion or application bugs using S3 Versioning, S3 Object Lock, and S3 Replication](https://aws.amazon.com/getting-started/hands-on/protect-data-on-amazon-s3/?ref=docs_gateway/amazons3/manage-versioning-examples.html).

Each S3 bucket that you create has a *versioning* subresource associated with it. (For more information, see [General purpose buckets configuration options](UsingBucket.md#bucket-config-options-intro).) By default, your bucket is *unversioned*, and the versioning subresource stores the empty versioning configuration, as follows.

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
</VersioningConfiguration>
```

To enable versioning, you can send a request to Amazon S3 with a versioning configuration that includes a status. 

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
  <Status>Enabled</Status> 
</VersioningConfiguration>
```

To suspend versioning, you set the status value to `Suspended`.

The bucket owner and all authorized users can enable versioning. The bucket owner is the AWS account that created the bucket (the root account). For more information about permissions, see [Identity and Access Management for Amazon S3](security-iam.md).

The following sections provide more detail about enabling S3 Versioning using the console, AWS CLI, and the AWS SDKs.

## Using the S3 console
<a name="enable-versioning"></a>

Follow these steps to use the AWS Management Console to enable versioning on an S3 bucket.

**To enable or disable versioning on an S3 general purpose bucket**

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the left navigation pane, choose **General purpose buckets**.

1. In the buckets list, choose the name of the bucket that you want to enable versioning for.

1. Choose **Properties**.

1. Under **Bucket Versioning**, choose **Edit**.

1. Choose **Suspend** or **Enable**, and then choose **Save changes**.

**Note**  
You can use AWS multi-factor authentication (MFA) with versioning. When you use MFA with versioning, you must provide your AWS account’s access keys and a valid code from the account’s MFA device to permanently delete an object version or suspend or reactivate versioning.   
To use MFA with versioning, you enable `MFA Delete`. However, you can't enable `MFA Delete` using the AWS Management Console. You must use the AWS Command Line Interface (AWS CLI) or the API. For more information, see [Configuring MFA delete](MultiFactorAuthenticationDelete.md).

## Using the AWS CLI
<a name="manage-versioning-examples-cli"></a>

The following example enables versioning on an S3 general purpose bucket. 

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled
```

The following example enables S3 Versioning and multi-factor authentication (MFA) delete on a bucket for a physical MFA device. For physical MFA devices, in the `--mfa` parameter, pass a concatenation of the MFA device serial number, a space character, and the value that is displayed on your authentication device.

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "SerialNumber 123456"
```

The following example enables S3 Versioning and multi-factor authentication (MFA) delete on a bucket for a virtual MFA device. For virtual MFA devices, in the `--mfa` parameter, pass a concatenation of the MFA device ARN, a space character, and the value that is displayed on your authentication device.

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "arn:aws:iam::account-id:mfa/root-account-mfa-device 123789"
```

**Note**  
Using MFA delete requires an approved physical or virtual authentication device. For more information about using MFA delete in Amazon S3, see [Configuring MFA delete](MultiFactorAuthenticationDelete.md).

For more information about enabling versioning using the AWS CLI, see [put-bucket-versioning](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-versioning.html) in the *AWS CLI Command Reference*.

## Using the AWS SDKs
<a name="manage-versioning-examples-sdk"></a>

The following examples enable versioning on a bucket and then retrieve versioning status using the AWS SDK for Java and the AWS SDK for .NET. For information about using other AWS SDKs, see the [AWS Developer Center](https://aws.amazon.com/code/).

------
#### [ .NET ]

For information about setting up and running the code examples, see [Getting Started with the AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html) in the *AWS SDK for .NET Developer Guide*. 

```
using System;
using Amazon.S3;
using Amazon.S3.Model;

namespace s3.amazon.com.rproxy.goskope.com.docsamples
{
    class BucketVersioningConfiguration
    {
        static string bucketName = "*** bucket name ***";

        public static void Main(string[] args)
        {
            using (var client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1))
            {
                try
                {
                    EnableVersioningOnBucket(client);
                    string bucketVersioningStatus = RetrieveBucketVersioningConfiguration(client);
                }
                catch (AmazonS3Exception amazonS3Exception)
                {
                    if (amazonS3Exception.ErrorCode != null &&
                        (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId")
                        ||
                        amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
                    {
                        Console.WriteLine("Check the provided AWS Credentials.");
                        Console.WriteLine(
                        "To sign up for service, go to http://aws.amazon.com/s3");
                    }
                    else
                    {
                        Console.WriteLine(
                         "Error occurred. Message:'{0}' when listing objects",
                         amazonS3Exception.Message);
                    }
                }
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        static void EnableVersioningOnBucket(IAmazonS3 client)
        {

                PutBucketVersioningRequest request = new PutBucketVersioningRequest
                {
                    BucketName = bucketName,
                    VersioningConfig = new S3BucketVersioningConfig 
                    {
                        Status = VersionStatus.Enabled
                    }
                };

                PutBucketVersioningResponse response = client.PutBucketVersioning(request);
        }


        static string RetrieveBucketVersioningConfiguration(IAmazonS3 client)
        {
                GetBucketVersioningRequest request = new GetBucketVersioningRequest
                {
                    BucketName = bucketName
                };
 
                GetBucketVersioningResponse response = client.GetBucketVersioning(request);
                return response.VersioningConfig.Status;
            }
    }
}
```

------
#### [ Java ]

For instructions on how to create and test a working sample, see [Getting Started](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html) in the AWS SDK for Java Developer Guide.

```
import java.io.IOException;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.BucketVersioningConfiguration;
import com.amazonaws.services.s3.model.SetBucketVersioningConfigurationRequest;

public class BucketVersioningConfigurationExample {
    public static String bucketName = "*** bucket name ***"; 
    public static AmazonS3Client s3Client;

    public static void main(String[] args) throws IOException {
        s3Client = new AmazonS3Client(new ProfileCredentialsProvider());
        s3Client.setRegion(Region.getRegion(Regions.US_EAST_1));
        try {

            // 1. Enable versioning on the bucket.
        	BucketVersioningConfiguration configuration = 
        			new BucketVersioningConfiguration().withStatus("Enabled");
            
			SetBucketVersioningConfigurationRequest setBucketVersioningConfigurationRequest = 
					new SetBucketVersioningConfigurationRequest(bucketName,configuration);
			
			s3Client.setBucketVersioningConfiguration(setBucketVersioningConfigurationRequest);
			
			// 2. Get bucket versioning configuration information.
			BucketVersioningConfiguration conf = s3Client.getBucketVersioningConfiguration(bucketName);
			 System.out.println("bucket versioning configuration status:    " + conf.getStatus());

        } catch (AmazonS3Exception amazonS3Exception) {
            System.out.format("An Amazon S3 error occurred. Exception: %s", amazonS3Exception.toString());
        } catch (Exception ex) {
            System.out.format("Exception: %s", ex.toString());
        }        
    }
}
```

------
#### [ Python ]

The following Python code example creates an Amazon S3 bucket, enables it for versioning, and configures a lifecycle that expires noncurrent object versions after 7 days.

```
def create_versioned_bucket(bucket_name, prefix):
    """
    Creates an Amazon S3 bucket, enables it for versioning, and configures a lifecycle
    that expires noncurrent object versions after 7 days.

    Adding a lifecycle configuration to a versioned bucket is a best practice.
    It helps prevent objects in the bucket from accumulating a large number of
    noncurrent versions, which can slow down request performance.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket_name: The name of the bucket to create.
    :param prefix: Identifies which objects are automatically expired under the
                   configured lifecycle rules.
    :return: The newly created bucket.
    """
    try:
        bucket = s3.create_bucket(
            Bucket=bucket_name,
            CreateBucketConfiguration={
                "LocationConstraint": s3.meta.client.meta.region_name
            },
        )
        logger.info("Created bucket %s.", bucket.name)
    except ClientError as error:
        if error.response["Error"]["Code"] == "BucketAlreadyOwnedByYou":
            logger.warning("Bucket %s already exists! Using it.", bucket_name)
            bucket = s3.Bucket(bucket_name)
        else:
            logger.exception("Couldn't create bucket %s.", bucket_name)
            raise

    try:
        bucket.Versioning().enable()
        logger.info("Enabled versioning on bucket %s.", bucket.name)
    except ClientError:
        logger.exception("Couldn't enable versioning on bucket %s.", bucket.name)
        raise

    try:
        expiration = 7
        bucket.LifecycleConfiguration().put(
            LifecycleConfiguration={
                "Rules": [
                    {
                        "Status": "Enabled",
                        "Prefix": prefix,
                        "NoncurrentVersionExpiration": {"NoncurrentDays": expiration},
                    }
                ]
            }
        )
        logger.info(
            "Configured lifecycle to expire noncurrent versions after %s days "
            "on bucket %s.",
            expiration,
            bucket.name,
        )
    except ClientError as error:
        logger.warning(
            "Couldn't configure lifecycle on bucket %s because %s. "
            "Continuing anyway.",
            bucket.name,
            error,
        )

    return bucket
```

------

# Configuring MFA delete
<a name="MultiFactorAuthenticationDelete"></a>

When working with S3 Versioning in Amazon S3 buckets, you can optionally add another layer of security by configuring a bucket to enable *MFA (multi-factor authentication) delete*. When you do this, the bucket owner must include two forms of authentication in any request to delete a version or change the versioning state of the bucket.

MFA delete requires additional authentication for either of the following operations:
+ Changing the versioning state of your bucket
+ Permanently deleting an object version

MFA delete requires two forms of authentication together:
+ Your security credentials
+ The concatenation of a valid serial number, a space, and the six-digit code displayed on an approved authentication device

MFA delete thus provides added security if, for example, your security credentials are compromised. MFA delete can help prevent accidental bucket deletions by requiring the user who initiates the delete action to prove physical possession of an MFA device with an MFA code and adding an extra layer of friction and security to the delete action.

To identify buckets that have MFA delete enabled, you can use Amazon S3 Storage Lens metrics. S3 Storage Lens is a cloud-storage analytics feature that you can use to gain organization-wide visibility into object-storage usage and activity. For more information, see [ Assessing your storage activity and usage with S3 Storage Lens](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens?icmpid=docs_s3_user_guide_MultiFactorAuthenticationDelete.html). For a complete list of metrics, see [ S3 Storage Lens metrics glossary](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens_metrics_glossary.html?icmpid=docs_s3_user_guide_MultiFactorAuthenticationDelete.html).

The bucket owner, the AWS account that created the bucket (root account), and all authorized users can enable versioning. However, only the bucket owner (root account) can enable MFA delete. For more information, see [Securing Access to AWS Using MFA](https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/) on the AWS Security Blog.

**Note**  
To use MFA delete with versioning, you enable `MFA Delete`. However, you cannot enable `MFA Delete` using the AWS Management Console. You must use the AWS Command Line Interface (AWS CLI) or the API.   
For examples of using MFA delete with versioning, see the examples section in the topic [Enabling versioning on buckets](manage-versioning-examples.md).  
You cannot use MFA delete with lifecycle configurations. For more information about lifecycle configurations and how they interact with other configurations, see [How S3 Lifecycle interacts with other bucket configurations](lifecycle-and-other-bucket-config.md).

To enable or disable MFA delete, you use the same API that you use to configure versioning on a bucket. Amazon S3 stores the MFA delete configuration in the same *versioning* subresource that stores the bucket's versioning status.

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
  <Status>VersioningState</Status>
  <MfaDelete>MfaDeleteState</MfaDelete>  
</VersioningConfiguration>
```

To use MFA delete, you can use either a hardware or virtual MFA device to generate an authentication code. The following example shows a generated authentication code displayed on a hardware device.

![\[An example of a generated authentication code displayed on a hardware device.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/MFADevice.png)


MFA delete and MFA-protected API access are features intended to provide protection for different scenarios. You configure MFA delete on a bucket to help ensure that the data in your bucket cannot be accidentally deleted. MFA-protected API access is used to enforce another authentication factor (MFA code) when accessing sensitive Amazon S3 resources. You can require any operations against these Amazon S3 resources to be done with temporary credentials created using MFA. For an example, see [Requiring MFA](example-bucket-policies.md#example-bucket-policies-MFA). 

For more information about how to purchase and activate an authentication device, see [Multi-factor authentication](https://aws.amazon.com/iam/details/mfa/).

## To enable S3 Versioning and configure MFA delete
<a name="enable-versioning-mfa-delete"></a>

### Using the AWS CLI
<a name="enable-versioning-mfa-delete-cli"></a>

The serial number is the number that uniquely identifies the MFA device. For physical MFA devices, this is the unique serial number that's provided with the device. For virtual MFA devices, the serial number is the device ARN. To use the following commands, replace the *user input placeholders* with your own information.

The following example enables S3 Versioning and multi-factor authentication (MFA) delete on a bucket for a physical MFA device. For physical MFA devices, in the `--mfa` parameter, pass a concatenation of the MFA device serial number, a space character, and the value that is displayed on your authentication device.

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "SerialNumber 123456"
```

The following example enables S3 Versioning and multi-factor authentication (MFA) delete on a bucket for a virtual MFA device. For virtual MFA devices, in the `--mfa` parameter, pass a concatenation of the MFA device ARN, a space character, and the value that is displayed on your authentication device.

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "arn:aws:iam::account-id:mfa/root-account-mfa-device 123789"
```

For more information, see the AWS rePost article [How do I turn on MFA delete for my Amazon S3 bucket?](https://repost.aws/knowledge-center/s3-bucket-mfa-delete).

### Using the REST API
<a name="enable-versioning-mfa-delete-rest-api"></a>

For more information about specifying MFA delete using the Amazon S3 REST API, see [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html) *Amazon Simple Storage Service API Reference*.

# Working with objects in a versioning-enabled bucket
<a name="manage-objects-versioned-bucket"></a>

Objects that are stored in an Amazon S3 bucket before you set the versioning state have a version ID of `null`. When you enable versioning, existing objects in your bucket do not change. What changes is how Amazon S3 handles the objects in future requests.

**Transitioning object versions**  
You can define lifecycle configuration rules for objects that have a well-defined lifecycle to transition object versions to the S3 Glacier Flexible Retrieval storage class at a specific time in the object's lifetime. For more information, see [Managing the lifecycle of objects](object-lifecycle-mgmt.md).

The topics in this section explain various object operations in a versioning-enabled bucket. For more information about versioning, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md).

**Topics**
+ [

# Adding objects to versioning-enabled buckets
](AddingObjectstoVersioningEnabledBuckets.md)
+ [

# Listing objects in a versioning-enabled bucket
](list-obj-version-enabled-bucket.md)
+ [

# Retrieving object versions from a versioning-enabled bucket
](RetrievingObjectVersions.md)
+ [

# Deleting object versions from a versioning-enabled bucket
](DeletingObjectVersions.md)
+ [

# Configuring versioned object permissions
](VersionedObjectPermissionsandACLs.md)

# Adding objects to versioning-enabled buckets
<a name="AddingObjectstoVersioningEnabledBuckets"></a>

After you enable versioning on a bucket, Amazon S3 automatically adds a unique version ID to every object stored (using `PUT`, `POST`, or `CopyObject`) in the bucket. 

The following figure shows that Amazon S3 adds a unique version ID to an object when it is added to a versioning-enabled bucket. 

![\[Illustration that shows a unique version ID added to an object when it is put in a versioning-enabled bucket.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_PUT_versionEnabled.png)


**Note**  
The version ID values that Amazon S3 assigns are URL safe (can be included as part of a URI).

For more information about versioning, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md). You can add object versions to a versioning-enabled bucket using the console, AWS SDKs, and REST API.

## Using the console
<a name="add-obj-versioning-enabled-bucket-console"></a>

For instructions, see [Uploading objects](upload-objects.md). 

## Using the AWS SDKs
<a name="add-obj-versioning-enabled-bucket-sdk"></a>

For examples of uploading objects using the AWS SDKs for Java, .NET, and PHP, see [Uploading objects](upload-objects.md). The examples for uploading objects in nonversioned and versioning-enabled buckets are the same, although in the case of versioning-enabled buckets, Amazon S3 assigns a version number. Otherwise, the version number is null. 

For information about using other AWS SDKs, see the [AWS Developer Center](https://aws.amazon.com/code/). 

## Using the REST API
<a name="add-obj-versioning-enabled-bucket-rest"></a>

**To add objects to versioning-enabled buckets**

1. Enable versioning on a bucket using a `PutBucketVersioning` request.

   For more information, see [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html) in the *Amazon Simple Storage Service API Reference*.

1. Send a `PUT`, `POST`, or `CopyObject` request to store an object in the bucket.

When you add an object to a versioning-enabled bucket, Amazon S3 returns the version ID of the object in the `x-amz-version-id` response header, as shown in the following example.

```
1. x-amz-version-id: 3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY
```

# Listing objects in a versioning-enabled bucket
<a name="list-obj-version-enabled-bucket"></a>

This section provides examples of listing object versions from a versioning-enabled bucket. Amazon S3 stores object version information in the *versions* subresource that is associated with the bucket. For more information, see [General purpose buckets configuration options](UsingBucket.md#bucket-config-options-intro). In order to list the objects in a versioning-enabled bucket, you need the `ListBucketVersions` permission.

## Using the S3 console
<a name="view-object-versions"></a>

Follow these steps to use the Amazon S3 console to see the different versions of an object.

**To see multiple versions of an object**

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the **Buckets** list, choose the name of the bucket that contains the object.

1. To see a list of the versions of the objects in the bucket, choose the **Show versions** switch. 

   For each object version, the console shows a unique version ID, the date and time the object version was created, and other properties. (Objects stored in your bucket before you set the versioning state have a version ID of **null**.)

   To list the objects without the versions, choose the **List versions** switch.

You also can view, download, and delete object versions in the object overview pane on the console. For more information, see [Viewing object properties in the Amazon S3 console](view-object-properties.md).

**Note**  
 To access object versions older than 300 versions, you must use the AWS CLI or the object's URL.

**Important**  
You can undelete an object only if it was deleted as the latest (current) version. You can't undelete a previous version of an object that was deleted. For more information, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md).

## Using the AWS SDKs
<a name="list-obj-version-enabled-bucket-sdk-examples"></a>

The examples in this section show how to retrieve an object listing from a versioning-enabled bucket. Each request returns up to 1,000 versions, unless you specify a lower number. If the bucket contains more versions than this limit, you send a series of requests to retrieve the list of all versions. This process of returning results in "pages" is called *pagination*.

To show how pagination works, the examples limit each response to two object versions. After retrieving the first page of results, each example checks to determine whether the version list was truncated. If it was, the example continues retrieving pages until all versions have been retrieved. 

**Note**  
The following examples also work with a bucket that isn't versioning-enabled, or for objects that don't have individual versions. In those cases, Amazon S3 returns the object listing with a version ID of `null`.

 For information about using other AWS SDKs, see the [AWS Developer Center](https://aws.amazon.com/code/). 

------
#### [ Java ]

For instructions on creating and testing a working sample, see [Getting Started](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html) in the AWS SDK for Java Developer Guide.

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ListVersionsRequest;
import com.amazonaws.services.s3.model.S3VersionSummary;
import com.amazonaws.services.s3.model.VersionListing;

public class ListKeysVersioningEnabledBucket {

    public static void main(String[] args) {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new ProfileCredentialsProvider())
                    .withRegion(clientRegion)
                    .build();

            // Retrieve the list of versions. If the bucket contains more versions
            // than the specified maximum number of results, Amazon S3 returns
            // one page of results per request.
            ListVersionsRequest request = new ListVersionsRequest()
                    .withBucketName(bucketName)
                    .withMaxResults(2);
            VersionListing versionListing = s3Client.listVersions(request);
            int numVersions = 0, numPages = 0;
            while (true) {
                numPages++;
                for (S3VersionSummary objectSummary : versionListing.getVersionSummaries()) {
                    System.out.printf("Retrieved object %s, version %s\n",
                            objectSummary.getKey(),
                            objectSummary.getVersionId());
                    numVersions++;
                }
                // Check whether there are more pages of versions to retrieve. If
                // there are, retrieve them. Otherwise, exit the loop.
                if (versionListing.isTruncated()) {
                    versionListing = s3Client.listNextBatchOfVersions(versionListing);
                } else {
                    break;
                }
            }
            System.out.println(numVersions + " object versions retrieved in " + numPages + " pages");
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}
```

------
#### [ .NET ]

For information about setting up and running the code examples, see [Getting Started with the AWS SDK for .NET](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html) in the *AWS SDK for .NET Developer Guide*. 

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class ListObjectsVersioningEnabledBucketTest
    {
        static string bucketName = "*** bucket name ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main(string[] args)
        {
            s3Client = new AmazonS3Client(bucketRegion);
            GetObjectListWithAllVersionsAsync().Wait();
        }

        static async Task GetObjectListWithAllVersionsAsync()
        {
            try
            {
                ListVersionsRequest request = new ListVersionsRequest()
                {
                    BucketName = bucketName,
                    // You can optionally specify key name prefix in the request
                    // if you want list of object versions of a specific object.

                    // For this example we limit response to return list of 2 versions.
                    MaxKeys = 2
                };
                do
                {
                    ListVersionsResponse response = await s3Client.ListVersionsAsync(request); 
                    // Process response.
                    foreach (S3ObjectVersion entry in response.Versions)
                    {
                        Console.WriteLine("key = {0} size = {1}",
                            entry.Key, entry.Size);
                    }

                    // If response is truncated, set the marker to get the next 
                    // set of keys.
                    if (response.IsTruncated)
                    {
                        request.KeyMarker = response.NextKeyMarker;
                        request.VersionIdMarker = response.NextVersionIdMarker;
                    }
                    else
                    {
                        request = null;
                    }
                } while (request != null);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

------

## Using the REST API
<a name="ListingtheObjectsinaVersioningEnabledBucket"></a>

**Example — Listing all object versions in a bucket**  
To list all the versions of all the objects in a bucket, you use the `versions` subresource in a `GET Bucket` request. Amazon S3 can retrieve a maximum of 1,000 objects, and each object version counts fully as an object. Therefore, if a bucket contains two keys (for example, `photo.gif` and `picture.jpg`), and the first key has 990 versions and the second key has 400 versions, a single request would retrieve all 990 versions of `photo.gif` and only the most recent 10 versions of `picture.jpg`.  
Amazon S3 returns object versions in the order in which they were stored, with the most recently stored returned first.  
In a `GET Bucket` request, include the `versions` subresource.  

```
1. GET /?versions HTTP/1.1
2. Host: bucketName.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 +0000
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

**Example — Retrieving all versions of a key**  
 To retrieve a subset of object versions, you use the request parameters for `GET Bucket`. For more information, see [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html).   

1. Set the `prefix` parameter to the key of the object that you want to retrieve.

1. Send a `GET Bucket` request using the `versions` subresource and `prefix`.

   `GET /?versions&prefix=objectName HTTP/1.1`

**Example — Retrieving objects using a prefix**  
The following example retrieves objects whose key is or begins with `myObject`.  

```
1. GET /?versions&prefix=myObject HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```
You can use the other request parameters to retrieve a subset of all versions of the object. For more information, see [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html) in the *Amazon Simple Storage Service API Reference*.

**Example — Retrieving a listing of additional objects if the response is truncated**  
If the number of objects that could be returned in a `GET` request exceeds the value of `max-keys`, the response contains `<isTruncated>true</isTruncated>`, and includes the first key (in `NextKeyMarker`) and the first version ID (in `NextVersionIdMarker`) that satisfy the request, but were not returned. You use those returned values as the starting position in a subsequent request to retrieve the additional objects that satisfy the `GET` request.   
Use the following process to retrieve additional objects that satisfy the original `GET Bucket versions` request from a bucket. For more information about `key-marker`, `version-id-marker`, `NextKeyMarker`, and `NextVersionIdMarker`, see [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html) in the *Amazon Simple Storage Service API Reference*.  
The following are additional responses that satisfy the original `GET` request:  
+ Set the value of `key-marker` to the key returned in `NextKeyMarker` in the previous response.
+ Set the value of `version-id-marker` to the version ID returned in `NextVersionIdMarker` in the previous response.
+ Send a `GET Bucket versions` request using `key-marker` and `version-id-marker`.

**Example — Retrieving objects starting with a specified key and version ID**  

```
1. GET /?versions&key-marker=myObject&version-id-marker=298459348571 HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

## Using the AWS CLI
<a name="list-obj-version-enabled-bucket-cli"></a>

The following command returns metadata about all versions of the objects in a bucket. 

```
aws s3api list-object-versions --bucket amzn-s3-demo-bucket1
```

For more information about `list-object-versions` see [https://docs.aws.amazon.com/cli/latest/reference/s3api/list-object-versions.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-object-versions.html) in the *AWS CLI Command Reference*.

# Retrieving object versions from a versioning-enabled bucket
<a name="RetrievingObjectVersions"></a>

Versioning in Amazon S3 is a way of keeping multiple variants of an object in the same bucket. A simple `GET` request retrieves the current version of an object. The following figure shows how `GET` returns the current version of the object, `photo.gif`.

![\[Illustration that shows how GET returns the current version of the object.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_GET_NoVersionID.png)


To retrieve a specific version, you have to specify its version ID. The following figure shows that a `GET versionId` request retrieves the specified version of the object (not necessarily the current one).

![\[Illustration that shows how a GET versionId request retrieves the specified version of the object.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_GET_Versioned.png)


You can retrieve object versions in Amazon S3 using the console, AWS SDKs, or REST API.

**Note**  
 To access object versions older than 300 versions, you must use the AWS CLI or the object's URL.

## Using the S3 console
<a name="retrieving-object-versions"></a>

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the **Buckets** list, choose the name of the bucket that contains the object.

1. In the **Objects** list, choose the name of the object.

1. Choose **Versions**.

   Amazon S3 shows all the versions for the object.

1. Select the check box next to the **Version ID** for the versions that you want to retrieve.

1. Choose **Actions**, choose **Download**, and save the object.

You also can view, download, and delete object versions in the object overview panel. For more information, see [Viewing object properties in the Amazon S3 console](view-object-properties.md).

**Important**  
You can undelete an object only if it was deleted as the latest (current) version. You can't undelete a previous version of an object that was deleted. For more information, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md).

## Using the AWS SDKs
<a name="retrieve-obj-version-sdks"></a>

The examples for uploading objects in nonversioned and versioning-enabled buckets are the same. However, for versioning-enabled buckets, Amazon S3 assigns a version number. Otherwise, the version number is null.

For examples of downloading objects using AWS SDKs for Java, .NET, and PHP, see [Downloading objects](https://docs.aws.amazon.com/AmazonS3/latest/userguide/download-objects.html).

For examples of listing the version of objects using AWS SDKs for .NET and Rust, see [List the version of objects in an Amazon S3 bucket](https://docs.aws.amazon.com/code-library/latest/ug/s3_example_s3_ListObjectVersions_section.html).

## Using the REST API
<a name="retrieve-obj-version-rest"></a>

**To retrieve a specific object version**

1. Set `versionId` to the ID of the version of the object that you want to retrieve.

1. Send a `GET Object versionId` request.

**Example — Retrieving a versioned object**  
The following request retrieves version `L4kqtJlcpXroDTDmpUMLUo` of `my-image.jpg`.  

```
1. GET /my-image.jpg?versionId=L4kqtJlcpXroDTDmpUMLUo HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

You can retrieve just the metadata of an object (not the content). For information, see [Retrieving the metadata of an object version](RetMetaOfObjVersion.md).

For information about restoring a previous object version, see [Restoring previous versions](RestoringPreviousVersions.md).

# Retrieving the metadata of an object version
<a name="RetMetaOfObjVersion"></a>

If you only want to retrieve the metadata of an object (and not its content), you use the `HEAD` operation. By default, you get the metadata of the most recent version. To retrieve the metadata of a specific object version, you specify its version ID.

**To retrieve the metadata of an object version**

1. Set `versionId` to the ID of the version of the object whose metadata you want to retrieve.

1. Send a `HEAD Object versionId` request.

**Example — Retrieving the metadata of a versioned object**  
The following request retrieves the metadata of version `3HL4kqCxf3vjVBH40Nrjfkd` of `my-image.jpg`.  

```
1. HEAD /my-image.jpg?versionId=3HL4kqCxf3vjVBH40Nrjfkd HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

The following shows a sample response.

```
 1. HTTP/1.1 200 OK
 2. x-amz-id-2: ef8yU9AS1ed4OpIszj7UDNEHGran
 3. x-amz-request-id: 318BC8BC143432E5
 4. x-amz-version-id: 3HL4kqtJlcpXroDTDmjVBH40Nrjfkd
 5. Date: Wed, 28 Oct 2009 22:32:00 GMT
 6. Last-Modified: Sun, 1 Jan 2006 12:00:00 GMT
 7. ETag: "fba9dede5f27731c9771645a39863328"
 8. Content-Length: 434234
 9. Content-Type: text/plain
10. Connection: close
11. Server: AmazonS3
```

# Restoring previous versions
<a name="RestoringPreviousVersions"></a>

You can use versioning to retrieve previous versions of an object. There are two approaches to doing so:
+ Copy a previous version of the object into the same bucket.

  The copied object becomes the current version of that object and all object versions are preserved.
+ Permanently delete the current version of the object.

  When you delete the current object version, you, in effect, turn the previous version into the current version of that object.

Because all object versions are preserved, you can make any earlier version the current version by copying a specific version of the object into the same bucket. In the following figure, the source object (ID = 111111) is copied into the same bucket. Amazon S3 supplies a new ID (88778877) and it becomes the current version of the object. So, the bucket has both the original object version (111111) and its copy (88778877). For more information about getting a previous version and then uploading it to make it the current version, see [Retrieving object versions from a versioning-enabled bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RetrievingObjectVersions.html) and [Uploading objects](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html).

![\[Illustration that shows copying a specific version of an object into the same bucket to make it the current version.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_COPY2.png)


A subsequent `GET` retrieves version 88778877.

The following figure shows how deleting the current version (121212) of an object leaves the previous version (111111) as the current object. For more information about deleting an object, see [Deleting a single object](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-objects.html).

![\[Illustration that shows deleting the current version of an object leaves the previous version as the current object.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_COPY_delete2.png)


A subsequent `GET` retrieves version 111111.

**Note**  
To restore object versions in batches, you can [use the `CopyObject` operation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/batch-ops-copy-object.html). The `CopyObject` operation copies each object that is specified in the manifest. However, be aware that objects aren't necessarily copied in the same order as they appear in the manifest. For versioned buckets, if preserving current/non-current version order is important, you should copy all non-current versions first. Then, after the first job is complete, copy the current versions in a subsequent job.

## To restore previous object versions
<a name="restoring-obj-version-version-enabled-bucket-examples"></a>

For more guidance on restoring deleted objects, see [How can I retrieve an Amazon S3 object that was deleted in a versioning-enabled bucket?](https://repost.aws/knowledge-center/s3-undelete-configuration) in the AWS re:Post Knowledge Center.

### Using the S3 console
<a name="retrieving-object-versions"></a>

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the **Buckets** list, choose the name of the bucket that contains the object.

1. In the **Objects** list, choose the name of the object.

1. Choose **Versions**.

   Amazon S3 shows all the versions for the object.

1. Select the check box next to the **Version ID** for the versions that you want to retrieve.

1. Choose **Actions**, choose **Download**, and save the object.

You also can view, download, and delete object versions in the object overview panel. For more information, see [Viewing object properties in the Amazon S3 console](view-object-properties.md).

**Important**  
You can undelete an object only if it was deleted as the latest (current) version. You can't undelete a previous version of an object that was deleted. For more information, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md).

### Using the AWS SDKs
<a name="restoring-obj-version-version-enabled-bucket-sdks"></a>

For information about using other AWS SDKs, see the [AWS Developer Center](https://aws.amazon.com/code/). 

------
#### [ Python ]

The following Python code example restores a versioned object's previous version by deleting all versions that occurred after the specified rollback version.

```
def rollback_object(bucket, object_key, version_id):
    """
    Rolls back an object to an earlier version by deleting all versions that
    occurred after the specified rollback version.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket: The bucket that holds the object to roll back.
    :param object_key: The object to roll back.
    :param version_id: The version ID to roll back to.
    """
    # Versions must be sorted by last_modified date because delete markers are
    # at the end of the list even when they are interspersed in time.
    versions = sorted(
        bucket.object_versions.filter(Prefix=object_key),
        key=attrgetter("last_modified"),
        reverse=True,
    )

    logger.debug(
        "Got versions:\n%s",
        "\n".join(
            [
                f"\t{version.version_id}, last modified {version.last_modified}"
                for version in versions
            ]
        ),
    )

    if version_id in [ver.version_id for ver in versions]:
        print(f"Rolling back to version {version_id}")
        for version in versions:
            if version.version_id != version_id:
                version.delete()
                print(f"Deleted version {version.version_id}")
            else:
                break

        print(f"Active version is now {bucket.Object(object_key).version_id}")
    else:
        raise KeyError(
            f"{version_id} was not found in the list of versions for " f"{object_key}."
        )
```

------

# Deleting object versions from a versioning-enabled bucket
<a name="DeletingObjectVersions"></a>

You can delete object versions from Amazon S3 buckets whenever you want. You can also define lifecycle configuration rules for objects that have a well-defined lifecycle to request Amazon S3 to expire current object versions or permanently remove noncurrent object versions. When your bucket has versioning enabled or the versioning is suspended, the lifecycle configuration actions work as follows:
+ The `Expiration` action applies to the current object version. Instead of deleting the current object version, Amazon S3 retains the current version as a noncurrent version by adding a *delete marker*, which then becomes the current version.
+ The `NoncurrentVersionExpiration` action applies to noncurrent object versions, and Amazon S3 permanently removes these object versions. You cannot recover permanently removed objects.

For more information about S3 Lifecycle, see [Managing the lifecycle of objects](object-lifecycle-mgmt.md) and [Examples of S3 Lifecycle configurations](lifecycle-configuration-examples.md).

To see how many current and noncurrent object versions that your buckets have, you can use Amazon S3 Storage Lens metrics. S3 Storage Lens is a cloud-storage analytics feature that you can use to gain organization-wide visibility into object-storage usage and activity. For more information, see [ Using S3 Storage Lens to optimize your storage costs](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-lens-optimize-storage.html?icmpid=docs_s3_user_guide_DeletingObjectVersions.html). For a complete list of metrics, see [ S3 Storage Lens metrics glossary](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens_metrics_glossary.html?icmpid=docs_s3_user_guide_replication.html).

**Note**  
 Normal Amazon S3 rates apply for every version of an object that is stored and transferred, including noncurrent object versions. For more information, see [Amazon S3 pricing](https://aws.amazon.com/s3/pricing/). 

## Delete request use cases
<a name="delete-request-use-cases"></a>

A `DELETE` request has the following use cases:
+ When versioning is enabled, a simple `DELETE` cannot permanently delete an object. (A simple `DELETE` request is a request that doesn't specify a version ID.) Instead, Amazon S3 inserts a delete marker in the bucket, and that marker becomes the current version of the object with a new ID. 

  When you try to `GET` an object whose current version is a delete marker, Amazon S3 behaves as though the object has been deleted (even though it has not been erased) and returns a 404 error. For more information, see [Working with delete markers](DeleteMarker.md).

  The following figure shows that a simple `DELETE` does not actually remove the specified object. Instead, Amazon S3 inserts a delete marker.  
![\[Illustration that shows a delete marker insertion.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled.png)
+ To delete versioned objects permanently, you must use `DELETE Object versionId`.

  The following figure shows that deleting a specified object version permanently removes that object.  
![\[Diagram that shows how DELETE Object versionId permanently deletes a specific object version.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled2.png)

## To delete object versions
<a name="delete-object-version"></a>

You can delete object versions in Amazon S3 using the console, AWS SDKs, the REST API, or the AWS Command Line Interface.

### Using the S3 console
<a name="deleting-object-versions"></a>

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the **Buckets** list, choose the name of the bucket that contains the object.

1. In the **Objects** list, choose the name of the object.

1. Choose **Versions**.

   Amazon S3 shows all the versions for the object.

1. Select the check box next to the **Version ID** for the versions that you want to permanently delete.

1. Choose **Delete**.

1. In **Permanently delete objects?**, enter **permanently delete**.
**Warning**  
When you permanently delete an object version, the action cannot be undone.

1. Choose **Delete objects**.

   Amazon S3 deletes the object version.

### Using the AWS SDKs
<a name="delete-obj-version-version-enabled-bucket-sdks"></a>

For examples of deleting objects using the AWS SDKs for Java, .NET, and PHP, see [Deleting Amazon S3 objects](DeletingObjects.md). The examples for deleting objects in nonversioned and versioning-enabled buckets are the same. However, for versioning-enabled buckets, Amazon S3 assigns a version number. Otherwise, the version number is null. 

For information about using other AWS SDKs, see the [AWS Developer Center](https://aws.amazon.com/code/). 

------
#### [ Python ]

The following Python code example permanently deletes a versioned object by deleting all of its versions.

```
def permanently_delete_object(bucket, object_key):
    """
    Permanently deletes a versioned object by deleting all of its versions.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket: The bucket that contains the object.
    :param object_key: The object to delete.
    """
    try:
        bucket.object_versions.filter(Prefix=object_key).delete()
        logger.info("Permanently deleted all versions of object %s.", object_key)
    except ClientError:
        logger.exception("Couldn't delete all versions of %s.", object_key)
        raise
```

------

### Using the REST API
<a name="delete-obj-version-enabled-bucket-rest"></a>

**To delete a specific version of an object**
+ In a `DELETE`, specify a version ID.

**Example — Deleting a specific version**  
The following example deletes version `UIORUnfnd89493jJFJ` of `photo.gif`.  

```
1. DELETE /photo.gif?versionId=UIORUnfnd89493jJFJ HTTP/1.1 
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 12 Oct 2009 17:50:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:xQE0diMbLRepdf3YB+FIEXAMPLE=
5. Content-Type: text/plain
6. Content-Length: 0
```

### Using the AWS CLI
<a name="delete-obj-version-enabled-bucket-cli"></a>

The following command deletes an object named test.txt from a bucket named `amzn-s3-demo-bucket1`. To remove a specific version of an object, you must be the bucket owner and you must use the version Id subresource.

```
aws s3api delete-object --bucket amzn-s3-demo-bucket1 --key test.txt --version-id versionID
```

For more information about `delete-object` see [https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html) in the *AWS CLI Command Reference*.

For more information about deleting object versions, see the following topics:
+ [Working with delete markers](DeleteMarker.md)
+ [Removing delete markers to make an older version current](ManagingDelMarkers.md#RemDelMarker)
+ [Deleting an object from an MFA delete-enabled bucket](UsingMFADelete.md)

# Working with delete markers
<a name="DeleteMarker"></a>

A *delete marker* in Amazon S3 is a placeholder (or marker) for a versioned object that was specified in a simple `DELETE` request. A simple `DELETE` request is a request that doesn't specify a version ID. Because the object is in a versioning-enabled bucket, the object is not deleted. But the delete marker makes Amazon S3 behave as if the object is deleted. You can use an Amazon S3 API `DELETE` call on a delete marker. To do this, you must make the `DELETE` request by using an AWS Identity and Access Management (IAM) user or role with the appropriate permissions.

A delete marker has a *key name* (or *key*) and version ID like any other object. However, a delete marker differs from other objects in the following ways:
+ A delete marker doesn't have data associated with it.
+ A delete marker isn't associated with an access control list (ACL) value.
+ If you issue a `GET` request for a delete marker, the `GET` request doesn't retrieve anything because a delete marker has no data. Specifically, when your `GET` request doesn't specify a `versionId`, you get a 404 (Not Found) error.

Delete markers accrue a minimal charge for storage in Amazon S3. The storage size of a delete marker is equal to the size of the key name of the delete marker. A key name is a sequence of Unicode characters. The UTF-8 encoding for the key name adds 1‐4 bytes of storage to your bucket for each character in the name. Delete markers are stored in the S3 Standard storage class. 

If you want to find out how many delete markers you have and what storage class they're stored in, you can use Amazon S3 Storage Lens. For more information, see [Monitoring your storage activity and usage with Amazon S3 Storage Lens](storage_lens.md) and [Amazon S3 Storage Lens metrics glossary](storage_lens_metrics_glossary.md).

For more information about key names, see [Naming Amazon S3 objects](object-keys.md). For information about deleting a delete marker, see [Managing delete markers](ManagingDelMarkers.md). 

Only Amazon S3 can create a delete marker, and it does so whenever you send a `DeleteObject` request on an object in a versioning-enabled or suspended bucket. The object specified in the `DELETE` request is not actually deleted. Instead, the delete marker becomes the current version of the object. The object's key name (or key) becomes the key of the delete marker. 

When you get an object without specifying a `versionId` in your request, if its current version is a delete marker, Amazon S3 responds with the following:
+ A 404 (Not Found) error
+ A response header, `x-amz-delete-marker: true`

When you get an object by specifying a `versionId` in your request, if the specified version is a delete marker, Amazon S3 responds with the following:
+ A 405 (Method Not Allowed) error
+ A response header, `x-amz-delete-marker: true`
+ A response header, `Last-Modified: timestamp` (only when using the [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) or [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) API operations)

The `x-amz-delete-marker: true` response header tells you that the object accessed was a delete marker. This response header never returns `false`, because when the value is `false`, the current or specified version of the object is not a delete marker.

The `Last-Modified` response header provides the creation time of the delete markers.

The following figure shows how a `GetObject` API call on an object whose current version is a delete marker responds with a 404 (Not Found) error and the response header includes `x-amz-delete-marker: true`.

![\[Illustration that shows a GetObject call for a delete marker returning a 404 (Not Found) error.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_NoObjectFound.png)


If you make a `GetObject` call on an object by specifying a `versionId` in your request, and if the specified version is a delete marker, Amazon S3 responds with a 405 (Method Not Allowed) error and the response headers include `x-amz-delete-marker: true` and `Last-Modified: timestamp`.

![\[Illustration that shows a GetObject call for a delete marker returning a 405 (Method Not Allowed) error.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_NoObjectFound_405.png)


Even if overwritten, delete markers remain in your object versions. The only way to list delete markers (and other versions of an object) is by using a [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html) request. You can make this request in the AWS Management Console by listing your objects in an general purpose bucket and selecting **Show versions**. For more information, see [Listing objects in a versioning-enabled bucket](list-obj-version-enabled-bucket.md).

The following figure shows that a [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) or [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) request doesn't return objects whose current version is a delete marker.

![\[Illustration that shows how a ListObjectsV2 or ListObjects call doesn't return any delete markers.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_GETBucketwithDeleteMarkers.png)


# Managing delete markers
<a name="ManagingDelMarkers"></a>

## Configuring lifecycle to clean up expired delete markers automatically
<a name="LifecycleDelMarker"></a>

An expired object delete marker is one where all object versions are deleted and only a single delete marker remains. If the lifecycle configuration is set to delete current versions, or the `ExpiredObjectDeleteMarker` action is explicitly set, Amazon S3 removes the expired object’s delete marker. For an example, see [Removing expired object delete markers in a versioning-enabled bucket](lifecycle-configuration-examples.md#lifecycle-config-conceptual-ex7). 

## Removing delete markers to make an older version current
<a name="RemDelMarker"></a>

When you delete an object in a versioning-enabled bucket, all versions remain in the bucket, and Amazon S3 creates a delete marker for the object. To undelete the object, you must delete this delete marker. For more information about versioning and delete markers, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md).

To delete a delete marker permanently, you must include its version ID in a `DeleteObject versionId` request. The following figure shows how a `DeleteObject versionId` request permanently removes a delete marker.

![\[Illustration that shows a delete marker deletion using its version ID.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_deleteMarkerVersioned.png)


The effect of removing the delete marker is that a simple `GET` request will now retrieve the current version ID (121212) of the object. 

**Note**  
If you use a `DeleteObject` request where the current version is a delete marker (without specifying the version ID of the delete marker), Amazon S3 does not delete the delete marker, but instead `PUTs` another delete marker.

To delete a delete marker with a `NULL` version ID, you must pass the `NULL` as the version ID in the `DeleteObject` request. The following figure shows how a simple `DeleteObject` request made without a version ID where the current version is a delete marker, removes nothing, but instead adds an additional delete marker with a unique version ID (7498372).

![\[Illustration that shows a delete marker deletion using a NULL version ID.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_deleteMarker.png)


## Using the S3 console
<a name="undelete-objects"></a>

Use the following steps to recover deleted objects that are not folders from your S3 bucket, including objects that are within those folders. 

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the **Buckets** list, choose the name of the bucket that you want.

1. To see a list of the **versions** of the objects in the bucket, choose the **List versions** switch. You'll be able to see the delete markers for deleted objects. 

   

1. To undelete an object, you must delete the delete marker. Select the check box next to the **delete marker** of the object to recover, and then choose **Delete**.

1. Confirm the deletion on the **Delete objects** page.

   1. For **Permanently delete objects?** enter **permanently delete**.

   1. Choose **Delete objects**.

**Note**  
You can't use the Amazon S3 console to undelete folders. You must use the AWS CLI or SDK. For examples, see [ How can I retrieve an Amazon S3 object that was deleted in a versioning-enabled bucket?](https://aws.amazon.com/premiumsupport/knowledge-center/s3-undelete-configuration/) in the AWS Knowledge Center.

## Using the REST API
<a name="delete-marker-rest-api"></a>

**To permanently remove a delete marker**

1. Set `versionId` to the ID of the version to the delete marker you want to remove.

1. Send a `DELETE Object versionId` request.

**Example — Removing a delete marker**  
The following example removes the delete marker for `photo.gif` version 4857693.  

```
1. DELETE /photo.gif?versionId=4857693 HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

When you delete a delete marker, Amazon S3 includes the following in the response.

```
1. 204 NoContent 
2. x-amz-version-id: versionID 
3. x-amz-delete-marker: true
```

## Using the AWS SDKs
<a name="remove-delete-marker-examples-sdk"></a>

For information about using other AWS SDKs, see the [AWSDeveloper Center](https://aws.amazon.com/code/).

------
#### [ Python ]

The following Python code example demonstrates how to remove a delete marker from an object and thus makes the most recent non-current version, the current version of the object.

```
def revive_object(bucket, object_key):
    """
    Revives a versioned object that was deleted by removing the object's active
    delete marker.
    A versioned object presents as deleted when its latest version is a delete marker.
    By removing the delete marker, we make the previous version the latest version
    and the object then presents as *not* deleted.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket: The bucket that contains the object.
    :param object_key: The object to revive.
    """
    # Get the latest version for the object.
    response = s3.meta.client.list_object_versions(
        Bucket=bucket.name, Prefix=object_key, MaxKeys=1
    )

    if "DeleteMarkers" in response:
        latest_version = response["DeleteMarkers"][0]
        if latest_version["IsLatest"]:
            logger.info(
                "Object %s was indeed deleted on %s. Let's revive it.",
                object_key,
                latest_version["LastModified"],
            )
            obj = bucket.Object(object_key)
            obj.Version(latest_version["VersionId"]).delete()
            logger.info(
                "Revived %s, active version is now %s  with body '%s'",
                object_key,
                obj.version_id,
                obj.get()["Body"].read(),
            )
        else:
            logger.warning(
                "Delete marker is not the latest version for %s!", object_key
            )
    elif "Versions" in response:
        logger.warning("Got an active version for %s, nothing to do.", object_key)
    else:
        logger.error("Couldn't get any version info for %s.", object_key)
```

------

# Deleting an object from an MFA delete-enabled bucket
<a name="UsingMFADelete"></a>

When you configure MFA delete, only the root user can permanently delete object versions or change the versioning configuration on your S3 bucket. You must use an MFA device to authenticate the root user to perform the delete action.

If a bucket's versioning configuration is MFA delete enabled, the bucket owner must include the `x-amz-mfa` request header in requests to permanently delete an object version or change the versioning state of the bucket. Requests that include `x-amz-mfa` must use HTTPS.

The header's value is the concatenation of your authentication device's serial number, a space, and the authentication code displayed on it. If you don't include this request header, the request fails.

When using the AWS CLI include the same information as the value of the `mfa` parameter.

For more information about authentication devices, see [Multi-factor Authentication](https://aws.amazon.com/iam/details/mfa/).

For more information about enabling MFA delete, see [Configuring MFA delete](MultiFactorAuthenticationDelete.md).

**Note**  
Deleting an object in a versioning-enabled bucket that is MFA delete enabled is not available through the AWS Management Console.

## Using the AWS CLI
<a name="MFADeleteCLI"></a>

To delete an object in a versioning-enabled bucket that is MFA delete enabled, use the following command. When you use the following example command, replace the `user input placeholders` with your own information.

```
 aws s3api delete-object --bucket amzn-s3-demo-bucket --key OBJECT-KEY --version-id "VERSION ID" --mfa "MFA_DEVICE_SERIAL_NUMBER MFA_DEVICE_CODE"						
```

## Using the REST API
<a name="MFADeleteAPI"></a>

The following example deletes `my-image.jpg` (with the specified version), which is in a bucket configured with MFA delete enabled. 

For more information, see [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html) in the Amazon Simple Storage Service API Reference

```
1. DELETE /my-image.jpg?versionId=3HL4kqCxf3vjVBH40Nrjfkd HTTPS/1.1
2. Host: bucketName.s3.amazonaws.com
3. x-amz-mfa: 20899872 301749
4. Date: Wed, 28 Oct 2009 22:32:00 GMT
5. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

# Configuring versioned object permissions
<a name="VersionedObjectPermissionsandACLs"></a>

Permissions for objects in Amazon S3 are set at the version level. Each version has its own object owner. The AWS account that creates the object version is the owner. So, you can set different permissions for different versions of the same object. To do so, you must specify the version ID of the object whose permissions you want to set in a `PUT Object versionId acl` request. For a detailed description and instructions on using ACLs, see [Identity and Access Management for Amazon S3](security-iam.md).

**Example — Setting permissions for an object version**  
The following request sets the permission of the grantee with canonical user ID *b4bf1b36f9716f094c3079dcf5ac9982d4f2847de46204d47448bc557fb5ac2a*, to `FULL_CONTROL` on the key, `my-image.jpg`, version ID, `3HL4kqtJvjVBH40Nrjfkd`.  

```
 1. PUT /my-image.jpg?acl&versionId=3HL4kqtJvjVBH40Nrjfkd HTTP/1.1
 2. Host: bucket.s3.amazonaws.com
 3. Date: Wed, 28 Oct 2009 22:32:00 GMT
 4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
 5. Content-Length: 124
 6.  
 7. <AccessControlPolicy>
 8.   <Owner>
 9.     <ID>75cc57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a</ID>
10.   </Owner>
11.   <AccessControlList>
12.     <Grant>
13.       <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
14.         <ID>a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9</ID>
15.       </Grantee>
16.       <Permission>FULL_CONTROL</Permission>
17.     </Grant>
18.   </AccessControlList>
19.   </AccessControlPolicy>
```

Likewise, to get the permissions of a specific object version, you must specify its version ID in a `GET Object versionId acl` request. You need to include the version ID because, by default, `GET Object acl` returns the permissions of the current version of the object. 

**Example — Retrieving the permissions for a specified object version**  
In the following example, Amazon S3 returns the permissions for the key, `my-image.jpg`, version ID, `DVBH40Nr8X8gUMLUo`.  

```
1. GET /my-image.jpg?versionId=DVBH40Nr8X8gUMLUo&acl HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU
```

For more information, see [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html) in the *Amazon Simple Storage Service API Reference*.

# Working with objects in a versioning-suspended bucket
<a name="VersionSuspendedBehavior"></a>

In Amazon S3, you can suspend versioning to stop accruing new versions of the same object in a bucket. You might do this because you only want a single version of an object in a bucket. Or, you might not want to accrue charges for multiple versions. 

When you suspend versioning, existing objects in your bucket do not change. What changes is how Amazon S3 handles objects in future requests. The topics in this section explain various object operations in a versioning-suspended bucket, including adding, retrieving, and deleting objects.

For more information about S3 Versioning, see [Retaining multiple versions of objects with S3 Versioning](Versioning.md). For more information about retrieving object versions, see [Retrieving object versions from a versioning-enabled bucket](RetrievingObjectVersions.md).

**Topics**
+ [

# Adding objects to versioning-suspended buckets
](AddingObjectstoVersionSuspendedBuckets.md)
+ [

# Retrieving objects from versioning-suspended buckets
](RetrievingObjectsfromVersioningSuspendedBuckets.md)
+ [

# Deleting objects from versioning-suspended buckets
](DeletingObjectsfromVersioningSuspendedBuckets.md)

# Adding objects to versioning-suspended buckets
<a name="AddingObjectstoVersionSuspendedBuckets"></a>

You can add objects to versioning-suspended buckets in Amazon S3 to create the object with a null version ID or overwrite any object version with a matching version ID.

After you suspend versioning on a bucket, Amazon S3 automatically adds a `null` version ID to every subsequent object stored thereafter (using `PUT`, `POST`, or `CopyObject`) in that bucket.

The following figure shows how Amazon S3 adds the version ID of `null` to an object when it is added to a version-suspended bucket.

![\[Amazon S3 adding the version ID of null to an object graphic.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_PUT_versionSuspended.png)


If a null version is already in the bucket and you add another object with the same key, the added object overwrites the original null version. 

If there are versioned objects in the bucket, the version you `PUT` becomes the current version of the object. The following figure shows how adding an object to a bucket that contains versioned objects does not overwrite the object already in the bucket. 

In this case, version 111111 was already in the bucket. Amazon S3 attaches a version ID of null to the object being added and stores it in the bucket. Version 111111 is not overwritten.

![\[Amazon S3 adding the version ID of null to an object without overwriting version 111111 graphic.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_PUT_versionSuspended3.png)


If a null version already exists in a bucket, the null version is overwritten, as shown in the following figure.

![\[Amazon S3 adding the version ID of null to an object while overwriting the original contents graphic.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_PUT_versionSuspended4.png)


Although the key and version ID (`null`) of the null version are the same before and after the `PUT`, the contents of the null version originally stored in the bucket are replaced by the contents of the object `PUT` into the bucket.

# Retrieving objects from versioning-suspended buckets
<a name="RetrievingObjectsfromVersioningSuspendedBuckets"></a>

A `GET Object` request returns the current version of an object whether you've enabled versioning on a bucket or not. The following figure shows how a simple `GET` returns the current version of an object.

![\[Illustration that shows how a simple GET returns the current version of an object.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_GET_suspended.png)


# Deleting objects from versioning-suspended buckets
<a name="DeletingObjectsfromVersioningSuspendedBuckets"></a>

You can delete objects from versioning-suspended buckets to remove an object with a null version ID.

If versioning is suspended for a bucket, a `DELETE` request:
+ Can only remove an object whose version ID is `null`.
+ Doesn't remove anything if there isn't a null version of the object in the bucket.
+ Inserts a delete marker into the bucket.

If bucket versioning is suspended, the operation removes the object that has a null `versionId`. If a version ID exists, Amazon S3 inserts a delete marker that becomes the current version of the object. The following figure shows how a simple `DELETE` removes a null version and Amazon S3 inserts a delete marker in its place instead with a `null` version ID.

![\[Illustration that shows a simple delete to remove an object with a NULL version ID.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningSuspended.png)


To permanently delete an object that has a `versionId`, you must include the object’s `versionId` in the request. Since a delete marker doesn't contain any content, you'll lose the content for the `null` version when a delete marker replaces it.

The following figure shows a bucket that doesn't have a null version. In this case, the `DELETE` removes nothing. Instead, Amazon S3 just inserts a delete marker.

![\[Illustration that shows a delete marker insertion.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningSuspendedNoNull.png)


Even in a versioning-suspended bucket, the bucket owner can permanently delete a specified version by including the version ID in the `DELETE` request, unless permissions for the `DELETE` request have been explicitly denied. For example, to deny deletion of any objects that have a `null` version ID, you must explicitly deny the `s3:DeleteObject` and `s3:DeleteObjectVersions` permissions.

The following figure shows that deleting a specified object version permanently removes that version of the object. Only the bucket owner can delete a specified object version.

![\[Illustration that shows a permanent object deletion using a specified version ID.\]](http://docs.aws.amazon.com/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled2.png)


# Troubleshooting versioning
<a name="troubleshooting-versioning"></a>

The following topics can help you troubleshoot some common Amazon S3 versioning issues.

**Topics**
+ [

## I want to recover objects that were accidentally deleted in a versioning-enabled bucket
](#recover-objects)
+ [

## I want to permanently delete versioned objects
](#delete-objects-permanent)
+ [

## I'm experiencing performance degradation after enabling bucket versioning
](#performance-degradation)

## I want to recover objects that were accidentally deleted in a versioning-enabled bucket
<a name="recover-objects"></a>

In general, when object versions are deleted from S3 buckets, there is no way for Amazon S3 to recover them. However, if you have enabled S3 Versioning on your S3 bucket, a `DELETE` request that doesn't specify a version ID cannot permanently delete an object. Instead, a delete marker is added as a placeholder. This delete marker becomes the current version of the object. 

To verify whether your deleted objects are permanently deleted or temporarily deleted (with a delete marker in their place), do the following: 

1. Sign in to the AWS Management Console and open the Amazon S3 console at [https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/).

1. In the left navigation pane, choose **Buckets**.

1. In the **Buckets** list, choose the name of the bucket that contains the object.

1. In the **Objects** list, Turn on the **Show versions** toggle to the right of the search bar, and then search for the deleted object in the search bar. This toggle is available only if versioning was previously enabled on the bucket.

   You can also use [S3 Inventory to search for deleted objects](storage-inventory.md#storage-inventory-contents).

1. If you can't find the object after toggling **Show versions** or creating an inventory report, and you also cannot find a [delete marker](DeleteMarker.md) of the object, the deletion is permanent and the object cannot be recovered.



You can also verify a deleted object's status by using the `HeadObject` API operation from the AWS Command Line Interface (AWS CLI). To do so, use the following `head-object` command and replace the `user input placeholders` with your own information: 

`aws s3api head-object --bucket amzn-s3-demo-bucket --key index.html`

If you run the `head-object` command on a versioned object whose current version is a delete marker, you will receive a 404 Not Found error. For example: 

An error occurred (404) when calling the HeadObject operation: Not Found

If you run the `head-object` command on a versioned object and provide the object's version ID, Amazon S3 retrieves the object's metadata, confirming that the object still exists and is not permanently deleted.

`aws s3api head-object --bucket amzn-s3-demo-bucket --key index.html --version-id versionID`

```
{
"AcceptRanges": "bytes",
"ContentType": "text/html",
"LastModified": "Thu, 16 Apr 2015 18:19:14 GMT",
"ContentLength": 77,
"VersionId": "Zg5HyL7m.eZU9iM7AVlJkrqAiE.0UG4q",
"ETag": "\"30a6ec7e1a9ad79c203d05a589c8b400\"",
"Metadata": {}
}
```

If the object is found and the newest version is a delete marker, the previous version of the object still exists. Because the delete marker is the current version of the object, you can recover the object by deleting the delete marker. 

After you permanently remove the delete marker, the second newest version of the object becomes the current version of the object, making your object available once again. For a visual depiction of how objects are recovered, see [Removing delete markers](ManagingDelMarkers.md#RemDelMarker).

To remove a specific version of an object, you must be the bucket owner. To delete a delete marker permanently, you must include its version ID in a `DeleteObject` request. To delete the delete marker, use the following command, and replace the `user input placeholders` with your own information: 

****  
`aws s3api delete-object --bucket amzn-s3-demo-bucket --key index.html --version-id versionID`

For more information about the `delete-object` command, see [https://docs.aws.amazon.com//cli/latest/reference/s3api/delete-object.html](https://docs.aws.amazon.com//cli/latest/reference/s3api/delete-object.html) in the *AWS CLI Command Reference*. For more information about permanently deleting delete markers, see [Managing delete markers](ManagingDelMarkers.md).

## I want to permanently delete versioned objects
<a name="delete-objects-permanent"></a>

In a versioning-enabled bucket, a `DELETE` request without a version ID cannot permanently delete an object. Instead, such a request inserts a delete marker.

To permanently delete versioned objects, you can choose from the following methods:
+ Create an S3 Lifecycle rule to permanently delete noncurrent versions. To permanently delete noncurrent versions, select **Permanently delete noncurrent versions of objects**, and then enter a number under **Days after objects become noncurrent**. You can optionally specify the number of newer versions to retain by entering a value under **Number of newer versions to retain**. For more information about creating this rule, see [Setting an S3 Lifecycle configuration](how-to-set-lifecycle-configuration-intro.md).
+ Delete a specified version by including the version ID in the `DELETE` request. For more information, see [How to delete versioned objects permanently](DeletingObjectVersions.md#delete-request-use-cases).
+ Create a lifecycle rule to expire current versions. To expire current versions of objects, select **Expire current versions of objects**, and then add a number under **Days after object creation**. For more information about creating this lifecycle rule, see [Setting an S3 Lifecycle configuration](how-to-set-lifecycle-configuration-intro.md).
+ To permanently delete all versioned objects and delete markers, create two lifecycle rules: one to expire current versions and permanently delete noncurrent versions of objects, and the other to delete expired object delete markers.

In a versioning-enabled bucket, a `DELETE` request that doesn't specify a version ID can remove only objects with a `NULL` version ID. If the object was uploaded when versioning was enabled, a `DELETE` request that doesn't specify a version ID creates a delete marker of that object.

**Note**  
For S3 Object Lock-enabled buckets, a `DELETE` object request with a protected object version ID causes a 403 Access Denied error. A `DELETE` object request without a version ID adds a delete marker as the newest version of the object with a 200 OK response. Objects protected by Object Lock cannot be permanently deleted until their retention periods and legal holds are removed. For more information, see [How S3 Object Lock works](object-lock.md#object-lock-overview).

## I'm experiencing performance degradation after enabling bucket versioning
<a name="performance-degradation"></a>

Performance degradation can occur on versioning-enabled buckets if there are too many delete markers or versioned objects, and if best practices aren't followed.

**Too many delete markers**  
After you enable versioning on a bucket, a `DELETE` request without a version ID made to an object creates a delete marker with a unique version ID. Lifecycle configurations with an **Expire current versions of objects** rule add a delete marker with a unique version ID to every object. Excessive delete markers can reduce performance in the bucket.

When versioning is suspended on a bucket, Amazon S3 marks the version ID as `NULL` on newly created objects. An expiration action in a versioning-suspended bucket causes Amazon S3 to create a delete marker with `NULL` as the version ID. In a versioning-suspended bucket, a `NULL` delete marker is created for any delete request. These `NULL` delete markers are also called expired object delete markers when all object versions are deleted and only a single delete marker remains. If too many `NULL` delete markers accumulate, performance degradation in the bucket occurs.

**Too many versioned objects**  
If a versioning-enabled bucket contains objects with millions of versions, an increase in 503 Service Unavailable errors can occur. If you notice a significant increase in the number of HTTP 503 Service Unavailable responses received for `PUT` or `DELETE` object requests to a versioning-enabled bucket, you might have one or more objects in the bucket with millions of versions. When you have objects with millions of versions, Amazon S3 automatically throttles requests to the bucket. Throttling requests protects your bucket from an excessive amount of request traffic, which could potentially impede other requests made to the same bucket. 

To determine which objects have millions of versions, use S3 Inventory. S3 Inventory generates a report that provides a flat file list of the objects in a bucket. For more information, see [Cataloging and analyzing your data with S3 Inventory](storage-inventory.md).

To verify if there are high number of versioned objects in the bucket, use S3 Storage Lens metrics to view the **Current version object count**, **Noncurrent version object count**, and **Delete marker object count**. For more information about Storage Lens metrics, see [Amazon S3 Storage Lens metrics glossary](storage_lens_metrics_glossary.md).

The Amazon S3 team encourages customers to investigate applications that repeatedly overwrite the same object, potentially creating millions of versions for that object, to determine whether the application is working as intended. For instance, an application overwriting the same object every minute for a week can create over ten thousand versions. We recommend storing less than one hundred thousand versions for each object. If you have a use case that requires millions of versions for one or more objects, contact the AWS Support team for assistance with determining a better solution.

**Best practices**  
To prevent versioning-related performance degradation issues, we recommend that you employ the following best practices:
+ Enable a lifecycle rule to expire the previous versions of objects. For example, you can create a lifecycle rule to expire noncurrent versions after 30 days of the object being noncurrent. You can also retain multiple noncurrent versions if you don't want to delete all of them. For more information, see [Setting an S3 Lifecycle configuration](how-to-set-lifecycle-configuration-intro.md).
+ Enable a lifecycle rule to delete expired object delete markers that don't have associated data objects in the bucket. For more information, see [Removing expired object delete markers](lifecycle-configuration-examples.md#lifecycle-config-conceptual-ex7).

For additional Amazon S3 performance-optimization best practices, see [Best practices design patterns](optimizing-performance.md).