Decoding Michelson storage is not a simple deserialization task. The language's type system is unusually rich for a blockchain VM, supporting deeply nested pairs, unions (ors), options, maps, big maps, and lambda values. The binary encoding is a compact, tag-free format where the meaning of every byte depends entirely on the expected type. A parser cannot walk the raw bytes without a complete, canonical type definition. This means that to decode the storage of any Tezos contract, an indexer must first retrieve the contract's full Michelson type from the node and use it as a schema to interpret the binary blob. Any mismatch between the type and the decoding logic produces silent corruption, not clean errors.

Decoding Michelson Storage and Big Maps
Why Michelson Storage Decoding Is a Hard Problem
Michelson's expressive type system and compact binary encoding create a uniquely difficult decoding surface for indexers, data teams, and any off-chain application that must read Tezos contract state.
The big_map type introduces a second, harder problem. Unlike a standard map, a big map's contents are not stored inline in the contract's storage. The storage only holds a big map ID, a numeric handle. To resolve the actual key-value data, an indexer must query the node's RPC for each big map key individually or traverse the entire big map using chunked RPCs. This is an I/O-bound operation that can time out for large datasets, and the RPC endpoints involved (/chains/main/blocks/head/context/big_maps/{id}) are computationally expensive for archive nodes. An indexer that naively tries to hydrate all big maps on every block will fail to scale. Teams must design lazy-loading strategies, caching layers, and incremental update logic that correctly handles big map key deletions and re-allocations across protocol upgrades.
These decoding challenges are a primary source of indexer bugs, incorrect wallet balances, and broken block explorers. A single misinterpreted pair nesting or a missed big map key can cause an exchange to display wrong user balances or a DeFi dashboard to report incorrect pool state. Chainscore Labs reviews storage decoding pipelines, big map traversal logic, and type-parsing implementations to identify the edge cases that cause silent data corruption. For teams building indexers, custody integrations, or analytics platforms on Tezos, a structured review of the storage decoding layer is the most direct way to prevent the class of bug that is hardest to detect and most expensive to fix in production.
Quick Facts: Michelson Storage and Big Maps
Operational facts for teams parsing and indexing Michelson contract storage, with a focus on big_map traversal, RPC behavior, and data integrity risks.
| Area | What changes | Who is affected | Action |
|---|---|---|---|
big_map key decoding | Keys are stored as serialized byte sequences, not plain values. Decoding requires the key's Michelson type, which is not stored with the value. | Indexer builders, data analysts, wallet backends | Verify that your indexer correctly deserializes big_map keys using the contract's type schema to prevent data corruption. |
big_map value decoding | Values are stored as serialized bytes. Lazy deserialization without the full schema can produce incorrect or incomplete data. | Indexer builders, DeFi protocol dashboards | Validate value decoding against the contract's full storage type. Request a storage parsing review from Chainscore Labs to ensure accuracy. |
RPC timeout on large big_maps | Using the /chains/main/blocks/head/context/big_maps/{id} RPC to fetch all keys can cause timeouts on maps with thousands of entries. | Infrastructure operators, dApp backends | Implement paginated traversal using the offset and length parameters or use the chunked RPC endpoint to avoid service disruption. |
Total active big_map keys | The RPC does not provide a direct count of active keys. Counting via pagination is an O(n) operation that can be expensive. | Data teams, monitoring services | Do not rely on a single RPC call for an exact count. Implement a caching layer or use an indexer like TzKT that pre-computes this metric. |
Lazy deserialization in big_maps | A big_map value can itself contain another big_map ID. Recursive traversal is required to fully resolve the contract's state. | Indexer builders, bridge operators | Ensure your indexing logic handles nested big_map structures to avoid missing critical state, such as rollup inboxes or complex DeFi ledgers. |
Storage schema changes | Contract upgrades can alter the storage and big_map value types. Historical data may become unparseable with the new schema. | Indexer builders, archival node operators | Design your indexer to version storage schemas by block level. Chainscore Labs can audit your migration logic to prevent historical data loss. |
Packing and address encoding | Michelson uses optimized binary encodings for addresses and other primitives within PACK. Standard base58 checks are insufficient. | Wallet backends, custody platforms | Use a Michelson-aware library for all packing and unpacking operations. An integration review can identify mismatches that lead to failed transactions. |
The Binary Encoding and Big Map Architecture
How Tezos stores contract data in binary and why big_map traversal breaks naive indexers.
Tezos contract storage is not a JSON blob. It is a compact binary encoding defined by the Michelson type system, where every value is serialized according to its type tree. For simple types like int, nat, string, and bytes, the encoding is straightforward. However, for complex types—pairs, ors, maps, and big_maps—the binary layout requires recursive parsing guided by the contract's type schema. Indexers that treat storage as opaque bytes or attempt generic binary-to-JSON conversion without the exact type structure will produce corrupted or incomplete data. The canonical encoding specification is defined in the Michelson documentation, and any deviation in a custom parser leads to silent data loss.
The big_map type is the primary source of parsing complexity and operational risk. Unlike a standard map, which is serialized inline in the contract's storage, a big_map is stored as an integer handle referencing a lazy, content-addressed structure in the node's context. Each key-value pair is individually accessible via RPC, but enumerating a large big_map by iterating over all keys is a common anti-pattern that causes RPC timeouts, node memory pressure, and incomplete indexing. The correct approach for off-chain indexers is to replay historical operations that modify the big_map—specifically big_map_diff entries in transaction receipts—to reconstruct the current state incrementally. This requires parsing the binary key and value types within each diff entry, which themselves are serialized using the same Michelson encoding rules as inline storage.
Operational teams building Tezos indexers must handle several edge cases: big_map keys and values can be arbitrarily nested types, the big_map_diff only appears in operation receipts for blocks where the map was modified, and reorgs require unwinding big_map state correctly. A common failure mode is an indexer that correctly parses inline storage but silently drops or misinterprets big_map data, leading to incorrect token balances or contract state for wallets, explorers, and DeFi dashboards. Chainscore Labs reviews storage parsing logic against the canonical Michelson serialization spec, audits big_map reconstruction pipelines for completeness under reorgs, and validates that indexer output matches on-chain state for high-value contracts.
Who Is Affected by Storage Decoding Complexity
Indexer and Data Teams
These teams are the most directly affected. Incorrectly parsing Michelson storage, especially deeply nested big_maps, leads to incomplete or inaccurate on-chain data. The primary risk is failing to traverse large big_maps within RPC timeout limits, causing indexer stalls or data gaps.
Action Steps:
- Audit your deserialization logic for all Michelson types, including complex annotations.
- Implement paginated big_map traversal using the
big_mapRPC endpoint with offset parameters. - Benchmark parsing performance against mainnet contracts with large state to identify timeout risks.
- Validate that your indexer correctly unwinds state during chain reorganizations, a common failure point when storage parsing is fragile.
Chainscore Labs can review your indexing pipeline's storage decoding logic to prevent data corruption and ensure reliable dApp data delivery.
Implementation Playbook: Reliable Decoding and Traversal
A practical guide for indexer and data teams to reliably parse Michelson storage and traverse big maps without hitting RPC timeouts or introducing data corruption.
Schema-Driven Deserialization
Do not rely on generic binary-to-JSON converters. Implement a schema-aware deserializer that maps Michelson primitives to typed structures. For complex nested pairs and ors, generate a strict layout map from the contract script to ensure field names and types are correctly resolved. This prevents silent data corruption where a misaligned annotation causes a balance to be parsed as a timestamp.
Efficient Big Map Traversal
Avoid iterating big maps via the Tezos node RPC using naive offset pagination on large maps, which causes gateway timeouts. Instead, use the big_map block endpoint to stream only the active keys for a specific block level. For historical state reconstruction, replay operations that write to the big map rather than re-downloading the entire map at every block. This reduces indexing latency from hours to minutes.
Lazy Value Decoding
Big map values are stored as raw Michelson byte sequences. Decode them lazily on first access rather than eagerly during ingestion. Cache the decoded representation with a hash of the raw bytes. This avoids wasting compute on values that are never queried by the application layer and allows you to handle schema evolution where a contract upgrade changes the value type of an existing big map.
Reorg-Aware State Management
Tezos chain reorganizations can invalidate big map diffs. Your indexer must maintain a reversible log of big map operations keyed by block hash, not just block level. When a reorg is detected, walk the undo log to revert big map key-value pairs to their state at the common ancestor block. Failing to do this leaves your database with phantom keys that never existed on the canonical chain.
Risk Matrix: Storage Parsing and Indexer Reliability
Identifies specific risks that cause indexers to return incorrect balances, miss token transfers, or fail to decode contract state when parsing Michelson storage and traversing big_map structures.
| Risk | Failure mode | Severity | Mitigation |
|---|---|---|---|
Incorrect Michelson type definition | Indexer uses a stale or mismatched storage type to deserialize contract state, producing garbled balances or metadata | Critical | Automate type-schema fetching from the chain for each contract at the block level being indexed |
Unbounded big_map traversal | Indexer attempts to iterate all big_map keys via RPC without pagination, hitting timeout limits and leaving state partially indexed | High | Implement chunked traversal using big_map key hashing and offset-based pagination |
Lazy deserialization of big_map values | Indexer assumes all big_map values are present in the storage root, missing active data that must be fetched per-key | High | Design the indexer to resolve big_map pointers and fetch individual key-value pairs on demand |
Schema evolution without re-indexing | Contract upgrades change storage layout, but the indexer replays historical blocks using the new schema, corrupting historical state | High | Maintain a versioned schema registry keyed by block level and re-index historical data when schemas change |
Complex annotation parsing | Indexer fails to correctly map annotated Michelson fields to human-readable labels, causing display errors in wallets and explorers | Medium | Validate annotation extraction against the contract's entrypoint and storage metadata during integration testing |
Nested comb structure misinterpretation | Indexer flattens or misorders nested pairs in storage, scrambling the logical structure of multi-asset contract state | Medium | Use a recursive parser that respects Michelson comb nesting semantics rather than applying generic tree flattening |
Missing lazy storage resolution | Indexer does not follow | Critical | Audit the indexer's storage traversal logic to ensure all lazy storage types are explicitly resolved |
Indexer Reliability Checklist for Storage Decoding
A practical checklist for data and indexer teams to validate the correctness, completeness, and resilience of their Michelson storage and big_map decoding logic before production deployment.
What to check: Verify that your decoder correctly handles contract storage schema changes across origination and subsequent upgrades. Michelson storage types are immutable after origination unless the contract is explicitly upgraded via a migration or lambda-based proxy pattern.
Why it matters: A decoder built against the current storage type will fail or silently corrupt data if the contract is upgraded to a new storage layout. This is a common source of indexer outages after protocol upgrades or contract migrations.
Confirmation signal: Your decoder should either (a) dynamically resolve the storage type from the contract's current script at each block, or (b) maintain a versioned mapping of contract addresses to known storage schemas with explicit handling for unknown or upgraded types. Test against a contract that has undergone a known storage migration.
Canonical Resources and Tools
Use these resources to validate Michelson storage decoding, big_map traversal, RPC behavior, and indexer design against Tezos-native semantics rather than inferred JSON shapes.
Looking to build on a specific blockchain?
We build smart contracts, DeFi applications, wallets, tokenization platforms, and blockchain infrastructure across the major ecosystems teams choose today. That includes Ethereum, Arbitrum, Optimism, Polygon, Avalanche, Solana, Sui, Aptos, Hedera, Stellar, and NEAR, with support for additional EVM and non-EVM networks based on your product requirements.
EVM ecosystems
- Ethereum
- Arbitrum
- Optimism
- Polygon
- Avalanche
- Cronos

