Setting Up Object Storage Versioning for Data Protection

Losing an object or accidentally overwriting it can halt a service for hours. We implement object storage versioning turnkey: we select retention modes, test rollback, and hand over ready-to-use rules to your team. Data recovery time is reduced severalfold.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1365
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1330
  • B2B Advance company logo design
    B2B Advance company logo design
    776
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1077
  • AIDER company logo development
    AIDER company logo development
    1022
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1113

What Breaks Without Object Storage Versioning

A failed job in a processing pipeline most often corrupts data through object overwrites: a client or script issues a PUT over an existing key, and the previous revision disappears at that very moment.

The bottleneck here is the object storage interface itself: without versioning, a write operation is final and leaves no trace, so the previous content can only be restored from an external backup, if one exists at all and was taken after the last correct state.

The second scenario is cascading deletion by an erroneous prefix.

One typo in the path, an extra slash, or a regular expression in a cleanup script, and the delete command wipes out not a temporary directory but the entire working branch: thousands or millions of objects are removed in bulk within seconds.

There is no protection against deletion because deletion is irreversible — an object does not retain a previous state to return to, and there is no way to stop the process: requests are sent in parallel and complete successfully.

Change history is a separate loss. Even when an object is not deleted but merely changed, without object storage versioning it is impossible to answer what the file was an hour ago and who replaced it with what.

Data rollback turns into manual work: correlating access logs, searching for copies among consumers, re-exporting from the source — all against the backdrop of downtime for a service that reads the corrupted object.

Finally, storage integrity suffers: it is impossible to prove that the content has not changed since it was written, and the discrepancy between what was uploaded and what is stored is discovered too late — when a report has already been built or a decision made based on that data.

All three failure modes share one thing: the bottleneck is not in the application code but in the absence of versions at the storage level itself.

We will break down how this is addressed: which versioning modes are enabled on a bucket, how lifecycle rules and delete markers are configured, and what rolling data back to a specific object revision provides.

What Versioning Provides: Rollback and Deletion Protection

With versioning enabled, modifying an object does not overwrite it but creates a new version with its own identifier; deletion places a delete marker, while previous copies remain accessible by number. The failure class of "data was overwritten and lost" disappears entirely.

Rolling back to a previous version is an operation on a single object, not restoring the entire set from a backup. The return takes seconds, and the recovery point coincides with the moment of the last successful write, not with the snapshot time. The share of recoverable overwrites approaches completeness.

Protection against cascading deletion relies on object lock: a version is assigned a retention period before which it cannot be erased even by an account with full permissions.

An erroneous script, an export pipeline failure, or a compromised key will not destroy data within the retention window.

Managing object versions without lifecycle rules makes storage more expensive: volume grows in proportion to the number of overwrites, not the number of files. Rules transition outdated versions to a cold class and delete them by age, leaving the required rollback window.

We set the version retention period based on the actual error detection cycle: if a discrepancy in reports is noticed on the tenth day, the rollback window must be wider. Such a margin does not prevent deleting garbage and keeps storage growth predictable.

Comparison of Storage Modes: When Each Approach Is Appropriate

The version storage mode is chosen to match the data profile: how often an object is overwritten, whether rollback is needed after a deployment failure, and whether immutability requirements exist.

A mistake in either direction is costly — either the bucket grows indefinitely, or the previous config revision can no longer be restored.

Mode When it fits Limitations
Without versioning Temporary exports, cache layers, build directories that are restored from the source Overwrite is irreversible: previous content is lost immediately, rollback to a previous release is impossible
Permanent versioning Configurations, release manifests, data where every revision matters Every overwrite and deletion creates a version — volume and listing time grow without limit
Versioning with a lifecycle policy Production data and artifacts with a predictable period of relevance A well-calibrated version retention period is required: a short one removes rollback capability, a long one is equivalent to permanent mode
Object lock for a period Regulatory documents, backups, access logs While the lock is active, the object cannot be deleted or overwritten even by administrators

Deletion behavior also differs: in a versioned bucket, deletion places a marker, the object disappears from listings, but revisions remain and are restored with a single operation.

