Advanced16 min

Custom Checkpointer & Store

When to build a custom LangGraph checkpointer instead of using an official package, the complete 6-method BaseCheckpointSaver contract (the old 3-method documentation is wrong), a working DynamoDB implementation with all required methods, serialization security for custom backends, conformance testing, and production failure modes.

Quick Reference

  • BaseCheckpointSaver requires 6 sync methods: put(), put_writes(), get_tuple(), list(), delete_thread(), get_next_version() — plus 5 async variants for production
  • Official packages cover Postgres, SQLite, Redis, MongoDB, DynamoDB, CosmosDB, and Aerospike — build custom only when none fits your backend
  • put_writes() is the most commonly missed method — without it, interrupt/resume silently loses the resumed value
  • Run langgraph-checkpoint-conformance before deploying any custom checkpointer — it tests contract compliance including edge cases manual tests miss
  • Set LANGGRAPH_STRICT_MSGPACK=true in all deployments — blocks deserialization RCE (CVE-2025-64439) regardless of which checkpointer you use
  • Stores are accessed via runtime.store injection, not by direct class instantiation — built-in stores (InMemoryStore, PostgresStore, RedisStore) cover most use cases

Should You Build a Custom Checkpointer?

LangGraph ships official checkpointer packages for the most common backends. Building a custom checkpointer is justified in three situations: (1) your infrastructure runs a backend with no official package — an internal data platform, a proprietary database; (2) you need cross-cutting behavior official packages don't support — multi-region replication, custom sharding, audit logging at the storage layer; (3) you are a platform team wrapping a shared internal storage service for other teams. In all other cases, use an official package — it handles edge cases, receives framework updates, and is covered by upstream conformance tests.

Which checkpointer backend?self-hosted vs. Agent ServerNeed persistencebeyond a restart?NOMemorySaverdev · testing · ephemeralYESUsing LangGraphAgent Server?YESAgent Server built-inspostgres (default) · no config neededmongo · set backend: "mongo"NOself-hosted: pick by use casePostgreSQLdefault production choicealso: CockroachDB (PG-compatible)local: SQLiteRedis · Aerospikelow-latency / high-throughputephemeral-friendlysub-millisecond readsAWSDynamoDB · ValkeyAgentCore Memory/ValkeyAWS-native infraMongoDB · Couchbasedocument-oriented stackflexible schemacommunity-maintained

Agent Server has 2 built-in backends; everything else is a self-hosted custom saver

BackendPackageKey Savers
PostgreSQL / CockroachDBlanggraph-checkpoint-postgresPostgresSaver, AsyncPostgresSaver
SQLitelanggraph-checkpoint-sqliteSqliteSaver, AsyncSqliteSaver
Redis / Aerospikelanggraph-checkpoint-redisRedisSaver, AsyncRedisSaver, ShallowRedisSaver
DynamoDB / Valkeylanggraph-checkpoint-awsDynamoDBSaver, ValkeySaver, AgentCoreMemorySaver
Azure CosmosDBlanggraph-checkpoint-cosmosdbCosmosDBSaver, AsyncCosmosDBSaver
MongoDBlangchain-mongodb (community)MongoDBSaver
Building custom means you own conformance maintenance

When LangGraph adds a new required method — as happened when put_writes() was added in v0.2 — official packages update automatically. Your custom checkpointer does not. Budget time to track the langgraph-checkpoint changelog and update your implementation on each minor release that touches the base interface.