Skip to main content

PutBucketLifecycleConfiguration

PutBucketLifecycleConfiguration sets a bucket's lifecycle configuration: the rules that expire current object versions, delete noncurrent versions and abort incomplete multipart uploads. The request replaces the bucket's whole configuration, rules set in the dashboard included - the dashboard shows and edits the same rules. The deprecated PutBucketLifecycle sends exactly the same request, so this operation is the better choice. Lifecycle policies explains what the rules do.

Good to know on STRG
  • Rules hold the three actions STRG offers - Expiration with Days, NoncurrentVersionExpiration with NoncurrentDays and AbortIncompleteMultipartUpload - each filtered by key prefix. STRG answers anything else with 501 NotImplemented, so a client knows straight away.
  • Each prefix has one rule, which carries all of its actions. Prefixes stay apart - no prefix starts with another - and a rule for the whole bucket is the bucket's one rule, so it is always clear which rule applies to an object.
  • A bucket holds up to 100 rules.
  • Every rule with Expiration gets a companion rule from STRG that tidies away expired delete markers, and GetBucketLifecycleConfiguration returns it.
  • x-amz-expected-bucket-owner is welcome and has nothing to check, and x-amz-transition-default-minimum-object-size is set aside, as it concerns storage-class transitions.
Deleted versions are gone for good

NoncurrentVersionExpiration deletes object versions permanently; they cannot be restored. Every bucket keeps versions, so a rule with Expiration alone frees no storage: an expired object stays on as a noncurrent version, billed as stored data, until a NoncurrentVersionExpiration rule removes it or it is deleted. Keeping 30 days of old versions shows a rule that does both.

When you'd use it​

  • Keeping storage costs in check. Every version of every object is billed as stored data, so a team whose documents change daily keeps the last 30 days of old versions and lets STRG delete the rest - the Keeping 30 days of old versions recipe.
  • Tidying up after interrupted uploads. A mobile app uploading large videos in parts leaves unfinished uploads behind whenever a phone loses its connection, and their parts are billed too. A rule with AbortIncompleteMultipartUpload clears them away after a day - Cleaning up abandoned multipart uploads.
  • Scratch space and logs. An agent keeping intermediate results under tmp/, or a service writing logs under logs/, has that data expire on its own after a few days - Expiring a tmp/ prefix.
  • Settings kept in code. A deploy script or infrastructure tool that manages each bucket's settings writes the rules from the repository, so what the repository says is what the bucket does.

Request​

PUT /?lifecycle HTTP/1.1
Host: my-bucket.s3.eu-central-1.strg.com
Authorization: AWS4-HMAC-SHA256 Credential=...
x-amz-date: 20260926T120000Z
x-amz-content-sha256: <SHA-256 of the body>
Content-MD5: <base64 MD5 of the body>
Content-Type: application/xml

<LifecycleConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Rule>
<ID>expire-logs</ID>
<Filter>
<Prefix>logs/</Prefix>
</Filter>
<Status>Enabled</Status>
<Expiration>
<Days>30</Days>
</Expiration>
<NoncurrentVersionExpiration>
<NoncurrentDays>7</NoncurrentDays>
</NoncurrentVersionExpiration>
</Rule>
</LifecycleConfiguration>

Path-style, the same request is PUT /my-bucket?lifecycle on s3.eu-central-1.strg.com. Addressing in the S3 API overview has both styles.

Permissions​

The access key needs Manage lifecycle rules (bucket-lifecycle:write). A key limited to certain buckets works too, as long as this bucket is one of them. A key prefix does not narrow this operation, because the configuration belongs to the whole bucket. Access keys has every permission.

URI parameters​

NameTypeRequiredDescription
BucketStringYesThe bucket whose lifecycle configuration is set.
lifecycleFlagYesSelects the lifecycle subresource. Sent without a value.

STRG answers 501 NotImplemented to any other query parameter, so a client knows straight away. The X-Amz-* parameters of a presigned URL and the x-id parameter the JavaScript SDK adds are welcome.

Request headers​

NameTypeRequiredDescription
Content-MD5StringOne integrity header is requiredThe base64 MD5 digest of the body. STRG checks it and answers 400 BadDigest if it does not match.
x-amz-checksum-crc32, x-amz-checksum-crc32c, x-amz-checksum-crc64nvme, x-amz-checksum-sha1, x-amz-checksum-sha256StringOne integrity header is requiredA checksum of the body, which works in place of Content-MD5. The AWS SDKs and CLI send one by default.
x-amz-sdk-checksum-algorithmStringNoThe algorithm of the x-amz-checksum-* header the SDK sends. Accepted.
x-amz-expected-bucket-ownerStringNoWelcome, with nothing to check: an access key only ever reaches its own account's buckets.
x-amz-transition-default-minimum-object-sizeStringNoSet aside. It concerns storage-class transitions, and STRG has one storage class.

