---
title: "Substate Model"
url: "https://radix.wiki/contents/tech/core-concepts/substate-model"
version: "1.3.1"
updated: 2026-07-29
license: CC-BY-4.0
license_url: "https://creativecommons.org/licenses/by/4.0/"
---

# Substate Model

|  |  |
| --- | --- |
| **Category** | State Model |
| **Comparison** | Not account model ([Ethereum](https://ethereum.org)), not [UTXO](https://en.wikipedia.org/wiki/Unspent_transaction_output) ([Bitcoin](https://bitcoin.org)) |
| **Key Benefit** | Fine-grained parallelism |
| **Addressing** | `NodeId` → Partition Number → `SubstateKey` |
| **Defined by** | [Kernel layer](https://radix-engine-docs.radixdlt.com/architecture/layers.html) of the Radix Engine |
| **Stored in** | A key-value database, keyed by partition key and sort key |

## Overview

The **Substate Model** is Radix's approach to storing and managing on-ledger state. Rather than using a global account-based model ([Ethereum](https://ethereum.org)) or UTXOs ([Bitcoin](https://bitcoin.org)), Radix breaks state into fine-grained pieces called **substates**.

Each substate is an independently addressable, independently lockable piece of data. A component's state might consist of dozens of substates – each vault, each metadata field, each access rule is its own substate.

### Why It Matters

This granularity is what enables [Cerberus](/contents/tech/core-protocols/cerberus-consensus-protocol) to achieve unlimited parallelism. Two transactions that touch different substates can execute on different shards simultaneously, even if they interact with the same component. Only transactions that touch overlapping substates need coordination.

Compare this to Ethereum's account model: any two transactions interacting with the same contract must be serialized, even if they access completely different data within that contract. This creates bottlenecks around popular contracts (DEXes, stablecoins).

## How a Substate Is Addressed

Substates are not a storage detail bolted onto the ledger – they are one of the three abstractions the [kernel layer](https://radix-engine-docs.radixdlt.com/architecture/kernel/index.html) of the Radix Engine is built around. The layered architecture reference lists the kernel’s responsibilities as defining the "Node, Partition, Substate abstractions", defining the call frame abstraction, maintaining ownership and reference invariants, and "managing transaction state updates, which are to be subsequently committed to the database at the end of the transaction" ([Radix Engine Docs](https://radix-engine-docs.radixdlt.com/architecture/layers.html)).

That gives every piece of on-ledger state a three-level address:

- **`NodeId`** – the entity the state belongs to: a component, a resource manager, an account, a vault.
- **Partition Number** – a numbered region of that node’s state, grouping related data together.
- **`SubstateKey`** – the individual substate within the partition.

Below the kernel, the [database layer](https://radix-engine-docs.radixdlt.com/architecture/database/index.html) flattens this into partition-key and sort-key abstractions "implemented on top of a key-value database". The kernel is explicitly "implemented on top of the database layer’s Partition Key and Sort Key abstractions", so the addressing scheme the engine reasons about and the keys the store actually writes are the same structure at two levels of detail. For the layer that executes code against these substates, see [Kernel Layer](/contents/tech/core-protocols/kernel-layer) and [VM Layer](/contents/tech/core-protocols/vm-layer).

## Where a Component’s Substates Come From

A blueprint author never writes substates by hand. They declare **fields** – the individual pieces of a component’s state – and **collections**, the keyed structures (key-value stores, indexes, sorted indexes) a component uses for data that grows. "The mapping from the Fields and Collection indices to Partition Number is managed by the System Layer and done at a per blueprint basis" ([Radix Engine Docs](https://radix-engine-docs.radixdlt.com/architecture/system/blueprint_impl.html)), so the layout is derived from the blueprint rather than chosen by the developer.

Object modules contribute partitions of their own on top of the blueprint’s: a component’s [metadata](/contents/tech/core-concepts/metadata-module), its [royalty configuration](/contents/tech/core-concepts/component-royalties), and its access rules are each their own state, addressed separately from the fields the blueprint declares. This is why the count adds up the way it does: a single [Scrypto](/contents/tech/core-protocols/scrypto-programming-language) component is not one state blob but dozens of independently addressable substates – every [vault](/contents/tech/core-concepts/buckets-proofs-and-vaults) it holds, every metadata entry, every access rule, and every entry in every collection.

## What the Granularity Buys

Because a substate is the unit that gets read and written, it is also the unit that gets contended. Two transactions that touch disjoint substates have nothing to coordinate, even when they call into the same component – a swap against one vault and a metadata read on the same DEX are, as far as state is concerned, unrelated work.

The comparison in the Overview holds in the other direction too. Under an account model the contract is the unit of state, so any two transactions touching a popular contract must be ordered against each other whether or not they share any data. Under a UTXO model the granularity is there, but state is consumed and recreated rather than updated in place, which makes long-lived shared state awkward to express.

The practical consequence shows up in how Radix's sharded designs schedule work. [hyperscale-rs](/contents/tech/research/hyperscale-rs) distinguishes per-substate locking – where a transaction's manifest and blueprint metadata are analysed ahead of execution to determine exactly which substates it will touch – from hot-state flagging for indivisible state such as a pool price, where one shard batches many transactions under a single amortized lock. Neither technique is available to a runtime whose smallest lockable unit is an entire contract.

## See Also

- [Radix Engine](/contents/tech/core-protocols/radix-engine)
- [Kernel Layer](/contents/tech/core-protocols/kernel-layer)
- [Resource](/contents/tech/core-concepts/resources)
- [Buckets, Proofs and Vaults](/contents/tech/core-concepts/buckets-proofs-and-vaults)
- [hyperscale-rs](/contents/tech/research/hyperscale-rs)

## External Links

- [Layered Architecture – Radix Engine Docs](https://radix-engine-docs.radixdlt.com/architecture/layers.html)
- [Kernel Layer – Radix Engine Docs](https://radix-engine-docs.radixdlt.com/architecture/kernel/index.html)
- [Blueprint Implementation – Radix Engine Docs](https://radix-engine-docs.radixdlt.com/architecture/system/blueprint_impl.html)
