# TTL strategies — sliding TTL and a per-thread checkpoint cap?

**URL:** <https://forum.langchain.com/t/ttl-strategies-sliding-ttl-and-a-per-thread-checkpoint-cap/4622>\
**Category:** LangSmith Product Help\
**Created:** [September 28, 2026, 5:30pm UTC](https://forum.langchain.com/t/ttl-strategies-sliding-ttl-and-a-per-thread-checkpoint-cap/4622 "2026-09-28T17:30:31Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![santosh-nallur](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/santosh-nallur/32/3178_2.png) [@santosh-nallur](https://forum.langchain.com/u/santosh-nallur)\
**Post date:** [September 28, 2026, 5:30pm UTC](https://forum.langchain.com/t/ttl-strategies-sliding-ttl-and-a-per-thread-checkpoint-cap/4622/1 "2026-09-28T17:30:31Z")

</div>

Hi team,

I’ve been working through the thread/checkpoint TTL model on LangGraph Platform (`checkpointer.ttl` in `langgraph.json`, plus per-thread `ttl` via the Threads API) and I’ve read the existing threads on this — [Checkpoint cleanup (#3037)](https://forum.langchain.com/t/checkpoint-cleanup/3037), [How to handle growing checkpoint blob (#4448)](https://forum.langchain.com/t/how-to-handle-growing-checkpoint-blob/4448), [configuring TTL via env vars (#4253)](https://forum.langchain.com/t/how-to-configure-thread-checkpointer-ttl-when-deploying-the-langgraph-server-with-docker-using-environment-variables/4253), and the [keep\_latest pruning proposal (#4291)](https://forum.langchain.com/t/proposal-add-safe-keep-latest-pruning-to-postgressaver/4291).  
Also the official docs on [configure ttl](https://docs.langchain.com/langsmith/configure-ttl)

Those cover the pieces individually, but I couldn’t find one place that ties together how TTL is supposed to coexist with **human-in-the-loop (HITL) _and_ replay/time-travel debugging**. I want to confirm my understanding and raise two potential feature-shaped questions.

## **My understanding (please correct)**

- **`delete`** : at expiry, the entire thread (runs + all checkpoints + blobs + writes) is removed. The timer is **absolute** — it starts when the TTL is applied and does **not** refresh on activity.

- **`keep_latest`** : here the docs are genuinely ambiguous to me. I can read it two ways:

The rest of this post assumes **Interpretation A**.

If that’s right, then:

## **1. HITL + replay seem to be in tension under any single strategy**

- `keep_latest` preserves the latest checkpoint → **HITL survives** , but it prunes the older checkpoints that **replay/time-travel/debug** depend on.
- `delete` keeps the full chain (so replay works) but only until the absolute deadline, after which **both** HITL and replay are gone.

So it looks like there’s **no strategy that supports HITL + full replay history beyond the TTL window** — you must size `delete` to cover your entire replay/debug horizon, or disable TTL and manage growth manually. **Is that the intended model?** Is there a recommended pattern for “keep the latest for continuity/HITL, but retain the last N checkpoints (not just 1) for replay”?

## **2. Is there a sliding TTL for `delete`?**

For long-running conversations that stay active for many days, `delete` will remove an _active_ thread at the deadline regardless of activity. Today the workarounds I see are:

- switch to `keep_latest` (loses replay history), or
- `PATCH /threads/{id}` with a fresh relative `ttl` on each activity to roll the window myself, or
- set a very large `default_ttl` upfront.

**Is application-managed `PATCH` the blessed way to get a sliding `delete` TTL?** Or is an activity-refreshing option for `delete` on the roadmap?

## **3. No count-based cap on checkpoints per thread?**

There’s a time-based prune (`keep_latest`) but no `max_checkpoints_per_thread` style cap. For long threads under a large TTL, checkpoints accumulate until the sweeper acts. Two asks:

- A **count-based retention** (“keep last N checkpoints per namespace”) would serve replay + bounded growth better than keep-exactly-1.
- Separately, even with `keep_latest`, each surviving blob still holds the **entire message history** (raised in #4448). Is `ReducingSaver` / state-level trimming the recommended answer for blob-size growth, or is there platform-level guidance?

Thanks in advance — mainly want to confirm the HITL-vs-replay tradeoff is by design and hear the recommended production pattern.