How to Choose a Mode for the Load Profile

Look at two parameters: the overwrite frequency of a single object and the rollback depth required by the process.

If a file is written once and then only read — object lock for a period is sufficient; if it is overwritten daily — versioning plus a rule that removes versions older than the agreed period.

Implementation Stages: From Storage Audit to Handover

Versioning is enabled with a toggle on the bucket, but without prior inventory this leads to volume growth, unexpected overwrites, and deletions that no one planned to roll back.

That is why we work in stages, and each has a verifiable readiness criterion: until it is met, we do not move to the next one.

  1. Storage audit. We inventory buckets and prefixes, calculate volume and the share of active objects, and identify all consumers — services, backup jobs, analytics. We record where versioning is already partially enabled and where writes originate.
  2. Placement and replication design. We decide which prefixes to version, which to move to a cold class, and what to duplicate to another region. We determine the failover switching procedure for a site failure and the data divergence time.
  3. Enabling the mode. We configure bucket state and object lock for immutable data, and set the order across buckets so that writing services do not receive errors at the moment of enablement.
  4. Policy configuration. Lifecycle rules: deleting outdated versions and delete markers, transitioning old copies to a cheaper class, and deleting incomplete uploads. Separately — who is authorized to delete a version.
  5. Rollback verification. We restore the previous version individually and in bulk, test behavior when a name is overwritten, measure recovery time, and confirm that access logging is being written.
  6. Documentation handover. We provide a map of prefixes and policies, a roles and access diagram, an on-call guide for rollback and deletion, and train the shift using a real scenario.

Stage Readiness Criteria

A stage is closed when every prefix has an owner and an assigned policy, no writing service received failures when the mode was enabled, object recovery fits within the agreed time, and the operations log is confirmed by an export.

If even one item does not match, we remain at the stage — it is cheaper to refine the design than to deal with mass deletion in production.

What We Hand Over: Policies, Designs, Procedures

We hand over not access to the control panel but a set of artifacts from which the on-call shift can reproduce the configuration from scratch and not break data protection. Each document reflects the actual state of the storage at the time of handover, not what it was at launch.

  • Storage and bucket configuration: enabled versioning, lifecycle rules, object lock, limits on the number and retention period of versions.
  • Placement and replication design: where the primary bucket is, where the copy goes, and how long recovery from it takes.
  • Access policies and roles: who reads, who writes, who is authorized to delete versions and remove locks; separately — service accounts for applications.
  • Version handling procedures: when a version moves to archive, how deleted items are stored, and in what order rollback is performed.
  • Team instructions: what to check on a schedule, which signals are considered emergencies, and in what order to act during a failure.
  • Storage documentation: bucket map, integration points, known limitations, and configuration change log.

How Artifacts Live After Handover

Configurations are stored in a repository, changes go through approval rather than being edited manually in the panel. Documentation is updated by the same change as the configuration — otherwise it diverges from reality within a couple of months.

Once a quarter, we reconcile the described state with the actual one and hand over a list of discrepancies.

Case Study: Eliminating the Overwrite Failure Class

The customer writes to object storage around the clock: nightly exports, database snapshots, a stream of events from services.

Object overwrites happen constantly, and one failing script wiped out several days' worth of snapshots — there was nothing to roll back with because the new version of an object irreversibly overwrote the previous one.

We enabled bucket versioning on S3-compatible storage and built lifecycle rules around it: fresh versions of each object are retained, outdated ones transition to a cold class, and access to version deletion is moved to a separate role with confirmation.

What the Metrics Showed

Object recovery time dropped from several hours of manual reassembly from backups to minutes: the required version is restored directly by timestamp.

The share of successful rollbacks grew from 40% to 100% — if a version exists, rollback no longer depends on the completeness of the nightly copy. The number of incidents in the "data lost" class over the quarter was zero.

What Turned Out to Be the Bottleneck

Registry volume: with constant overwriting of small objects, it doubled within weeks. Separation helped — hot logs were moved to a bucket without versioning, while protection was kept where data integrity is critical.

