Lifecycle rules based on last access time automatically identify cold data by monitoring actual access patterns, then transition objects to lower-cost storage classes — without manual log analysis or scripting.
Use this approach when access patterns across objects in the same path differ. For example, if a path contains both frequently accessed and rarely accessed files that were uploaded at similar times, a last-modification-time rule would treat them identically. A last-access-time rule transitions only the cold files. If all objects in a path age uniformly regardless of access, use last-modification-time rules instead.
Prerequisites
Before you begin, make sure you have:
Access tracking enabled on the target bucket
Submitted a support ticket if you need to transition objects to Archive, Cold Archive, or Deep Cold Archive storage class (Standard to Infrequent Access (IA) transitions do not require a ticket)
After your ticket is approved, objects transitioned from Standard or IA to Archive, Cold Archive, or Deep Cold Archive using a last-access-time policy will have their last access time set to the time access tracking was enabled for the bucket.
Scenario
A multimedia platform stores two types of data in examplebucket:
| Path | Content | Access pattern | Policy |
|---|---|---|---|
data/ | WMV live streams and MP4 movies | WMV files: infrequent after 2 months. MP4 files: accessed repeatedly within 6-month cycles. | Transition to IA 200 days after last access; stay in IA if accessed again. |
log/ | Application logs | Low activity within 3 months; almost none after 6 months. | Transition to IA 120 days after last access, then to Archive 250 days after last access. |
With last-access-time rules, frequently accessed MP4 files remain in Standard automatically. MP4 files untouched for 200 days transition to IA. A last-modification-time rule cannot make this distinction — it would transition all files based on upload date alone.
The policies above are examples. Adjust thresholds based on your actual access patterns and cost requirements.
Enable access tracking and create lifecycle rules
Use the OSS console
Step 1: Enable access tracking
Log on to the OSS console.
In the left navigation pane, click Buckets. Find and click the target bucket.
In the left navigation pane, choose Data Management > Lifecycle.
On the Lifecycle page, turn on the Enable Access Tracking switch.
After you enable access tracking, OSS sets the last access time for all existing objects in the bucket to the time access tracking was enabled.
Step 2: Create lifecycle rules
On the Lifecycle page, click Create Rule.
In the Create Lifecycle Rule panel, configure rules for the
data/andlog/prefixes as follows.
Rule for the `data/` prefix
| Setting | Value |
|---|---|
| Status | Start |
| Applied to | Match by Prefix |
| Prefix | data/ |
| Object lifecycle | Specify Days |
| Lifecycle-based rules | Last Access Time: 200 days → Infrequent Access (Data remains in IA after being accessed) |
Rule for the `log/` prefix
| Setting | Value |
|---|---|
| Status | Start |
| Applied to | Match by Prefix |
| Prefix | log/ |
| Object lifecycle | Specify Days |
| Lifecycle-based rules | Last Access Time: 120 days → Infrequent Access (Data remains in IA after being accessed) |
| Last Access Time: 250 days → Archive |
Click OK.
Use an Alibaba Cloud SDK
Only the Java, Python, and Go SDKs support lifecycle rules based on last access time. Enable access tracking for the bucket before creating these rules.
The examples below use two key parameters:
IsAccessTime: true— base the transition on last access time, not last modification timeReturnToStdWhenVisit: false— objects stay in the transitioned storage class when accessed again (they do not return to Standard)
Step 1: Enable access tracking
Python
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Load credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
region = "cn-hangzhou"
bucket = oss2.Bucket(auth, endpoint, "examplebucket", region=region)
# Enable access tracking. To disable it later, first remove all last-access-time lifecycle rules.
bucket.put_bucket_access_monitor("Enabled")Java
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.AccessMonitor;
public class Demo {
public static void main(String[] args) throws Exception {
// Replace with your actual endpoint. Example: China (Hangzhou).
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Load credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
EnvironmentVariableCredentialsProvider credentialsProvider =
CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
String bucketName = "examplebucket";
String region = "cn-hangzhou";
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// Enable access tracking. To disable it later, first remove all last-access-time lifecycle rules.
ossClient.putBucketAccessMonitor(bucketName, AccessMonitor.AccessMonitorStatus.Enabled.toString());
} catch (OSSException oe) {
System.out.println("Error Code: " + oe.getErrorCode());
System.out.println("Request ID: " + oe.getRequestId());
} catch (ClientException ce) {
System.out.println("Client error: " + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}Go
package main
import (
"context"
"flag"
"log"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
var (
region string
bucketName string
)
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}
func main() {
flag.Parse()
if len(bucketName) == 0 {
log.Fatalf("invalid parameters, bucket name required")
}
if len(region) == 0 {
log.Fatalf("invalid parameters, region required")
}
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg)
// Enable access tracking. To disable it later, first remove all last-access-time lifecycle rules.
request := &oss.PutBucketAccessMonitorRequest{
Bucket: oss.Ptr(bucketName),
AccessMonitorConfiguration: &oss.AccessMonitorConfiguration{
Status: oss.AccessMonitorStatusEnabled,
},
}
result, err := client.PutBucketAccessMonitor(context.TODO(), request)
if err != nil {
log.Fatalf("failed to enable access tracking: %v", err)
}
log.Printf("access tracking enabled: %#v\n", result)
}Step 2: Create lifecycle rules
All three examples configure the same two rules:
rule1 (
data/): transition to IA after 200 days of no access; stay in IA if accessed againrule2 (
log/): transition to IA after 120 days, then to Archive after 250 days
Python
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2.models import LifecycleRule, BucketLifecycle, StorageTransition
# Load credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# rule1: data/ prefix — transition to IA 200 days after last access; stay in IA when accessed again.
rule1 = LifecycleRule('rule1', 'data/', status=LifecycleRule.ENABLED)
rule1.storage_transitions = [
StorageTransition(
days=200,
storage_class=oss2.BUCKET_STORAGE_CLASS_IA,
is_access_time=True, # base on last access time
return_to_std_when_visit=False # stay in IA when accessed again
)
]
# rule2: log/ prefix — transition to IA 120 days after last access, then to Archive after 250 days.
rule2 = LifecycleRule('rule2', 'log/', status=LifecycleRule.ENABLED)
rule2.storage_transitions = [
StorageTransition(
days=120,
storage_class=oss2.BUCKET_STORAGE_CLASS_IA,
is_access_time=True,
return_to_std_when_visit=False
),
StorageTransition(
days=250,
storage_class=oss2.BUCKET_STORAGE_CLASS_ARCHIVE,
is_access_time=False # Archive transition based on last modification time
)
]
lifecycle = BucketLifecycle([rule1, rule2])
result = bucket.put_bucket_lifecycle(lifecycle)
print('Lifecycle rules set. Status:', result.status)Java
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.util.ArrayList;
import java.util.List;
public class Lifecycle {
public static void main(String[] args) throws Exception {
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Load credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
EnvironmentVariableCredentialsProvider credentialsProvider =
CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
String bucketName = "examplebucket";
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
try {
SetBucketLifecycleRequest request = new SetBucketLifecycleRequest(bucketName);
// rule1: data/ prefix — transition to IA 200 days after last access; stay in IA when accessed again.
List<LifecycleRule.StorageTransition> transitions1 = new ArrayList<>();
LifecycleRule.StorageTransition t1 = new LifecycleRule.StorageTransition();
t1.setStorageClass(StorageClass.IA);
t1.setExpirationDays(200);
t1.setIsAccessTime(true); // base on last access time
t1.setReturnToStdWhenVisit(false); // stay in IA when accessed again
transitions1.add(t1);
LifecycleRule rule1 = new LifecycleRule("rule1", "data/", LifecycleRule.RuleStatus.Enabled);
rule1.setStorageTransition(transitions1);
request.AddLifecycleRule(rule1);
// rule2: log/ prefix — transition to IA 120 days after last access, then to Archive after 250 days.
List<LifecycleRule.StorageTransition> transitions2 = new ArrayList<>();
LifecycleRule.StorageTransition t2 = new LifecycleRule.StorageTransition();
t2.setStorageClass(StorageClass.IA);
t2.setExpirationDays(120);
t2.setIsAccessTime(true);
t2.setReturnToStdWhenVisit(false);
transitions2.add(t2);
LifecycleRule.StorageTransition t3 = new LifecycleRule.StorageTransition();
t3.setStorageClass(StorageClass.Archive);
t3.setExpirationDays(250);
t3.setIsAccessTime(false); // Archive transition based on last modification time
transitions2.add(t3);
LifecycleRule rule2 = new LifecycleRule("rule2", "log/", LifecycleRule.RuleStatus.Enabled);
rule2.setStorageTransition(transitions2);
request.AddLifecycleRule(rule2);
VoidResult result = ossClient.setBucketLifecycle(request);
System.out.println("Lifecycle rules set. Status: " + result.getResponse().getStatusCode());
} catch (OSSException oe) {
System.out.println("Error Code: " + oe.getErrorCode());
System.out.println("Request ID: " + oe.getRequestId());
} catch (ClientException ce) {
System.out.println("Client error: " + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
}
}Go
package main
import (
"context"
"flag"
"log"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
var (
region string
bucketName string
)
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}
func main() {
flag.Parse()
if len(bucketName) == 0 {
log.Fatalf("invalid parameters, bucket name required")
}
if len(region) == 0 {
log.Fatalf("invalid parameters, region required")
}
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg)
request := &oss.PutBucketLifecycleRequest{
Bucket: oss.Ptr(bucketName),
LifecycleConfiguration: &oss.LifecycleConfiguration{
Rules: []oss.LifecycleRule{
{
// rule1: data/ prefix — transition to IA 200 days after last access; stay in IA when accessed again.
ID: oss.Ptr("rule1"),
Status: oss.Ptr("Enabled"),
Prefix: oss.Ptr("data/"),
Transitions: []oss.LifecycleRuleTransition{
{
Days: oss.Ptr(int32(200)),
StorageClass: oss.StorageClassIA,
IsAccessTime: oss.Ptr(true), // base on last access time
ReturnToStdWhenVisit: oss.Ptr(false), // stay in IA when accessed again
},
},
},
{
// rule2: log/ prefix — transition to IA 120 days after last access, then to Archive after 250 days.
ID: oss.Ptr("rule2"),
Status: oss.Ptr("Enabled"),
Prefix: oss.Ptr("log/"),
Transitions: []oss.LifecycleRuleTransition{
{
Days: oss.Ptr(int32(120)),
StorageClass: oss.StorageClassIA,
IsAccessTime: oss.Ptr(true),
ReturnToStdWhenVisit: oss.Ptr(false),
},
{
Days: oss.Ptr(int32(250)),
StorageClass: oss.StorageClassArchive,
IsAccessTime: oss.Ptr(true),
ReturnToStdWhenVisit: oss.Ptr(false),
},
},
},
},
},
}
result, err := client.PutBucketLifecycle(context.TODO(), request)
if err != nil {
log.Fatalf("failed to set lifecycle rules: %v", err)
}
log.Printf("lifecycle rules set: %#v\n", result)
}Use ossutil
Enable access tracking on the bucket, then apply lifecycle rules.
ossutil 2.0
Step 1: Enable access tracking
Create a local file config1.xml:
<?xml version="1.0" encoding="UTF-8"?>
<AccessMonitorConfiguration>
<Status>Enabled</Status>
</AccessMonitorConfiguration>Apply it to the bucket:
ossutil api put-bucket-access-monitor --bucket bucketname --access-monitor-configuration file://config1.xmlStep 2: Create lifecycle rules
Create a local file config2.xml:
<?xml version="1.0" encoding="UTF-8"?>
<LifecycleConfiguration>
<Rule>
<ID>rule1</ID>
<Prefix>data/</Prefix>
<Status>Enabled</Status>
<Transition>
<Days>200</Days>
<StorageClass>IA</StorageClass>
<IsAccessTime>true</IsAccessTime>
<ReturnToStdWhenVisit>false</ReturnToStdWhenVisit>
</Transition>
</Rule>
<Rule>
<ID>rule2</ID>
<Prefix>log/</Prefix>
<Status>Enabled</Status>
<Transition>
<Days>120</Days>
<StorageClass>IA</StorageClass>
<IsAccessTime>true</IsAccessTime>
<ReturnToStdWhenVisit>false</ReturnToStdWhenVisit>
</Transition>
<Transition>
<Days>250</Days>
<StorageClass>Archive</StorageClass>
<IsAccessTime>true</IsAccessTime>
<ReturnToStdWhenVisit>false</ReturnToStdWhenVisit>
</Transition>
</Rule>
</LifecycleConfiguration>Apply the rules:
ossutil api put-bucket-lifecycle --bucket bucketname --lifecycle-configuration file://config2.xmlossutil 1.0
Step 1: Enable access tracking
Create config1.xml with the same content as above, then run:
ossutil access-monitor --method put oss://examplebucket/ config1.xmlStep 2: Create lifecycle rules
Create config2.xml with the same content as above, then run:
ossutil lifecycle --method put oss://examplebucket config2.xmlUse the REST API
For custom integrations, call the REST API directly. You must calculate request signatures manually.
Enable access tracking: PutBucketAccessMonitor
Set lifecycle rules: PutBucketLifecycle
What's next
Lifecycle rules based on the last access time — detailed rule behavior and limits
Impact of common operations on the LastAccessTime of an object — understand what counts as an access
Storage fees — compare costs across storage classes