All Products
Search
Document Center

Object Storage Service:Bucket-level retention policy (BucketWorm)

Last Updated:May 27, 2026

BucketWorm applies a Write Once, Read Many (WORM) model to an OSS bucket, making all objects immutable for a specified retention period. During this period, objects can be uploaded and read but not modified or deleted by any user, including the bucket owner.

Use cases

OSS retention policies help meet regulatory requirements from entities such as the SEC and FINRA. Typical use cases include compliance archiving and log data audits in finance, insurance, healthcare, and securities.

Note

OSS is accredited by Cohasset Associates and meets electronic records retention requirements including SEC Rule 17a-4(f), FINRA Rule 4511, and Commodity Futures Trading Commission (CFTC) Rule 1.31. OSS Cohasset Assessment Report.

Prerequisites

Versioning must be enabled or disabled for the bucket, not suspended. Versioning.

Usage notes

  • You cannot enable OSS-HDFS and configure a bucket-level retention policy for the same bucket.

  • During the retention period, you can configure a lifecycle rule to transition objects to a different storage class, reducing storage costs while maintaining compliance.

  • A bucket-level retention policy (BucketWorm) and an object-level retention policy (ObjectWorm) are mutually exclusive. You cannot enable both for the same bucket.

How it works

  • Activation rule

    When created, a retention policy enters the InProgress state for 24 hours. Bucket resources are protected during this period.

    • Within 24 hours of creation

      • If not locked, the bucket owner and authorized users can delete the policy.

      • Once locked, the policy cannot be deleted or shortened—only extended. Attempts to delete or modify protected data return 409 FileImmutable.

    • After 24 hours

      If not locked within 24 hours, the policy expires and can be deleted.

  • Deletion rule

    • A retention policy is a bucket metadata attribute. Deleting the bucket also deletes its policy.

    • If not locked within 24 hours of creation, the bucket owner and authorized users can delete the policy.

    • You cannot delete the policy or bucket while any objects remain within their retention period.

  • Example

    Suppose you create and lock a 30-day retention policy on June 1, 2022, and upload three objects at different times:

    Object name

    Upload time

    Expiration time

    file1.txt

    April 1, 2022

    April 30, 2022

    file2.txt

    June 1, 2022

    June 30, 2022

    file3.txt

    September 1, 2022

    September 30, 2022

Procedure

OSS console

  1. Create a retention policy.

    1. Log on to the OSS console.

    2. In the left-side navigation pane, click Buckets. On the Buckets page, click the name of the target bucket.

    3. In the left-side navigation pane, choose Content Security > Bucket-Level Retention Policy.

    4. On the Retention Policy page, click Create Policy.

    5. In the Create Policy dialog box, specify the Retention Period.

      Note

      The retention period is measured in days. Valid values: 1 to 25,550.

    6. Click OK.

      Note

      The policy enters the InProgress state for 24 hours, during which bucket resources are protected. You can delete the policy within this window.

  2. Lock the retention policy.

    1. Click Lock.

    2. In the dialog box that appears, click OK.

      Important

      Once locked, the policy cannot be modified or deleted, and data in the bucket is immutable during the retention period.

  3. (Optional) Modify the retention period.

    1. Click Edit.

    2. In the dialog box that appears, modify the retention period.

      Important

      You can only extend the retention period, not shorten it.

Alibaba Cloud SDKs

The following code configures retention policies with common SDKs. Other SDKs are covered in SDK overview.

Java

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.InitiateBucketWormRequest;
import com.aliyun.oss.model.InitiateBucketWormResult;

public class Demo {

    public static void main(String[] args) throws Exception {
        // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. 
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Specify the name of the bucket. Example: examplebucket. 
        String bucketName = "examplebucket";
        // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. 
        String region = "cn-hangzhou";

        // Create an OSSClient instance. 
        // Call the shutdown method to release resources when the OSSClient is no longer in use.
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // Create an InitiateBucketWormRequest object. 
            InitiateBucketWormRequest initiateBucketWormRequest = new InitiateBucketWormRequest(bucketName);
            // Set the retention period to 1 day. 
            initiateBucketWormRequest.setRetentionPeriodInDays(1);

            // Create a retention policy. 
            InitiateBucketWormResult initiateBucketWormResult = ossClient.initiateBucketWorm(initiateBucketWormRequest);

            // Display the ID of the retention policy. 
            String wormId = initiateBucketWormResult.getWormId();
            System.out.println(wormId);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

PHP

<?php

// Import the autoloader file to load dependencies.
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// Define command line argument descriptions.
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located', 'required' => True], // Required. The region where the bucket is located.
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS', 'required' => False], // Optional. The domain name that other services can use to access OSS.
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Required. The name of the bucket.
];

// Generate a long options list to parse command line arguments.
$longopts = \array_map(function ($key) {
    return "$key:"; // Add a colon after each argument to indicate that a value is required.
}, array_keys($optsdesc));

// Parse the command line arguments.
$options = getopt("", $longopts); 

// Check if any required arguments are missing.
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help'];
        echo "Error: the following arguments are required: --$key, $help"; // Prompt the user that a required argument is missing.
        exit(1); 
    }
}

