Versioning & Object Lock
Bucket versioning, delete markers, and per-tenant Object Lock — COMPLIANCE and GOVERNANCE retention plus legal hold — for accidental-deletion and ransomware-resistant, immutable object storage.
Bucket versioning, delete markers, and per-tenant Object Lock — COMPLIANCE and GOVERNANCE retention plus legal hold — for accidental-deletion and ransomware-resistant, immutable object storage.
What this area is
Versioning keeps every prior copy of an object instead of overwriting it; Object Lock adds a retention window during which no version can be deleted or altered, even by the account owner.
Operations covered here
GetBucketVersioning/PutBucketVersioning · delete markers · GetObjectLockConfiguration/Put · PutObjectRetention/Get (COMPLIANCE and GOVERNANCE modes) · PutObjectLegalHold/Get · s3:BypassGovernanceRetention
How XNS implements it
cost_center is threaded into all 13 read/write SQL statements in object_lock_handlers.go: the bucket_object_lock table’s primary key is (cost_center, bucket), and object_versions lock columns (retention_mode, retain_until, legal_hold) are keyed (cost_center, bucket, object_key, version_id).
GetObjectLockConfiguration/PutObjectRetention/PutObjectLegalHold rows “OPEN — no passing test,” pending a sync against newer runs. The 2026-08-11 conformance run shows all 39 object-lock-named nodeids passing — newer evidence than that note. Both are stated here rather than picking one silently.
Object data itself lands on the same erasure-coded storage layer as every other object (80 data + 40 parity shards = 120 hosts, corp deployment convention). Requests land on the S3 data plane, port 9000/9443, SigV4-signed, cost_center-scoped.
bucket_handlers.go.object_lock_handlers.go.retain_until. GOVERNANCE mode: bypassable only by a principal holding s3:BypassGovernanceRetention.checkLockProtection) evaluates only the caller's own cost_center; proven by object_lock_handlers_test.go (7 two-tenant isolation tests) and object_lock_e7_verify_test.go (6 verify tests) — reverting any predicate to a bare bucket match fails the isolation suite.How we conform to the S3 protocol
Object Lock, retention, legal hold, and bucket versioning 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.
Object Lock and retention passed clean. All 39 object-lock, retention, and legal-hold nodeids passed in the 2026-08-11 run, plus all but two of the versioning/delete-marker nodeids. Both open gaps sit on the plain, non-locked delete-marker path — not on anything under retention or legal hold.
Full per-test detail, including those two gaps, is on the compatibility matrix, alongside every measured figure and its provenance.
How we compare
Source: the “Versioning & data protection” section of the S3 compatibility matrix, competitor cells from each vendor’s own documentation, researched 2026-06-14. The retired OLD-XNS (MinIO 2020) gateway scored ✗ on every row in this section — bucket versioning and object-lock config both returned HTTP 200 while persisting nothing, the exact “looks successful, does nothing” trap this new gateway was built to close.
| Capability | XNS | AWS S3 | Ceph | MinIO | Wasabi | B2 | Storj |
|---|---|---|---|---|---|---|---|
| Bucket versioning | ✓ | ✓ | ✓ | ✓ | ✓ | ◐ always-on; cannot suspend | ✓ |
| Delete markers | ✓ | ✓ | ✓ | ✓ | ✓ | ◐ partial | ✓ |
| Object Lock — governance | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Object Lock — compliance / WORM | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Legal hold | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| MFA delete | ✗ | ✓ | ✓ | ✗ | ◐ undocumented | ✗ | ✗ |
How applications use it
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",
)
# Turn on versioning
s3.put_bucket_versioning(Bucket="my-bucket", VersioningConfiguration={"Status": "Enabled"})
# Bucket-level default retention: 30-day COMPLIANCE lock on every new object
s3.put_object_lock_configuration(
Bucket="my-bucket",
ObjectLockConfiguration={
"ObjectLockEnabled": "Enabled",
"Rule": {"DefaultRetention": {"Mode": "COMPLIANCE", "Days": 30}},
},
)
# Per-object GOVERNANCE retention, explicit date
s3.put_object_retention(
Bucket="my-bucket", Key="contracts/msa-2026.pdf",
Retention={"Mode": "GOVERNANCE", "RetainUntilDate": "2027-08-12T00:00:00Z"},
)
# Legal hold — independent of retention mode, cleared explicitly
s3.put_object_legal_hold(Bucket="my-bucket", Key="contracts/msa-2026.pdf",
LegalHold={"Status": "ON"})
# List every version of an object
for v in s3.list_object_versions(Bucket="my-bucket", Prefix="contracts/msa-2026.pdf")["Versions"]:
print(v["VersionId"], v["IsLatest"])aws s3api put-bucket-versioning --bucket my-bucket \
--versioning-configuration Status=Enabled --endpoint-url https://relayer.example.com
aws s3api put-object-retention --bucket my-bucket --key contracts/msa-2026.pdf \
--retention '{"Mode":"GOVERNANCE","RetainUntilDate":"2027-08-12T00:00:00Z"}' \
--endpoint-url https://relayer.example.com
aws s3api put-object-legal-hold --bucket my-bucket --key contracts/msa-2026.pdf \
--legal-hold Status=ON --endpoint-url https://relayer.example.comUse cases
A compromised admin credential still can't delete a COMPLIANCE-locked backup before its retain-until date.
For critical shared datasets, using versioning alone (no lock) so a bad overwrite or delete is always recoverable.
Flag specific objects to survive any lifecycle rule or delete request until counsel clears the hold.
For records that must be provably unaltered for a fixed window (financial, audit-log, or compliance archives).
Applications that lean on it heavily
Immutable backup repositories depend on Object Lock GOVERNANCE/COMPLIANCE retention to resist ransomware that targets the backup store itself, not just production data.
The same immutability dependency as Veeam for hardened backup targets.
Writes once and relies on the storage layer, not the application, to enforce non-deletion.
What’s out of scope here
Only AWS S3 and Ceph RadosGW support MFA Delete among the compared vendors; MinIO, Wasabi (partial/undocumented), B2, and Storj don't either. If a workload specifically requires MFA Delete rather than Object Lock, this gateway doesn't cover it today.
FAQ
Is S3 Object Lock enforced per tenant?
Yes. cost_center is threaded into every object-lock SQL statement (13 read/write statements), and tenant isolation is proven by dedicated two-tenant isolation tests — tenant A cannot read or alter tenant B’s lock config or WORM objects.
Does XNS support MFA Delete?
No. MFA Delete is not implemented, matching MinIO, the retired OLD-XNS gateway, and B2/Storj; only AWS S3 and Ceph RadosGW support it among the compared vendors.
Can a bucket administrator delete an object under GOVERNANCE retention?
Only with the s3:BypassGovernanceRetention permission, evaluated per-principal. COMPLIANCE-mode retention cannot be bypassed by anyone until the retain-until date passes.
The versioning and Object Lock rows above are one section of the full S3 compatibility matrix — object operations, buckets, lifecycle, encryption, access control, and replication all get the same treatment.
Explore the platform
Everything you need to go from evaluation to production.