Configuring S3 Object Lock for Compliance Spatial Archives

Configuring S3 Object Lock for compliance spatial archives means enforcing Write-Once-Read-Many immutability at the storage layer so regulated geospatial records — environmental baselines, cadastral surveys, defense deliverables — cannot be altered or deleted until a retention clock expires, with legal holds that override any lifecycle rule. This guide is for compliance and infrastructure teams who must produce a legally defensible answer to “prove this survey has not been modified” and cannot rely on application-layer controls that a misconfiguration or a compromised credential could bypass. The subtle decisions are choosing COMPLIANCE versus GOVERNANCE mode correctly, setting a default retention that matches the governing mandate without over-locking, and wiring legal holds so an active hold suspends the lifecycle transitions and expiries described elsewhere in your archive. Get the mode wrong and you either cannot delete data you legally must purge, or you can delete data you legally must keep.

How a Delete Request Is Evaluated

Object Lock is a stack of independent controls — a legal hold, a retention clock, and a retention mode — each of which can independently block a mutation. Understanding the evaluation order is the whole game:

Object Lock delete-request evaluation flow A delete or overwrite request is evaluated against a legal hold, then the retain-until date, then the retention mode. A legal hold blocks unconditionally; an expired retention permits deletion; active retention blocks under COMPLIANCE even for root, and under GOVERNANCE unless the caller has BypassGovernanceRetention. DELETE / overwrite Legal hold active? retain-until in the future? Retention mode? Delete permitted BLOCKED — legal hold overrides lifecycle & expiry BLOCKED — COMPLIANCE even the root account cannot delete BLOCKED — GOVERNANCE unless caller has BypassGovernanceRetention yes no expired yes (locked)

Choosing the Retention Mode

The mode decision is irreversible in one direction and legally consequential, so make it deliberately. GOVERNANCE mode blocks deletions and overwrites for ordinary callers but lets a principal holding the s3:BypassGovernanceRetention permission remove the lock — appropriate for internal data-management policies where an administrator must retain a correction path. COMPLIANCE mode blocks everyone, including the root account, until the retain-until date passes; no principal, no permission, and no support ticket can shorten it. Regulatory records that demand tamper-proof custody — the kind an auditor will test — belong in COMPLIANCE. Operational retention that merely enforces internal discipline belongs in GOVERNANCE.

Two constraints shape the rollout. Object Lock can only be enabled on a bucket at creation time (or via support for existing versioned buckets), and it requires versioning. Enforcing Retention Policy Frameworks therefore starts with the bucket definition itself, not a policy bolted on later.

Provisioning the Lock in Terraform

Codify the bucket, its default retention, and the mode so the archive’s immutability posture is reproducible from source and auditable through pull requests. Map the days directly to the governing regulatory window.

resource "aws_s3_bucket" "spatial_archive" {
  bucket              = "spatial-archive"
  object_lock_enabled = true
}

resource "aws_s3_bucket_versioning" "spatial_archive" {
  bucket = aws_s3_bucket.spatial_archive.id
  versioning_configuration { status = "Enabled" }
}

resource "aws_s3_bucket_object_lock_configuration" "compliance" {
  bucket = aws_s3_bucket.spatial_archive.id

  rule {
    default_retention {
      mode = "COMPLIANCE"
      days = 3650 # 10-year environmental-record retention mandate
    }
  }
}

Default retention stamps every newly uploaded object with a retain-until date computed from its upload time — a survey landed today under this configuration is immutable until 2036. Override per object only to lengthen, never to shorten, and record the governing mandate in object metadata so the retention window is self-documenting. These immutable objects are the evidentiary backstop beneath the lifecycle transitions in Implementing Lifecycle Rules for Shapefile Archives: a rule may move an object to GLACIER, but Object Lock guarantees it cannot vanish mid-window.

A legal hold is an on/off flag independent of the retention clock. It blocks deletion for as long as it is set, even after the retain-until date passes, which is exactly what a litigation hold on a disputed parcel record requires:

# Place an indefinite legal hold on a specific survey record
aws s3api put-object-legal-hold --bucket spatial-archive \
  --key survey/2019/environmental_baseline.gpkg \
  --legal-hold '{"Status":"ON"}'

# Set a longer per-object retention than the bucket default (extend only)
aws s3api put-object-retention --bucket spatial-archive \
  --key survey/2019/environmental_baseline.gpkg \
  --retention '{"Mode":"COMPLIANCE","RetainUntilDate":"2040-01-01T00:00:00Z"}'

Map each dataset class to the window its mandate dictates rather than applying one blanket duration: a ten-year environmental baseline, a permanent cadastral record held under indefinite legal hold, a seven-year contract deliverable. When a retention window finally expires and deletion is authorized, sanitize according to NIST SP 800-88 Rev 1, treating KMS key destruction as the cloud-native equivalent of media destruction. The CRS lineage and provenance those records carry — asserted upstream by CRS Synchronization in Pipelines — are part of the legally significant content the lock protects, not incidental metadata.

Two interactions catch teams out when they extend a lock across a real archive. First, replication and Object Lock must be designed together: to keep an immutable copy in a second region, the destination bucket must itself have Object Lock enabled, and same-mode replication carries the retain-until date across so the replica is protected identically — a replica without its own lock is a deletable back door around the whole scheme. Second, retroactive locking of an existing archive is a batch operation, not a bucket flag. Objects that predate the lock configuration carry no retention, so apply retention to them explicitly with an S3 Batch Operations job that issues put-object-retention across the inventory, and verify coverage against a bucket inventory report rather than assuming the default retention reached historical uploads.

Minimum-duration billing is the cost tail of any retention decision. A ten-year COMPLIANCE lock means those objects cannot leave their storage class early without penalty, so the retention window and the tier policy have to agree — locking an object into COMPLIANCE while a lifecycle rule tries to expire it produces a rule that silently no-ops for a decade. Price the locked footprint over its full window, since the commitment is contractual the moment the object lands.

Verifying Immutability

A lock you have not tested is a lock you do not have. Confirm the configuration, inspect an object’s retention, then attempt a deletion and confirm it is refused.

aws s3api get-object-lock-configuration --bucket spatial-archive \
  --query "ObjectLockConfiguration.Rule.DefaultRetention"

Expected output — the mode and window match the mandate:

{
  "Mode": "COMPLIANCE",
  "Days": 3650
}

Now prove a delete is actually refused on a locked object:

aws s3api delete-object --bucket spatial-archive \
  --key survey/2019/environmental_baseline.gpkg \
  --version-id "3sL4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY"

Expected result — the storage layer, not the application, refuses:

An error occurred (AccessDenied) when calling the DeleteObject operation:
Access Denied because object protected by object lock.

An AccessDenied citing object lock is the proof auditors want: the immutability is enforced below any credential. If the delete succeeds, either versioning is disabled, the object predates the lock configuration, or the retain-until date has already passed — each of which is a finding to remediate before certifying the archive.

Diagnosing Lock Failures

Symptom Root Cause Resolution
Object deletes despite lock config Object uploaded before Object Lock was enabled, or no per-object retention applied Re-copy objects post-configuration; confirm default retention stamps new uploads
Cannot enable Object Lock on existing bucket Lock requires enablement at creation or via support, plus versioning Create a new locked bucket and migrate; enable versioning first
Retention cannot be shortened after error COMPLIANCE mode forbids shortening even for root Accept the window; use GOVERNANCE only where a correction path is legally acceptable
Object expired but must stay Retention lapsed with no legal hold set Apply a legal hold, which overrides expiry until explicitly removed

Operational Execution Checklist

Part of the Spatial Data Archival knowledge base.