// Get the command line argument values.
$region = $options["region"]; // The region where the bucket is located.
$bucket = $options["bucket"]; // The name of the bucket.

// Load credential information, such as AccessKey ID and AccessKey secret, from environment variables.
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// Use the default configurations of the software development kit (SDK).
$cfg = Oss\Config::loadDefault();

// Set the credential provider.
$cfg->setCredentialsProvider($credentialsProvider);

// Set the region.
$cfg->setRegion($region);

// If an endpoint is provided, set the endpoint.
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]);
}

// Create an OSS client instance.
$client = new Oss\Client($cfg);

// Create a request object to initialize the retention policy for the bucket. Set the retention period to 3 days.
$request = new Oss\Models\InitiateBucketWormRequest(
    bucket: $bucket, 
    initiateWormConfiguration: new Oss\Models\InitiateWormConfiguration(
        retentionPeriodInDays: 3 // The retention period in days.
));

// Call the initiateBucketWorm method to initialize the retention policy for the bucket.
$result = $client->initiateBucketWorm($request);

// Print the returned result.
printf(
    'status code:' . $result->statusCode . PHP_EOL . // The HTTP response status code.
    'request id:' . $result->requestId . PHP_EOL . // The unique ID of the request.
    'worm id:' . $result->wormId // The ID of the retention policy.
);

Node.js

const OSS = require('ali-oss');

const client = new OSS({
  // Set region to the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set region to oss-cn-hangzhou.
  region: 'yourregion',
  // Obtain access credentials from environment variables. Before you run this code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,  
  authorizationV4: true,
  // Set bucket to your bucket name.
  bucket: 'yourBucketName',
});
// Create a data retention policy.
async function initiateBucketWorm() {
 // Set bucket to your bucket name.
  const bucket = 'yourbucketname'
  // Specify the retention period in days.
  const days = '<Retention Days>'
    const res = await client.initiateBucketWorm(bucket, days)
  console.log(res.wormId)
}

initiateBucketWorm()

Python

import argparse
import alibabacloud_oss_v2 as oss

# Create a command-line argument parser and describe the script's purpose: This sample shows how to initialize the WORM configuration for an OSS bucket.
parser = argparse.ArgumentParser(description="initiate bucket worm sample")

# Add the --region command-line argument, which specifies the bucket region. This argument is required.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# Add the --bucket command-line argument, which specifies the bucket name. This argument is required.
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# Add the --endpoint command-line argument, which specifies the domain name that other services can use to access OSS. This argument is optional.
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# Add the --retention_period_in_days command-line argument, which specifies the retention period in days. This argument is required.
parser.add_argument('--retention_period_in_days', help='The number of days for which objects can be retained.', required=True)

def main():
    # Parse the command-line arguments to get the user-provided values.
    args = parser.parse_args()

    # Load the access credentials for OSS from environment variables for identity verification.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # Create a configuration object using the SDK's default configurations and set the credentials provider.
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region

    # If a custom endpoint is provided, update the endpoint property in the configuration object.
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # Initialize the OSS client with the configuration to interact with OSS.
    client = oss.Client(cfg)

    # Send a request to initialize the WORM configuration for the specified bucket.
    result = client.initiate_bucket_worm(oss.InitiateBucketWormRequest(
        bucket=args.bucket,  # Bucket name.
        initiate_worm_configuration=oss.InitiateWormConfiguration(
            retention_period_in_days=int(args.retention_period_in_days),  # Retention period in days, converted to an integer.
        ),
    ))

    # Print the status code, request ID, and WORM ID of the operation to confirm the request status.
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' worm id: {result.worm_id}'
    )

# When this script is run directly, call the main function to start the processing logic.
if __name__ == "__main__":
    main()  # Script entry point, where the program flow starts.

Go

package main

import (
	"log"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Fatalf("Error creating credentials provider: %v", err)
	}

	// Create an OSSClient instance.
	// Set yourEndpoint to the Endpoint of the bucket. For example, for a bucket in the China (Hangzhou) region, set the Endpoint to https://oss-cn-hangzhou.aliyuncs.com. For other regions, use the actual Endpoint.
	// Set yourRegion to the region where the bucket is located. For example, for a bucket in the China (Hangzhou) region, set the region to cn-hangzhou. For other regions, use the actual region.
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// Set the signature version.
	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
	if err != nil {
		log.Fatalf("Error creating OSS client: %v", err)
	}

	// Specify the name of the bucket for which you want to configure a retention policy.
	bucketName := "<yourBucketName>"

	// Set the retention period for objects to 60 days.
	result, err := client.InitiateBucketWorm(bucketName, 60)
	if err != nil {
		log.Fatalf("Error initiating bucket WORM: %v", err)
	}

	log.Println("WORM policy initiated successfully:", result)
}

C++