Every request carries either Content-MD5 or an x-amz-checksum-* header, and one with neither gets 400 InvalidRequest. The AWS CLI and SDKs add one automatically.

The body arrives whole. STRG answers a streaming aws-chunked upload of the body with 501 NotImplemented; the AWS CLI and SDKs never send one for this operation.

Request body​

A LifecycleConfiguration element holding up to 100 Rule elements, at most 2 MiB. The document is plain XML: a comment, CDATA section, DOCTYPE, processing instruction, namespace prefix or attribute other than xmlns gets 400 MalformedXML. A configuration with no rules is 400 MalformedXML too - removing every rule is the work of DeleteBucketLifecycle.

ElementRequiredDescription
RuleYesOne lifecycle rule. Up to 100, not counting companion rules.
Rule/IDNoThe rule's ID, at most 255 characters, unique within the configuration. For a rule with Expiration/Days, the ID plus the _marker suffix of its companion rule also fits in 255 characters and stays clear of every other ID. A rule sent without one gets an ID generated by STRG. The ID is kept, including across a save in the dashboard.
Rule/StatusYesEnabled. STRG answers Disabled with 501 NotImplemented; a rule that should stop applying is simply left out of the configuration.
Rule/FilterNoThe objects the rule applies to. An empty or missing Filter means every object in the bucket.
Rule/Filter/PrefixNoThe key prefix the rule applies to, at most 1,024 bytes, without control characters. It does not overlap another rule's prefix - one prefix never starts with another.
Rule/Filter/TagNoSTRG answers 501 NotImplemented: rules here filter by key prefix.
Rule/Filter/ObjectSizeGreaterThan, Rule/Filter/ObjectSizeLessThanNoSTRG answers 501 NotImplemented: rules here filter by key prefix.
Rule/Filter/AndNoSTRG answers 501 NotImplemented: rules here filter by key prefix.
Rule/PrefixNoThe deprecated top-level prefix. STRG answers 501 NotImplemented; Filter/Prefix sets the same thing.
Rule/Expiration/DaysNoDays after an object is created when its current version becomes a noncurrent version (a delete marker is placed on top of it). A whole number of at least 1.
Rule/Expiration/DateNoSTRG answers 501 NotImplemented; Days sets an expiration.
Rule/Expiration/ExpiredObjectDeleteMarkerNotrue is accepted in a rule on the same prefix as a rule with Expiration/Days, and is then replaced by the companion rule STRG adds - its ID is not kept. Anywhere else, or false, STRG answers 501 NotImplemented.
Rule/NoncurrentVersionExpiration/NoncurrentDaysNoDays after a version becomes noncurrent when it is permanently deleted. A whole number of at least 1.
Rule/NoncurrentVersionExpiration/NewerNoncurrentVersionsNoSTRG answers 501 NotImplemented.
Rule/AbortIncompleteMultipartUpload/DaysAfterInitiationNoDays after a multipart upload starts when it is aborted if not completed. A whole number of at least 1.
Rule/TransitionNoSTRG answers 501 NotImplemented: there is one storage class, so nothing to move objects between.
Rule/NoncurrentVersionTransitionNoSTRG answers 501 NotImplemented, for the same reason.

A day count that is not a whole number of at least 1 gets 501 NotImplemented. A rule with no action at all is set aside.

The companion rule. For every rule with Expiration/Days, STRG stores a second rule on the same prefix, with the ID <ID>_marker and Expiration/ExpiredObjectDeleteMarker set to true, which removes a delete marker once no versions remain beneath it. There is no need to send it. GetBucketLifecycleConfiguration returns it, and a configuration read from there can be sent back unchanged.

Response​

A successful request answers 200 OK with an empty body once the configuration is stored. The new rules replace the old ones.

Response headers​

NameDescription
x-amz-request-idThe request ID, useful in a support request.
x-amz-transition-default-minimum-object-sizeRelates to storage-class transitions, which STRG has no use for, so this header carries no meaning for a STRG bucket.

Response body​

None.

Errors​

These are the answers a client can get instead of 200, and the situation behind each.

