← S3 compatibility matrix S3 resource guide · Lifecycle & tiering

Lifecycle & Tiering

Automatic expiration and noncurrent-version cleanup, config CRUD plus an execution sweep — with one honest architectural boundary: storage-class transitions to a colder tier are N/A, because XNS runs a single distributed erasure-coded tier, not multiple storage classes.

Real expiration sweep, not config-only Noncurrent-version expiration — pass Storage-class transitions — N/A


What this area is

Lifecycle rules automatically expire or transition objects — without a client running a delete job.

S3’s lifecycle model covers two mechanisms: expiration (delete an object, or a noncurrent version, after N days or at a fixed date) and transition (move an object to a cheaper storage class after N days).

Operations covered here

GetBucketLifecycle/Put/Delete · current-version expiration · noncurrent-version expiration · storage-class transitions


How XNS implements it

Expiration is fully implemented: config CRUD plus an execution sweep that actually deletes.

Not just a stored rule nobody enforces. lifecycle_handlers.go handles config CRUD and the sweep; lifecycle_expiry_header.go adds an x-amz-expiration header (format expiry-date="<date>", rule-id="<id>") to PutObject and HeadObject responses when an enabled rule with an Expiration matches — the matcher evaluates live object tags at response time, not just at rule-write time.

The reason transitions are N/A, stated plainly: XNS stores every object on one distributed erasure-coded tier — the corp deployment convention is 80 data shards + 40 parity shards across up to 120 hosts per object (Reed-Solomon DataNum/ParityNum are per-cost-center configuration, not a fixed code constant). There is no second, cheaper tier for a lifecycle rule to move data into; redundancy and geo-distribution are inherent to every object from the moment it’s written, not something a rule turns on later.

Lifecycle expiration
Current-version delete after N days or at a fixed date. Real sweep, not config-only.
Noncurrent-version expiration
Cleans up old versions on a versioned bucket independently of current-version rules.
x-amz-expiration header
Returned on matching PutObject/HeadObject responses so a client can see its own expiry without a separate lifecycle-config fetch.
GetBucketLifecycle round-trip
Prefix-only rules emit a top-level <Prefix>, no <Filter> wrapper — fixed to match AWS's own round-trip shape.
Rule-ID validation
A rule ID over 255 characters is rejected 400 InvalidArgument rather than silently truncated.
Storage-class transitions
Architecturally N/A — see What's out of scope on this page.


How we conform to the S3 protocol

Measured against the public ceph/s3-tests suite — and published.

Expiration and noncurrent-version expiration are verified against the same public conformance suite the rest of the industry is measured by, test by test. We publish the full per-test result, including what still fails, on the compatibility matrix rather than summarizing it here.

Where we deliberately differ. Storage-class-transition and cloud-tiering tests in the full ceph/s3-tests suite are excluded from this build's count entirely — the feature they test is architecturally N/A here (see What's out of scope on this page), not a failure we're hiding.

Expiration and noncurrent-version expiration pass clean; one header/tag-interaction edge case remains open. Full per-test detail is on the compatibility matrix, alongside every measured figure and its provenance.


How we compare

N/A cells mean architecturally not applicable, not missing.

Source: the “Lifecycle & tiering” section of the S3 compatibility matrix, competitor cells from each vendor’s own documentation, researched 2026-06-14. The N/A cells carry the same footnote as the matrix (single distributed erasure tier) — read as “architecturally not applicable,” not “missing.”

Competitor figures from each vendor’s official documentation, researched 2026-06-14.
CapabilityXNSAWS S3CephMinIOWasabiB2Storj
Lifecycle expirationobject TTL only, no lifecycle config
Transitions to colder tiersN/A single distributed erasure tierN/A
Noncurrent-version expiration
Multiple storage classesN/ASTANDARD + REDUCED_REDUNDANCY onlyN/A


How applications use it

Write a lifecycle rule once; the sweep enforces it going forward.

boto3