#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* Initialize the OSS account information. */
            
    /* Set Endpoint to the endpoint of the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set Endpoint to https://oss-cn-hangzhou.aliyuncs.com. */
    std::string Endpoint = "yourEndpoint";
    /* Set Region to the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set Region to cn-hangzhou. */
    std::string Region = "yourRegion";
    /* Enter the bucket name. For example, examplebucket. */
    std::string BucketName = "examplebucket";

      /* Initialize resources such as the network. */
      InitializeSdk();

      ClientConfiguration conf;
      conf.signatureVersion = SignatureVersionType::V4;
      /* Obtain access credentials from environment variables. Before you run this code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set. */
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
  
      /* Create a data retention policy and set the object protection period to 1 day. */
      auto outcome = client.InitiateBucketWorm(InitiateBucketWormRequest(BucketName, 1));

      if (outcome.isSuccess()) {      
            std::cout << " InitiateBucketWorm success " << std::endl;
            std::cout << "WormId:" << outcome.result().WormId() << std::endl;
      }
      else {
        /* Handle the exception. */
        std::cout << "InitiateBucketWorm fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
      }

      /* Release resources such as the network. */
      ShutdownSdk();
      return 0;
}

ossutil

You can create a WORM policy with ossutil. To set up the tool, follow Install ossutil.

The following command creates a WORM policy in examplebucket with a 365-day retention period.

ossutil api initiate-bucket-worm --bucket examplebucket --initiate-worm-configuration "{\"RetentionPeriodInDays\":\"365\"}"

Command reference: initiate-bucket-worm.

API reference

For advanced customization, call the REST API directly. This requires manual signature calculation. InitiateBucketWorm.

Working with versioning

To allow continuous data updates while keeping all historical versions immutable—common in backup protection, asset tracking, and financial compliance—enable both versioning and a retention policy on the same bucket. Versioning preserves old versions when objects are overwritten or deleted; the retention policy prevents any version from being modified or deleted during the retention period.

When both features are enabled:

  • Order of enablement: No ordering constraint. Enable versioning and retention policies in any order.

  • State transition constraints:

    • After a retention policy is enabled, you cannot change the versioning state from enabled to suspended.

    • You can enable a retention policy for a bucket for which versioning is suspended. After the policy is enabled, you can change the versioning state to enabled.

  • Object version protection:

    • A retention policy protects all versions of an object. No version can be deleted or modified during the retention period.

    • You can upload an object with the same name to create a new version. The new version is also protected by the retention policy.

    • A retention policy does not protect a delete marker, so its deletion is not restricted by the policy.

  • Data replication synergy:

    • Both the source and destination buckets support independent configurations for versioning and retention policies.

    • Version information is transmitted normally during replication. The destination bucket manages versions based on its own configuration.

    • Deleting a version in the source bucket is not synchronized to a destination bucket that has a retention policy enabled.

FAQ

Object deletion with versioning

When a retention policy and versioning are both enabled, deleting an object has the following effects:

  • The deletion operation creates a delete marker but does not physically delete the historical versions of the object.

  • A retention policy does not protect delete markers, which can be deleted normally.

  • All object versions cannot be deleted during the retention period, even if a delete marker exists.

  • Lifecycle management can clean up dangling delete markers but cannot delete object versions protected by a retention policy.

Modify versioning state

After a retention policy is enabled, the following constraints apply to modifying the versioning state:

  • Enabled to suspended: If the versioning state is enabled, you cannot change it to suspended after the retention policy is locked.

  • Suspended to enabled: If the versioning state is suspended, you can still change it to enabled after you enable the retention policy.

  • Disabled to enabled: For a bucket with versioning disabled, you can enable versioning after you configure a retention policy.

Storage costs

Yes, in the following ways:

  • All object versions are retained during the retention period and cannot be deleted by a lifecycle rule.

  • The accumulation of versions can significantly increase storage usage, especially for frequently updated objects.

  • Set a reasonable retention period and use lifecycle rules to transition storage classes and reduce costs.

Benefits of a retention policy

A retention policy provides compliance-grade immutability. Data protected only by a RAM policy or Bucket Policy can still be modified or deleted.

When to use a retention policy

Enable a retention policy for data that must remain unchanged long-term, such as medical records, technical documents, or contracts.

Delete a retention policy

Whether you can delete a retention policy depends on its state:

  • Not locked: The bucket owner and authorized users can delete the policy.

  • Locked: No user can delete the policy.

Object-level policy

BucketWorm applies to entire buckets, not directories or individual objects. To set retention on a single object, use an object-level retention policy (ObjectWorm). BucketWorm and ObjectWorm are mutually exclusive on the same bucket.

Calculate retention time

Retention time = last modification time + retention period. For example, with a 10-day policy, an object last modified on February 15, 2022, is retained until February 25, 2022.

Delete a protected bucket

  • If the bucket contains no objects, you can directly delete it.

  • If the bucket contains objects whose retention periods have expired, you must delete all objects before deleting the bucket.

  • If the bucket contains objects that are still within their retention period, you cannot delete the bucket.

Overdue payments and data retention

Important: An overdue payment may cause Alibaba Cloud to delete data per the service suspension rules, even for objects protected by a retention policy.

RAM user authorization

Yes. Retention policy management supports RAM authorization. Authorized RAM users can manage policies through the OSS console, APIs, or SDKs.