Here's a scenario worth taking seriously before it happens to you in production: your agent has just called a payment API, the server restarts a second later, and now you have to decide whether to charge the customer again because the agent has no memory of what it already did. Persistence is LangGraph's answer to exactly this class of problem, and it's built in rather than something you bolt on afterward.
The checkpointer: automatic save points
When you compile a graph, you can pass it a checkpointer. From that point on, LangGraph automatically saves a snapshot of the full state after every single node finishes running - you don't write any of that saving logic yourself. If the process crashes, times out, or you deliberately pause it, the last snapshot is sitting there ready to pick up from.
Resuming with the same thread ID continues from Node 3's saved checkpoint - Nodes 1 and 2 never re-run.
Threads: how LangGraph knows which run is which
Checkpoints are organized by a thread ID - a string you choose that represents one ongoing run or conversation. You pass it in through the config on every call:
config = {"configurable": {"thread_id": "order-48213"}}
app.invoke({"messages": [...]}, config)
Call invoke again later with that same thread_id, and LangGraph loads the latest checkpoint for that thread and continues from there - it isn't starting a fresh run, it's picking the existing one back up. Use a different thread_id and you get a completely separate, independent run with its own history.
Picking a checkpointer backend
LangGraph ships a few checkpointer implementations, and which one you reach for depends entirely on what you're doing:
- MemorySaver - keeps checkpoints in memory only. Perfect for local development and quick experiments; everything disappears the moment the process restarts.
- SqliteSaver - writes checkpoints to a SQLite file. A solid fit for a single-server deployment where you want real persistence without standing up a database.
- PostgresSaver - backed by Postgres. What you reach for once you're running multiple instances of your app and need every instance to see the same checkpoint state.
Short-term memory vs long-term memory
Threads give you short-term memory - everything relevant to one specific run or conversation. But sometimes you want an agent to remember something across different threads entirely - a user's stated preference, a fact it learned last week, something that should carry over the next time that same user starts a brand-new conversation. That's a different job, and LangGraph has a separate mechanism for it: a store, which nodes can read from and write to independently of any one thread's checkpoint history. Threads answer "where did this specific run leave off"; a store answers "what do we know about this user, period."
MemorySaver while you're building, switch to SqliteSaver or PostgresSaver once you actually deploy, and only reach for a store once you have a concrete case for memory that needs to outlive a single conversation.Why this matters more than it sounds like it should
It's tempting to treat persistence as an operational afterthought you'll add "once this actually goes to production." The problem is that persistence isn't just a resiliency feature - it's also the foundation the next guide's human-in-the-loop pattern depends on. A graph can only pause and wait for a person to approve something because it has somewhere reliable to put its state while it waits. Get the checkpointer set up early, and both problems get solved at once.