A delete call on a versioned object store returned success, yet the stored bytes are still billed — what actually happened?
answer
- success does not mean removal
- a marker is a version, not an erase
- listings show current versions only
- hidden is not the same as unstored
- naming a version is the irreversible call
basics
~20 sThe delete wrote a marker that became the key's current version and hid it from ordinary listings and reads. The earlier versions still exist and still occupy paid storage until something removes them by version identifier.
solid answer
~40 sOn a versioned store, a delete call that names no version does not remove anything — it adds a **delete marker** as the key's new current version. A plain read then behaves as if the object is gone, and a plain listing omits the key entirely, because both only ever see the current version. Underneath, every prior version is intact, which is why the storage line on the bill does not move: the marker itself is small metadata, while the real bytes are all still there. That is the point of a soft delete — it makes the mistake reversible. Removing the marker by its version identifier makes the previous version current again. Actually freeing the bytes takes a version-targeted delete, or an age-based rule that expires non-current versions.
code
json · 9 lines{
"key": "records/2031/scan-00412.tiff",
"currentVersion": "v4",
"versions": [
{ "id": "v4", "deleteMarker": true, "sizeBytes": 0, "storageCharged": "metadata only" },
{ "id": "v3", "deleteMarker": false, "sizeBytes": 4194304, "storageCharged": "full object" },
{ "id": "v2", "deleteMarker": false, "sizeBytes": 4190112, "storageCharged": "full object" }
]
}go deeper
Recall that on a versioned store a delete without a version identifier hides the key rather than erasing it, and that the object can be brought back. Knowing success does not mean removal is the point.
Explain the mechanics: the marker becomes the current version, plain listings enumerate current versions only, the prior versions keep their bytes and their charges, and removing the marker by identifier restores the key.
Demonstrate the operating consequences: storage that climbs on a store with flat live data, markers stacking under retries, and the fact that reversibility disappears the moment a caller can issue version-targeted deletes.
Frame the standard for other teams: soft delete plus an expiry age for non-current versions, with the age derived from how long this organisation actually takes to notice a wrong delete rather than from a storage budget.
## What a delete call does when versioning is on There are really two different delete operations on a versioned object store, and they are distinguished by whether the caller names a version: - **A delete with no version identifier** is a *soft delete*. The store appends a **delete marker** as a new version of the key and makes it current. No bytes are removed. - **A delete that names a version identifier** is a *permanent* removal of exactly that version. Those bytes are gone, and if the version named is a delete marker, removing it un-hides the key. The same API call, with and without one parameter, is the difference between a reversible action and an irreversible one. That is the single most useful thing to be able to say about this mechanism. | Operation | What is written | What a plain read sees | Bytes freed | |---|---|---|---| | Write to an existing key | a new version, now current | the new object | no | | Delete without a version | a delete marker, now current | object not found | no | | Delete of a marker version | nothing; the marker is removed | the previous version | no | | Delete of a content version | nothing; that version is removed | unchanged, unless it was current | yes | ## Why the key disappears from listings A plain listing enumerates **current versions**, and skips any key whose current version is a delete marker. So the key vanishes from the application's view completely — this is not a filtered or greyed-out entry, it is absent. A version-aware listing, which asks the store for all versions rather than current ones, still shows the key, its marker, and every retained version beneath it. This is what makes the situation confusing in practice: an engineer checks the listing, sees nothing, and concludes the data is gone, while the storage total on the bill has not moved by a byte. Both observations are correct and both follow from the same mechanism. ## Why the bill does not move Storage is charged on what is stored, and a soft delete stores *more*, not less: - Every non-current version still holds its full object bytes and is charged for them. - The delete marker adds a small amount of metadata. It is charged as metadata rather than as object bytes, so it barely registers — but it is one more version. - Deleting the same key repeatedly stacks markers. Each call appends another one, so a retry loop against an already-deleted key quietly grows the history. The practical consequence is that 'delete everything under this prefix' is not a cost-reduction action on a versioned store. It is a visibility action. Cost only falls when versions themselves are removed. ## Undoing a soft delete Recovery is a single operation per key and needs no backup: 1. List the key's versions in a version-aware way and find the marker at the top. 2. Delete **that marker version**, by its identifier. 3. The version beneath it becomes current again, and ordinary reads and listings work exactly as before. Nothing is copied and nothing is restored — the object was never moved. This is why a soft delete is the right default for stores holding data a human can mistakenly delete: the wrong call is undone in seconds rather than recovered in hours. ## Actually removing the bytes When removal is what you genuinely want, there are two routes, and they differ in blast radius: - **Version-targeted deletes.** Enumerate versions and remove them explicitly. Precise, irreversible, and a job rather than a call for anything at scale. - **An age-based rule on non-current versions.** Configure the store so a version that has been superseded for longer than some number of days is removed automatically. This is the sustainable answer, because it bounds history growth without anyone remembering to run anything. Choosing the age is the real decision, and it is the same question as for overwrites: how long does it take this organisation to notice a wrong delete? Set the window shorter than that and the soft delete was decoration. ## The trap to name in an interview Two failure modes follow directly from the mechanism, and naming them is what separates a mechanical answer from an operating one. First, a store that gets heavy delete-and-rewrite traffic accumulates markers and versions indefinitely, so its storage cost drifts upward while the live data set stays flat. Second, a team that has convinced itself deletes are reversible may not have checked whether the caller doing the deleting can also issue version-targeted deletes — the reversibility only holds for the soft form.
- What does a second delete call on an already soft-deleted key do?It appends another delete marker and returns success again. Markers stack, so a retrying client can leave several on one key. Un-hiding then means removing the topmost marker — and repeating until the current version is real content rather than another marker.
- The application reports the object as missing but storage has not dropped. Which call would prove the bytes are still there?A version-aware listing of that key. It returns the marker as the current version and every retained version beneath it, with sizes. A plain read or plain listing cannot show this, because both are defined to see only the current version.
- Why is a soft delete not enough on its own for a store you want to shrink?Because it never frees bytes. Shrinking requires removing versions — either version-targeted deletes or an age-based rule that expires non-current versions after a chosen number of days. Until one of those runs, deleting keys only changes what is visible, not what is stored.
Crossing a name off the register does not empty the room. Everyone reading the list believes nobody is in there, and the space stays rented until someone actually clears it out.
saying these in an interview costs you the question
- Says the bytes are gone because the delete returned success
- Thinks a key hidden from listings stops being charged
- Expects a plain listing to still show a soft-deleted key
- Confuses hiding the current version with removing a version
- Believes undoing the delete needs a restore from backup
- Assumes one delete call per key can only ever add one marker