Non-EVM ecosystems
- Solana
- Sui
- Aptos
- Hedera
- Stellar
- NEAR
Additional ecosystems
- Polkadot
- Cosmos
- TON
- Cardano
- Algorand
- Tempo
Also available for Base, appchains, custom EVM networks, and cross-chain product architecture.
Frequently Asked Questions on Michelson Storage Decoding
Common questions from indexer, data, and integration teams on parsing Michelson storage, traversing big_maps efficiently, and avoiding RPC timeouts when extracting on-chain state.
The Tezos node RPC does not support paginated or streaming access to large big_maps via a single endpoint. A naive request to /chains/main/blocks/head/context/big_maps/{id} attempts to return all key-value pairs in one response. For maps with thousands of entries, this can exceed node processing time or HTTP response limits.
What to do:
- Use the individual key lookup endpoint:
/chains/main/blocks/head/context/big_maps/{id}/{script_expr}to fetch values one key at a time. - To discover active keys, you must either:
- Replay and index all
big_map_diffoperations from every block since the map's origination. - Maintain an off-chain database of known keys and periodically refresh their values.
- Replay and index all
- For new indexers, a full historical replay is the only reliable method to build a complete key set. There is no RPC endpoint to enumerate all keys without values.
Delivering blockchain solutions for 5+ years.
We have partnered with 50+ leading DeFi protocols, NFT ecosystems, and fintech innovators to build secure, scalable, and capital-efficient blockchain products.
Selected Partners & Clients
“I've been working with Chainscore Labs for last 3+ years, they've consistently delivered with strong ownership across multiple projects. The team is reliable and detail-oriented.”
How to get started?
If you're looking for blockchain integration, ChainScore Labs has 5+ years of experience helping teams build and integrate exchanges, wallets, smart contracts, tokenization solutions, and protocol-connected products, we can help you choose the right path, integrate securely, and get to production faster. Our team consists of experienced blockchain developers and architects who can help you with your blockchain integration needs.
Exploration & Strategy
Define your product goals and choose the right blockchain architecture for your use case.
Architecture & Design
Design the smart contracts, tokenomics, and security parameters of your system.
Development & Integration
Build and integrate with wallets, oracles, and front-end dApps for a seamless experience.
Security & Launch
Comprehensive audits followed by a risk-managed mainnet deployment to protect your users.
Discover our
blockchain development services.
We build production-grade blockchain solutions for top-tier projects across DeFi and Web3.
Need a blockchain engineering team?
Send the project context and we will respond with next steps, scope questions, and a practical path to delivery.


