mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-17 21:25:46 +02:00
The recursive CTE was bottlenecked by a JSON-expression join (`bl.version = checkpoint->'channel_versions'->>bl.channel`) that the planner could not index, producing an O(ancestors x blobs) nested-loop. At depth 1000 it ran ~275 ms and removed ~2M filter rows; the recursion itself was 2.4 ms. Switch to three plain indexed SELECTs per delta channel (checkpoints, checkpoint_writes, checkpoint_blobs); a pure helper on BasePostgresSaver walks the parent chain and assembles DeltaChannelWrites. Sync (__init__.py) and async (aio.py) each own their three-roundtrip I/O wrappers. Bench numbers (notes/delta_channel_query_bench.md): 3x at depth 50, 15x at depth 200, ~100x at depth 1000. Plain over-fetches sibling rows when the thread branches but still wins at every realistic depth on both local and remote postgres. Multi-channel coalescing dropped — reconstruction is per-channel now. Same shape as InMemorySaver. Can come back as a SQL-level optimization later if needed.