CodeHTTP statusWhen
MalformedXML400The body is not well-formed XML, its root is not LifecycleConfiguration, it uses a comment, CDATA section, DOCTYPE, processing instruction, namespace prefix or attribute other than xmlns, or it holds no rule with an action.
InvalidRequest400The request carries neither Content-MD5 nor an x-amz-checksum-* header. Or the rules go past a limit: more than 100, two rules for one prefix or overlapping prefixes, a whole-bucket rule beside another rule, a prefix over 1,024 bytes, or a control character in a prefix or ID. The message names the problem.
InvalidArgument400A rule ID is longer than 255 characters (with _marker, for a rule with Expiration/Days), or two rules share an ID.
BadDigest400Content-MD5 does not match the body.
XAmzContentSHA256Mismatch400x-amz-content-sha256 does not match the body.
MaxMessageLengthExceeded400The body is larger than 2 MiB.
NotImplemented501The configuration uses an element STRG does not take (see Request body), the request carries a query parameter this operation does not take, or it sends the body as a streaming aws-chunked upload.
NoSuchBucket404The bucket does not exist, it is in a region other than the endpoint's, or the account stores nothing in this endpoint's region yet.
AccessDenied403The access key does not hold Manage lifecycle rules, the bucket is outside its scope, or the account is not active.
InvalidAccessKeyId403The access key does not exist, has expired or has been revoked - or it was created moments ago and is not yet usable in this region, where the account already stores data. A retry a moment later succeeds.
SignatureDoesNotMatch403The request signature does not match.
RequestTimeTooSkewed403The request time is more than 15 minutes from the server's.
AuthorizationHeaderMalformed400The signature's credential scope names a region other than the endpoint's.
SlowDown503Too many requests at once. A retry after the Retry-After interval goes through.
ServiceUnavailable503A temporary failure. A retry of the same request is safe.

Differences from Amazon S3​

AspectAmazon S3STRG
ActionsExpiration by days or date, transitions, noncurrent expiration and transitions, NewerNoncurrentVersions, abort incomplete uploadsExpiration/Days, NoncurrentVersionExpiration/NoncurrentDays and AbortIncompleteMultipartUpload - three actions that cover expiring data, old versions and abandoned uploads. The rest gets 501 NotImplemented
FiltersPrefix, tags, object size, AndBy key prefix
Rules per prefixAny number, overlapping allowedOne rule per prefix, holding all its actions, and prefixes that never overlap; a whole-bucket rule is the bucket's one rule. It is always clear which rule applies to an object
Rule count1,000100, not counting companion rules
Disabled rulesStored with Status Disabled501 NotImplemented. A rule that should stop applying is left out of the configuration
Expiration rulesStored as sentA companion <ID>_marker rule with ExpiredObjectDeleteMarker is added to every rule with Expiration/Days, so expired delete markers are tidied away without asking; a client's own ExpiredObjectDeleteMarker rule is replaced by it
Top-level PrefixAccepted for backward compatibility501 NotImplemented. Filter/Prefix sets the same thing
VersioningRules apply to unversioned or versioned bucketsEvery bucket keeps versions, so Expiration leaves a noncurrent version behind; a NoncurrentVersionExpiration action beside it frees the storage
Bucket in another region301 redirect with x-amz-bucket-region404 NoSuchBucket, also when the account stores nothing in the endpoint's region. The bucket's own regional endpoint reaches it
x-amz-expected-bucket-ownerChecked against the bucket ownerWelcome, with nothing to check: a key only reaches its own account's buckets

Examples​

Expiring objects under logs/ after 30 days, deleting their noncurrent versions 7 days later, and aborting multipart uploads under uploads/ that are not completed within a day:

lifecycle.json
{
"Rules": [
{
"ID": "expire-logs",
"Filter": { "Prefix": "logs/" },
"Status": "Enabled",
"Expiration": { "Days": 30 },
"NoncurrentVersionExpiration": { "NoncurrentDays": 7 }
},
{
"ID": "abort-uploads",
"Filter": { "Prefix": "uploads/" },
"Status": "Enabled",
"AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 1 }
}
]
}
aws s3api put-bucket-lifecycle-configuration \
--bucket my-bucket \
--lifecycle-configuration file://lifecycle.json \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1

Adding a rule to an existing configuration means reading the current rules first, appending the new one and sending the whole list back. The companion rules in what was read can go back as they are:

aws s3api get-bucket-lifecycle-configuration \
--bucket my-bucket \
--endpoint-url https://s3.eu-central-1.strg.com \
--region eu-central-1 \
--query '{Rules: Rules}' > lifecycle.json

With the new rule added to lifecycle.json, the same put-bucket-lifecycle-configuration command as above sends it.

The new rule's prefix stays clear of every existing one. A prefix that overlaps gets 400 InvalidRequest, and the configuration stays as it was.

View as Markdown