Bright technical workstation with light surfaces, a small plant, and calm indexer dashboards.
Protocols

Decoding Michelson Storage and Big Maps

A technical deep-dive for indexer and data teams on parsing and deserializing Michelson storage data, including efficient big_map traversal without RPC timeout. Covers decoding complexity risks and where storage parsing review improves indexer reliability.
introduction
THE INDEXER'S PARSING CHALLENGE

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.

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.

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.

INDEXER AND DATA TEAM IMPACT ASSESSMENT

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.

AreaWhat changesWho is affectedAction

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.

technical-context
MICHELSON STORAGE PARSING

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.

IMPACT BY ROLE

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_map RPC 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-impact
MICHELSON STORAGE AND BIG MAP PARSING

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.

01

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.

02

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.

03

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.

04

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.

MICHELSON DATA EXTRACTION FAILURE MODES

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.

RiskFailure modeSeverityMitigation

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 big_map or sapling_state pointers in storage, silently omitting active contract data from indexed results

Critical

Audit the indexer's storage traversal logic to ensure all lazy storage types are explicitly resolved

MICHELSON STORAGE PARSING VALIDATION

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.

Chains We Build On

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 logo
    Ethereum
  • Arbitrum logo
    Arbitrum
  • Optimism logo
    Optimism
  • Polygon logo
    Polygon
  • Avalanche logo
    Avalanche
  • Cronos logo
    Cronos

Non-EVM ecosystems

  • Solana logo
    Solana
  • Sui logo
    Sui
  • Aptos logo
    Aptos
  • Hedera logo
    Hedera
  • Stellar logo
    Stellar
  • NEAR logo
    NEAR

Additional ecosystems

  • Polkadot logo
    Polkadot
  • Cosmos logo
    Cosmos
  • TON logo
    TON
  • Cardano logo
    Cardano
  • Algorand logo
    Algorand
  • Tempo logo
    Tempo

Also available for Base, appchains, custom EVM networks, and cross-chain product architecture.

INDEXER AND DATA TEAM FAQ

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_diff operations from every block since the map's origination.
    • Maintain an off-chain database of known keys and periodically refresh their values.
  • 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.
Trusted by Industry Leaders

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

ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
ChainVote logo
Reax logo
Sokail logo
Swapsicle logo
SyntheX logo
Tekika logo
Telos logo
Zexe logo
“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.”
L
Lee Erswell
CEO, Telos Foundation
how to get started

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.

01

Exploration & Strategy

Define your product goals and choose the right blockchain architecture for your use case.

02

Architecture & Design

Design the smart contracts, tokenomics, and security parameters of your system.

03

Development & Integration

Build and integrate with wallets, oracles, and front-end dApps for a seamless experience.

04

Security & Launch

Comprehensive audits followed by a risk-managed mainnet deployment to protect your users.

Start a build

Need a blockchain engineering team?

Send the project context and we will respond with next steps, scope questions, and a practical path to delivery.