Principle:Langchain ai Langgraph Checkpoint Encryption
| Attribute | Value |
|---|---|
| Knowledge Sources | LangGraph |
| Domains | Serialization, Encryption |
| Last Updated | 2026-02-11 15:00 GMT |
Overview
Checkpoint encryption is the mechanism by which LangGraph transparently encrypts serialized checkpoint data at rest by composing a serializer with a cipher, using the EncryptedSerializer decorator class.
Description
The EncryptedSerializer implements SerializerProtocol by composing an inner serializer with a CipherProtocol cipher. The encryption and decryption process works as follows:
During serialization (dumps_typed), the object is first serialized by the inner serializer (defaulting to JsonPlusSerializer) to obtain a (type, bytes) pair. The raw bytes are then encrypted via the cipher's encrypt method, which returns (cipher_name, ciphertext). The cipher name is appended to the type string with a + separator, producing a composite type like "json+aes".
During deserialization (loads_typed), the type string is checked for a + delimiter. If present, the string is split to extract the original type and the cipher name. The cipher name is used to decrypt the ciphertext, and the resulting plaintext is passed to the inner serializer's loads_typed with the original type string. If no + is found, the data is passed directly to the inner serializer without decryption, enabling transparent reading of unencrypted legacy data.
The from_pycryptodome_aes class method provides a convenience factory that creates an EncryptedSerializer pre-configured with AES encryption using the PyCryptodome library. The AES key can be provided directly via the key parameter or read from the LANGGRAPH_AES_KEY environment variable. The default mode is AES-EAX, which provides both confidentiality and authenticity. The encrypted output format concatenates the nonce (16 bytes), authentication tag (16 bytes), and ciphertext into a single byte sequence, ensuring all components needed for decryption are stored together.
Usage
Use EncryptedSerializer when checkpoint data must be encrypted at rest, such as when storing sensitive conversation data, PII, or API keys in checkpoint backends. Pass it as the serde parameter to any checkpoint saver (e.g., SqliteSaver, PostgresSaver). The from_pycryptodome_aes factory is the recommended setup method for AES encryption with minimal configuration. The same serializer instance can be shared across multiple savers.
Theoretical Basis
Checkpoint encryption applies the decorator pattern to serialization: the EncryptedSerializer wraps an existing serializer with an encryption layer without modifying the inner serializer's behavior. This preserves the single responsibility principle -- serialization and encryption are independent concerns that can be configured, tested, and evolved separately.
The composite type string ("json+aes") implements self-describing encryption metadata, ensuring that each blob carries the information needed to select the correct decryption path. This supports algorithm agility and key rotation: data encrypted with different algorithms or keys can coexist in the same checkpoint store, and the system automatically routes each blob to the correct decryptor.
The graceful fallback for unencrypted data (absence of + in the type string) enables incremental migration: existing unencrypted checkpoints remain readable after encryption is enabled, and new checkpoints are encrypted without requiring a bulk migration of existing data. This follows the backwards compatibility principle that is essential for production systems where downtime for data migration is unacceptable.
AES-EAX mode provides authenticated encryption with associated data (AEAD), combining confidentiality (data cannot be read without the key) with integrity (any tampering with the ciphertext is detected during decryption). This is strictly stronger than encryption alone, as it prevents both eavesdropping and undetected data modification.