Retention, Deletion and Legal Hold
In one line: in a system at steady state, deletion is exactly as large a workload as ingest, and it is the one with legal consequences on both sides.
Deletion is half the system
At steady state the fleet writes 43 TB a day and must delete 43 TB a day. Those are the same number, and that reframes deletion from housekeeping into a first-class path with its own capacity, monitoring and failure modes.
If deletion falls behind, storage grows without bound and the cost model breaks quietly. If deletion runs ahead — deleting footage still inside its window — the system has destroyed evidence. Both failures are worse than the equivalent failures on the write path, because both are discovered late.
Who does the deleting
Two mechanisms, and the choice is not obvious.
Storage lifecycle rules let the object store expire objects by age against a prefix. They are free, they run without any service of yours being healthy, and they scale to any object count. They are also blunt: they know only object age, not your policy.
Application-driven deletion walks the index and issues deletes. It can express any policy — per-camera retention, per-site rules, hold-aware logic — and it costs a delete request per object plus the compute to drive it, at 250 objects per second sustained.
| Lifecycle rules | Application-driven | |
|---|---|---|
| Cost | Free | A delete request per object |
| Policy expressiveness | Age and prefix only | Anything the index knows |
| Respects legal hold | Only via object-level lock | Yes, natively |
| Runs when your services are down | ||
| Auditability | Weak — no per-object record | Strong — you log every deletion |
Most real designs use both. Lifecycle rules as the backstop, set slightly longer than policy, so nothing survives indefinitely if the deleter breaks. Application-driven deletion as the primary, because it is the only one that can honour a hold and produce an audit trail.
Setting the backstop longer than the policy is the subtle part. If the lifecycle rule fires at exactly the policy boundary it will race the application and may delete something under hold. Give it a margin — expire at 45 days for a 30-day policy — so it only ever catches genuine neglect.
Legal hold inverts the policy
At some point someone says: preserve everything from cameras 14, 15 and 22 between two dates, because of an incident.
The hold has to defeat every deletion path, including the backstop and including a well-intentioned operator. That means it cannot live only as a flag your deleter checks — a bug or a manual bucket operation would step straight through it. It needs the object store's own immutability primitive, applied to the held objects, so deletion is refused by the storage layer itself.
Holds also have properties people forget:
They are retroactive. The hold arrives after the footage was recorded, so it must be applied to existing objects — which requires finding them, which requires the index, which is another reason the index is the thing you must not lose.
They expire, or they do not. A hold with no release process becomes permanent, and permanent retention of surveillance footage is its own compliance problem. Every hold needs an owner and a review date.
They conflict with erasure requests. A person may have the right to have their personal data deleted, while litigation requires the footage be preserved. These genuinely conflict, and the resolution is legal, not technical. The system's job is to represent the conflict explicitly — surfacing that an erasure request touches held footage and routing it to a human — rather than silently resolving it in either direction.
Proving deletion happened
"We delete after 30 days" is a claim a regulator may ask you to evidence, and the objects are gone, so the evidence has to be a record you kept deliberately.
The deletion log is that record: object key, camera, capture window, policy applied, timestamp, and the actor — usually the scheduler. It is small, it must outlive the footage by a long way, and it must be tamper-evident, since a deletion log an operator can edit proves nothing.
There is a neat property in the key layout from the previous lesson. Because keys encode camera and capture time, the deletion log entries are self-describing too: you can demonstrate that everything from a given camera before a given date is absent, and show the records of its removal, without retaining a byte of the footage.
The three-population model
Putting retention together, the archive is not one thing:
| Population | Retention | Storage | Deletion path |
|---|---|---|---|
| Rolling window | 30 days | Standard / IA | Scheduled, automatic, high volume |
| Flagged incidents | Months to years | Archive tiers, replicated | Reviewed, per-case |
| Under legal hold | Until released | Immutable, locked | Refused by the storage layer |
Almost all bytes are in the first row, almost all value is in the second, and almost all risk is in the third.
Key takeaway
At steady state deletion is the same 43 TB a day as ingest, so it needs its own capacity and monitoring. Run application-driven deletion as the primary path because it is the only one that can honour a hold and produce an audit trail, with a lifecycle rule set looser than policy as a backstop against a broken deleter. Enforce legal holds with the storage layer's own immutability rather than a flag your code checks, keep a tamper-evident deletion log that outlives the footage, and surface erasure-versus-hold conflicts to a human instead of resolving them silently.
Next: live viewing, and how to provide it without paying for it on every camera.