The second nuance was permissions: some commands by inertia deleted objects instead of writing a new version, so the access policy was restricted and documented in the procedures.

What to Do If the Storage Is Already Filled?

Protection can be enabled on a running storage — there is no need to stop writes or empty the bucket.

Already uploaded objects are not overwritten or copied again: they remain accessible at the same addresses and receive a null version marker, while only subsequent writes and overwrites are versioned.

Applications that read data via old links continue to work — backward compatibility is preserved, and code does not need to be rewritten.

The transition order is as follows: enable versioning, attach lifecycle rules for deleting outdated versions, and start background organization of historical objects. Writes and reads are not interrupted between steps, so no maintenance mode transition is required.

Transition Option When it fits Limitations
Enabling on an existing bucket filled storage, no window for downtime historical objects remain without versions, retention rules are configured separately
Migration to a new bucket time is available for background copying data resides in two places, application reconfiguration is needed
Phased by directories large volumes, different teams protection is heterogeneous, deadlines are harder to track

The main limitation is that volume grows in proportion to the number of overwrites: in active directories, storage increases by 2-5 times. This is remedied by a lifecycle that retains the latest versions and cleans up the rest; otherwise, a filled storage quickly hits the quota.

Another nuance: a regular object deletion does not remove it from storage while versions are alive — first the marker is removed, then the versions themselves are deleted.

Therefore, we test protection with scenarios on a test bucket before enabling it on the primary one: restoring an overwritten file, deleting a directory, and rolling back to a previous state.

Technical Concerns: Compatibility, Load, Migration

Versioning usually surfaces in a project at the stage when someone has deleted an object and needs to figure out how to bring it back.

Engineers' concerns are predictable: will the load on storage increase, will compatibility with already running services break, and how to limit retention periods and role-based access.

Will writes slow down after versioning is enabled?

An object is not copied twice: a version identifier and a metadata entry are added to it. Write latency remains in the same order — the load shifts not toward response time but toward storage volume, which grows due to outdated versions.

Will storage grow indefinitely?

No. A lifecycle rule retains the last N versions per object, moves the rest to a cold class or deletes them, and cleans delete markers with a separate rule. Registry volume becomes predictable: it is tied to version depth, not the number of changes.

Will services need to be stopped for migration?

Versioning is enabled on an existing bucket without downtime; addressing and the interface remain the same. Objects uploaded before enablement receive an empty version ID and are read as before; deletion semantics change — instead of the object disappearing, a marker appears.

Scripts and services continue to work, but their behavior should be rechecked in a test environment.

How should retention periods be set?

Version depth and the lifetime of outdated versions are set in the requirements before implementation: for logs and backups these are different values. Rules apply by prefix, so different data types have their own retention policy.

Who will be able to permanently delete data?

Role-based access separation: the right to delete a version and to remove an object lock is granted separately. A developer writes and reads data but cannot wipe out history; every such action is recorded in the log.

Let's Discuss the Task: We Will Assemble a Design and Implementation Plan

We start the conversation not with pricing but with your data: what is stored in object storage, which services write and read objects, where versioning is already enabled, and where it is yet to be added.

This is the task discussion — from it grows the solution design, not a set of generic recommendations.

Based on the conversation, we send:

  • solution design: buckets and prefixes, object naming rules, separation by environment and access roles;
  • a set of versioning and lifecycle policies — how many versions and deleted objects we keep in the hot layer, what goes to archive, and when an object is permanently deleted;
  • protection rules against accidental deletion: version locking, prohibition of deletion without the required permissions, separate accounts for services and for people;
  • a staged implementation plan with time estimates: where versioning is enabled immediately, where a replica is first raised, and at what point applications are switched;
  • verification criteria: control scenarios for restoring an overwritten and deleted object, measuring access time to a previous version, and testing rollback to the previous mode;
  • the scope of documentation to hand over: storage design, policy descriptions, recovery procedures, and instructions for the on-call shift;
  • a post-launch support plan: monitoring version volume growth, policy review, and incident response procedures.

Describe the task in general terms — we will come back with a time estimate and an implementation plan.