Letting data expire on purpose: TTL as an architecture decision
Not all data deserves to live forever. Designing expiration into the data model, instead of treating it as a cleanup job bolted on later, completely changes a system's scaling profile.
There's an almost universal reflex in database design: keep everything, indefinitely, "just in case it's needed later." For business data with lasting value (a transaction, an order, a contract) that reflex makes sense. For a very different category of data, that same reflex is the root of a scaling problem that shows up months later, silently.
The kind of data that shouldn't live forever
Picture a vehicle's GPS position, reported every few seconds. That data has extremely high value the moment it's generated: someone needs to know where the vehicle is right now. That same data, six months later, almost never has operational value. Nobody is going to query "where was this driver at 3:14pm on a Tuesday half a year ago" except in very specific audit cases, which have probably already been resolved with an aggregated summary, not every individual GPS point.
Keeping that data forever isn't prudence, it's accumulating volume without proportional value. And that volume has a real cost: bigger indexes, slower queries, heavier backups, and a database that grows indefinitely in size even though its useful value doesn't grow at all.
Why "delete it with a job later" isn't the same as designing with TTL
The naive answer is to schedule a cleanup job that periodically deletes old data. It works, but it introduces a strange asymmetry: during the window between when the data stops being useful and when the job runs, it keeps occupying space and remains part of any query that doesn't explicitly filter by date. That job is also one more piece of infrastructure that can fail, run longer than expected under high volume, or simply get forgotten over time.
Designing with TTL from the start, using a native database expiration mechanism instead of an external process, changes the nature of the problem: expiration stops being a maintenance task and becomes a property of the data itself, declared once, enforced consistently by the database engine, without depending on an external job remembering to run.
The design question that actually matters
The decision that matters isn't technical ("how do I implement TTL?"), it's about modeling: does this data represent an ephemeral operational event, or does it represent a business fact that needs to persist? The GPS position from six months ago is the former. The order that was delivered six months ago is the latter. Conflating both categories, and applying the same default retention policy to both, is where the problem originates: either operational junk accumulates indefinitely, or you risk accidentally deleting something that actually had lasting business value.
The lesson
A well-designed system doesn't treat "how long does this data live" as an operational decision made later, by an infrastructure team worried about disk size. It treats it as a product decision, made at the same moment the entity is modeled, with the same seriousness given to defining its fields or its relationships. Data that expires by design isn't data that got less attention. It's data that got the right attention.