Configure AWS S3 Bucket Versioning

The aws:s3/bucketVersioningV2:BucketVersioningV2 resource, part of the Pulumi AWS provider, controls versioning behavior on an S3 bucket: enabling, disabling, or suspending version creation. This guide focuses on three capabilities: enabling versioning for object history, disabling versioning to stop new versions, and coordinating object creation with versioning state.

This resource configures versioning on existing S3 buckets. Objects that need version IDs may reference this resource to ensure versioning is active before creation. The examples are intentionally small. Combine them with your own bucket and object configurations.

Enable versioning to preserve object history

Teams protecting against accidental deletions or overwrites enable versioning to preserve every version of every object.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.s3.Bucket("example", {bucket: "example-bucket"});
const exampleBucketAcl = new aws.s3.BucketAcl("example", {
    bucket: example.id,
    acl: "private",
});
const versioningExample = new aws.s3.BucketVersioning("versioning_example", {
    bucket: example.id,
    versioningConfiguration: {
        status: "Enabled",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.s3.Bucket("example", bucket="example-bucket")
example_bucket_acl = aws.s3.BucketAcl("example",
    bucket=example.id,
    acl="private")
versioning_example = aws.s3.BucketVersioning("versioning_example",
    bucket=example.id,
    versioning_configuration={
        "status": "Enabled",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := s3.NewBucket(ctx, "example", &s3.BucketArgs{
			Bucket: pulumi.String("example-bucket"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketAcl(ctx, "example", &s3.BucketAclArgs{
			Bucket: example.ID(),
			Acl:    pulumi.String("private"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketVersioning(ctx, "versioning_example", &s3.BucketVersioningArgs{
			Bucket: example.ID(),
			VersioningConfiguration: &s3.BucketVersioningVersioningConfigurationArgs{
				Status: pulumi.String("Enabled"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.S3.Bucket("example", new()
    {
        BucketName = "example-bucket",
    });

    var exampleBucketAcl = new Aws.S3.BucketAcl("example", new()
    {
        Bucket = example.Id,
        Acl = "private",
    });

    var versioningExample = new Aws.S3.BucketVersioning("versioning_example", new()
    {
        Bucket = example.Id,
        VersioningConfiguration = new Aws.S3.Inputs.BucketVersioningVersioningConfigurationArgs
        {
            Status = "Enabled",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.Bucket;
import com.pulumi.aws.s3.BucketArgs;
import com.pulumi.aws.s3.BucketAcl;
import com.pulumi.aws.s3.BucketAclArgs;
import com.pulumi.aws.s3.BucketVersioning;
import com.pulumi.aws.s3.BucketVersioningArgs;
import com.pulumi.aws.s3.inputs.BucketVersioningVersioningConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Bucket("example", BucketArgs.builder()
            .bucket("example-bucket")
            .build());

        var exampleBucketAcl = new BucketAcl("exampleBucketAcl", BucketAclArgs.builder()
            .bucket(example.id())
            .acl("private")
            .build());

        var versioningExample = new BucketVersioning("versioningExample", BucketVersioningArgs.builder()
            .bucket(example.id())
            .versioningConfiguration(BucketVersioningVersioningConfigurationArgs.builder()
                .status("Enabled")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:s3:Bucket
    properties:
      bucket: example-bucket
  exampleBucketAcl:
    type: aws:s3:BucketAcl
    name: example
    properties:
      bucket: ${example.id}
      acl: private
  versioningExample:
    type: aws:s3:BucketVersioning
    name: versioning_example
    properties:
      bucket: ${example.id}
      versioningConfiguration:
        status: Enabled

When you set status to “Enabled”, S3 begins creating a new version for every PUT operation. Existing objects remain accessible, and previous versions can be retrieved or restored. AWS recommends waiting 15 minutes after enabling versioning before issuing write operations on objects in the bucket.

Disable versioning to stop creating new versions

When versioning is no longer needed, you can disable it to stop creating new versions while preserving existing ones.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.s3.Bucket("example", {bucket: "example-bucket"});
const exampleBucketAcl = new aws.s3.BucketAcl("example", {
    bucket: example.id,
    acl: "private",
});
const versioningExample = new aws.s3.BucketVersioning("versioning_example", {
    bucket: example.id,
    versioningConfiguration: {
        status: "Disabled",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.s3.Bucket("example", bucket="example-bucket")
example_bucket_acl = aws.s3.BucketAcl("example",
    bucket=example.id,
    acl="private")
versioning_example = aws.s3.BucketVersioning("versioning_example",
    bucket=example.id,
    versioning_configuration={
        "status": "Disabled",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := s3.NewBucket(ctx, "example", &s3.BucketArgs{
			Bucket: pulumi.String("example-bucket"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketAcl(ctx, "example", &s3.BucketAclArgs{
			Bucket: example.ID(),
			Acl:    pulumi.String("private"),
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketVersioning(ctx, "versioning_example", &s3.BucketVersioningArgs{
			Bucket: example.ID(),
			VersioningConfiguration: &s3.BucketVersioningVersioningConfigurationArgs{
				Status: pulumi.String("Disabled"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.S3.Bucket("example", new()
    {
        BucketName = "example-bucket",
    });

    var exampleBucketAcl = new Aws.S3.BucketAcl("example", new()
    {
        Bucket = example.Id,
        Acl = "private",
    });

    var versioningExample = new Aws.S3.BucketVersioning("versioning_example", new()
    {
        Bucket = example.Id,
        VersioningConfiguration = new Aws.S3.Inputs.BucketVersioningVersioningConfigurationArgs
        {
            Status = "Disabled",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.Bucket;
import com.pulumi.aws.s3.BucketArgs;
import com.pulumi.aws.s3.BucketAcl;
import com.pulumi.aws.s3.BucketAclArgs;
import com.pulumi.aws.s3.BucketVersioning;
import com.pulumi.aws.s3.BucketVersioningArgs;
import com.pulumi.aws.s3.inputs.BucketVersioningVersioningConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Bucket("example", BucketArgs.builder()
            .bucket("example-bucket")
            .build());

        var exampleBucketAcl = new BucketAcl("exampleBucketAcl", BucketAclArgs.builder()
            .bucket(example.id())
            .acl("private")
            .build());

        var versioningExample = new BucketVersioning("versioningExample", BucketVersioningArgs.builder()
            .bucket(example.id())
            .versioningConfiguration(BucketVersioningVersioningConfigurationArgs.builder()
                .status("Disabled")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:s3:Bucket
    properties:
      bucket: example-bucket
  exampleBucketAcl:
    type: aws:s3:BucketAcl
    name: example
    properties:
      bucket: ${example.id}
      acl: private
  versioningExample:
    type: aws:s3:BucketVersioning
    name: versioning_example
    properties:
      bucket: ${example.id}
      versioningConfiguration:
        status: Disabled

Setting status to “Disabled” stops S3 from creating new versions for subsequent writes. Existing versions remain in the bucket and continue to consume storage. To remove old versions, you must delete them explicitly or configure lifecycle policies.

Coordinate object creation with versioning enablement

Applications that need to reference specific version IDs must ensure versioning is enabled before creating objects.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.s3.Bucket("example", {bucket: "yotto"});
const exampleBucketVersioning = new aws.s3.BucketVersioning("example", {
    bucket: example.id,
    versioningConfiguration: {
        status: "Enabled",
    },
});
const exampleBucketObjectv2 = new aws.s3.BucketObjectv2("example", {
    bucket: exampleBucketVersioning.id,
    key: "droeloe",
    source: new pulumi.asset.FileAsset("example.txt"),
});
import pulumi
import pulumi_aws as aws

example = aws.s3.Bucket("example", bucket="yotto")
example_bucket_versioning = aws.s3.BucketVersioning("example",
    bucket=example.id,
    versioning_configuration={
        "status": "Enabled",
    })
example_bucket_objectv2 = aws.s3.BucketObjectv2("example",
    bucket=example_bucket_versioning.id,
    key="droeloe",
    source=pulumi.FileAsset("example.txt"))
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/s3"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := s3.NewBucket(ctx, "example", &s3.BucketArgs{
			Bucket: pulumi.String("yotto"),
		})
		if err != nil {
			return err
		}
		exampleBucketVersioning, err := s3.NewBucketVersioning(ctx, "example", &s3.BucketVersioningArgs{
			Bucket: example.ID(),
			VersioningConfiguration: &s3.BucketVersioningVersioningConfigurationArgs{
				Status: pulumi.String("Enabled"),
			},
		})
		if err != nil {
			return err
		}
		_, err = s3.NewBucketObjectv2(ctx, "example", &s3.BucketObjectv2Args{
			Bucket: exampleBucketVersioning.ID(),
			Key:    pulumi.String("droeloe"),
			Source: pulumi.NewFileAsset("example.txt"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.S3.Bucket("example", new()
    {
        BucketName = "yotto",
    });

    var exampleBucketVersioning = new Aws.S3.BucketVersioning("example", new()
    {
        Bucket = example.Id,
        VersioningConfiguration = new Aws.S3.Inputs.BucketVersioningVersioningConfigurationArgs
        {
            Status = "Enabled",
        },
    });

    var exampleBucketObjectv2 = new Aws.S3.BucketObjectv2("example", new()
    {
        Bucket = exampleBucketVersioning.Id,
        Key = "droeloe",
        Source = new FileAsset("example.txt"),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.s3.Bucket;
import com.pulumi.aws.s3.BucketArgs;
import com.pulumi.aws.s3.BucketVersioning;
import com.pulumi.aws.s3.BucketVersioningArgs;
import com.pulumi.aws.s3.inputs.BucketVersioningVersioningConfigurationArgs;
import com.pulumi.aws.s3.BucketObjectv2;
import com.pulumi.aws.s3.BucketObjectv2Args;
import com.pulumi.asset.FileAsset;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Bucket("example", BucketArgs.builder()
            .bucket("yotto")
            .build());

        var exampleBucketVersioning = new BucketVersioning("exampleBucketVersioning", BucketVersioningArgs.builder()
            .bucket(example.id())
            .versioningConfiguration(BucketVersioningVersioningConfigurationArgs.builder()
                .status("Enabled")
                .build())
            .build());

        var exampleBucketObjectv2 = new BucketObjectv2("exampleBucketObjectv2", BucketObjectv2Args.builder()
            .bucket(exampleBucketVersioning.id())
            .key("droeloe")
            .source(new FileAsset("example.txt"))
            .build());

    }
}
resources:
  example:
    type: aws:s3:Bucket
    properties:
      bucket: yotto
  exampleBucketVersioning:
    type: aws:s3:BucketVersioning
    name: example
    properties:
      bucket: ${example.id}
      versioningConfiguration:
        status: Enabled
  exampleBucketObjectv2:
    type: aws:s3:BucketObjectv2
    name: example
    properties:
      bucket: ${exampleBucketVersioning.id}
      key: droeloe
      source:
        fn::FileAsset: example.txt

The BucketObjectv2 resource references the versioning resource’s bucket ID, creating an implicit dependency that ensures versioning is active before the object is created. For critical or production objects, do not enable versioning and create objects in the same configuration; AWS recommends a 15-minute wait between these operations.

Beyond these examples

These snippets focus on specific versioning configuration features: enabling and disabling versioning, and object dependency coordination. They’re intentionally minimal rather than full bucket configurations.

The examples reference pre-existing infrastructure such as S3 buckets created separately. They focus on versioning state management rather than bucket provisioning.

To keep things focused, common versioning patterns are omitted, including:

  • MFA delete protection (mfa property)
  • Cross-account bucket ownership (expectedBucketOwner)
  • Suspending versioning (status: Suspended)

These omissions are intentional: the goal is to illustrate how versioning configuration is wired, not provide drop-in bucket modules. See the S3 BucketVersioningV2 resource reference for all available configuration options.

Let's configure AWS S3 Bucket Versioning

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Versioning Lifecycle & Timing
Why should I wait 15 minutes after enabling versioning before writing objects?
AWS recommends waiting 15 minutes after enabling versioning before issuing write operations (PUT or DELETE) to ensure versioning is fully propagated across the S3 infrastructure.
Can I create a bucket, enable versioning, and add objects in the same configuration?
Not for critical or production objects. This approach doesn’t allow the AWS-recommended 15-minute wait between enabling versioning and writing to the bucket. Enable versioning in a separate deployment first.
What happens when I delete this versioning resource?
Deletion will either suspend versioning on the bucket or simply remove the resource from state if the bucket is unversioned. It doesn’t necessarily disable versioning completely.
Configuration & Status
How do I enable versioning on an S3 bucket?
Set versioningConfiguration.status to "Enabled" in your BucketVersioningV2 resource.
How do I disable versioning on an S3 bucket?
Set versioningConfiguration.status to "Disabled" in your BucketVersioningV2 resource. Note that this suspends versioning rather than removing existing versions.
Can I change the bucket name after creating the versioning resource?
No, the bucket property is immutable and cannot be changed after creation.
Dependencies & Object Management
How do I ensure my S3 objects depend on versioning being enabled?
Create an implicit dependency by referencing the BucketVersioning resource’s bucket property in your object configuration, or use an explicit dependsOn relationship. This ensures versioning is enabled before objects are created.
Compatibility & Limitations
Can I use this resource with S3 directory buckets?
No, BucketVersioningV2 cannot be used with S3 directory buckets. Use standard S3 buckets only.
Is the expectedBucketOwner parameter still supported?
While still functional, expectedBucketOwner is deprecated and will be removed in a future version of the provider.

Using a different cloud?

Explore storage guides for other cloud providers: