Object versioning is a cloud storage feature that keeps multiple versions of the same object in a bucket. When versioning is enabled, overwriting an object creates a new current version while the previous one is retained as a noncurrent version, and deleting an object hides it instead of erasing it. Each version receives its own version identifier and can be read, restored or permanently removed.
In object storage, objects are immutable: a change always means writing a whole new object. Versioning turns that property into a built-in history, protecting data against accidental overwrites, faulty application releases and many forms of malicious deletion. It is available in S3 and S3-compatible services, Google Cloud Storage and Azure Blob Storage, with small differences in terminology and behavior.
How object versioning stores changes
With versioning enabled, every successful write to a key produces a new version with a unique version ID assigned by the service. A plain read returns the current version; a read that specifies a version ID returns that exact version. Listing operations can show either only current objects or all versions with their timestamps.
Deletion works differently from an unversioned bucket. A simple delete request adds a delete marker, a placeholder that becomes the current version and makes the object appear absent. The data remains as a noncurrent version, so removing the delete marker restores the object. Only a delete request that names a specific version ID removes data permanently.
The table below shows how common operations behave with and without versioning.
| Operation | Unversioned bucket | Versioned bucket |
|---|---|---|
| Overwrite an object | Old data is replaced | Old data becomes a noncurrent version |
| Simple delete | Object is removed | A delete marker is added |
| Delete by version ID | Not applicable | That version is removed permanently |
| Read without version ID | Returns the object | Returns the current version |
| Restore an older state | Requires a separate backup | Copy an older version over the current one |
Versioning states and provider variants
In S3, a bucket has three versioning states: unversioned, enabled and suspended. Once enabled, versioning cannot return to the unversioned state; it can only be suspended. While suspended, new writes receive a null version ID and overwrite one another, but existing versions remain and continue to incur storage charges.
| Service | Feature name | Notable behavior |
|---|---|---|
| Amazon S3 | Bucket versioning | Delete markers, suspend but not disable, optional MFA delete |
| Google Cloud Storage | Object versioning | Noncurrent versions identified by a generation number |
| Azure Blob Storage | Blob versioning | Versions created automatically on each write, complements soft delete |
| S3-compatible stores | Bucket versioning | Support for markers and lifecycle rules varies by product |
Versioning is often a prerequisite for other features. Cross-region replication in S3 requires it on both source and destination buckets, and write-once-read-many protection through object lock depends on it as well, because retention applies to individual versions.
Object versioning compared with related protections
Versioning is one layer in a data protection strategy, not a complete one. It protects against changes made inside the same bucket, but anyone with permission to delete specific versions, or to delete the bucket, can still destroy the history.
| Mechanism | Protects against | Does not protect against |
|---|---|---|
| Object versioning | Overwrites and simple deletes | Deliberate deletion of versions by privileged users |
| Soft delete | Accidental deletion within a retention window | Overwrites, in some implementations |
| Object lock | Any deletion before the retention date | Loss of the whole account or region |
| Replication | Regional outage, single-bucket loss | Replicated corruption, unless versioned |
| Separate backup | Account compromise and logical errors | Nothing on its own if stored in the same account |
For ransomware resilience, the strongest combination is versioning plus object lock, with replication to a bucket in a separate account whose credentials are not shared with production.
Managing cost with lifecycle rules
Every version is a full copy of the object, billed at normal storage rates. A file overwritten daily keeps accumulating versions, so storage consumption can grow far beyond the visible data size. Lifecycle rules are the standard control: they expire noncurrent versions after a number of days, keep only a fixed number of recent noncurrent versions or move them to cheaper storage classes.
- Expire noncurrent versions after 30 to 90 days for most application data, longer for regulated records.
- Keep a fixed number of newer noncurrent versions, for example three to five, for frequently rewritten files.
- Transition noncurrent versions to an infrequent-access or archive class before expiring them.
- Add a rule that removes expired delete markers, which otherwise clutter listings and slow some operations.
- Clean up incomplete multipart uploads, which are billed but never appear as objects.
Common mistakes with object versioning
The most frequent mistake is enabling versioning without lifecycle rules, which leads to storage bills that grow silently for months. The opposite mistake is assuming that versioning alone is a backup: an attacker with sufficient rights can delete every version in minutes unless deletions are locked or require extra authentication.
Applications also misbehave when they ignore versions. Tools that list only current objects report a small bucket size while the bill reflects all versions, and high-churn keys, such as a log file rewritten every minute, can create millions of versions that slow listing operations. Writing new keys instead of rewriting one key is usually the better pattern.
The idea in brief
Imagine a document folder that quietly keeps a copy every time someone saves over a file. If a colleague replaces a contract with the wrong text, or throws it away, the earlier copy is still in the folder, and you can bring it back with a few clicks.
Object versioning gives cloud storage that safety net. The cost is that every saved copy takes up space, so organizations also set rules about how long old copies are kept.
A practical scenario
A media company stores its website images and configuration files in an object storage bucket. A deployment script with a path error overwrites 12,000 product images with placeholder files on a Friday evening. Because versioning is enabled, the operations team lists the noncurrent versions written before the incident and copies them back over the current ones with a short script.
The website is restored in under an hour without touching the nightly backup. Afterward, the team adds a lifecycle rule that keeps noncurrent versions for 60 days and moves them to an infrequent-access class after 14 days, and it enables object lock on the backup bucket in a separate account.