import boto3
s3 = boto3.client(
    "s3",
    endpoint_url="https://relayer.example.com",
    aws_access_key_id="AKIA...",
    aws_secret_access_key="...",
    region_name="us-east-1",
)
# Expire objects under a prefix after 90 days; expire noncurrent versions after 30
s3.put_bucket_lifecycle_configuration(
    Bucket="my-bucket",
    LifecycleConfiguration={
        "Rules": [{
            "ID": "expire-staging-90d",
            "Status": "Enabled",
            "Filter": {"Prefix": "staging/"},
            "Expiration": {"Days": 90},
            "NoncurrentVersionExpiration": {"NoncurrentDays": 30},
        }]
    },
)
# The response echoes x-amz-expiration when an enabled rule matches
resp = s3.put_object(Bucket="my-bucket", Key="staging/build-4821.tar.gz", Body=data)
print(resp["ResponseMetadata"]["HTTPHeaders"].get("x-amz-expiration"))
# Round-trip the config back
cfg = s3.get_bucket_lifecycle_configuration(Bucket="my-bucket")
print(cfg["Rules"])

AWS CLI

aws s3api put-bucket-lifecycle-configuration --bucket my-bucket \
  --lifecycle-configuration file://lifecycle.json \
  --endpoint-url https://relayer.example.com
aws s3api get-bucket-lifecycle-configuration --bucket my-bucket \
  --endpoint-url https://relayer.example.com
aws s3api head-object --bucket my-bucket --key staging/build-4821.tar.gz \
  --endpoint-url https://relayer.example.com


Use cases

Where this matters in practice.

  • Automatic expiration of temp/staging data
  • CI artifact cleanup
  • Log retention windows
  • Cost control on versioned buckets
  • Abandoned multipart cleanup
Automatic expiration of temp/staging data

Build artifacts, upload scratch space, or ETL intermediates deleted N days after write with no cron job.

CI artifact cleanup

Expire build outputs after a fixed retention window, keyed by prefix (e.g. ci/branch-name/).

Log retention windows

Expire logs after a compliance- or cost-driven number of days.

Cost control on versioned buckets

Noncurrent-version expiration prevents unbounded version accumulation from inflating stored bytes.

Abandoned multipart cleanup

Paired with the background multipart reaper described on the core object operations page.


Applications that lean on it heavily

Real software, named.

  • rclone
  • Backup tools with retention policies (restic, Duplicati)
  • Internal log pipelines
rclone

Can drive bucket lifecycle configuration directly (rclone backend commands) as part of a retention pipeline.

Backup tools with retention policies (restic, Duplicati)

Their own forget/pruning policies pair naturally with S3-side noncurrent-version and expiration rules as a second, storage-enforced safety net.

Internal log pipelines

XNS's own audit-log-to-Loki path (NDJSON sink + Alloy tail) is exactly the kind of write-once, expire-later workload this mechanism targets.


What’s out of scope here

Storage-class transitions are architecturally not applicable, not missing.

The boundary, stated plainly

There is one distributed erasure-coded tier; a lifecycle rule can expire or clean up noncurrent versions, but it cannot move an object to a “colder” class because no second class exists. If a workload specifically needs S3-Glacier-style tiered storage economics, that's a different architecture than this gateway offers today.


FAQ

Lifecycle and tiering questions, answered directly.

Yes. GetBucketLifecycle/Put/Delete are real, DB-backed handlers with an execution sweep, plus an x-amz-expiration response header on PutObject and HeadObject when an enabled rule matches.

No — storage-class transitions are not applicable to this architecture. XNS runs one distributed erasure-coded tier (80 data + 40 parity shards across up to 120 hosts, by corp deployment convention) rather than multiple storage classes, so there is no colder tier to transition into.

Yes, including noncurrent-version expiration, which is a real, conformance-tested handler distinct from current-version expiration.



See the full conformance picture.

The lifecycle and tiering rows above are one section of the full S3 compatibility matrix — object operations, buckets, versioning, encryption, access control, and replication all get the same treatment.


Claims on this page last verified
© Copyright - SCP, Corp | Xa Net Services and Affiliates