What is an object on Sui?
November 8, 2026
An object is the basic unit of storage on Sui. Sui doesn't keep one global key-value store per account. Each piece of onchain state (a coin, an NFT, a config, a published package) is a separate object with a globally unique ID, an owner, a type and a version that goes up every time it changes. Transactions take objects as inputs and produce new or modified objects as outputs.
Objects in Move
A Move struct becomes a Sui object when it has the key ability and its first field is id: UID:
module example::todo;
use std::string::String;
public struct TodoList has key, store {
id: UID,
items: vector<String>,
}
public fun new(ctx: &mut TxContext): TodoList {
TodoList { id: object::new(ctx), items: vector[] }
}
public fun add(list: &mut TodoList, item: String) {
list.items.push_back(item);
}object::new(ctx) creates a fresh UID. A value only becomes a stored object once you transfer, share or freeze it, for example with transfer::public_transfer(list, ctx.sender()). The store ability is optional. With it, anyone can transfer the object using the public_* functions. Without it, only your module can. See What are abilities in Sui Move?.
What every object carries
- ID: 32 bytes, derived from the digest of the creating transaction plus a counter. It never changes, even when the object is transferred or wrapped.
- Version: an 8-byte integer that increases with each transaction that modifies the object.
- Previous transaction: the digest of the last transaction that output this object.
- Owner: an address, another object, shared, immutable, or a consensus-address owner (party).
- Contents: BCS-encoded data. For Move objects that's the type, whether it allows
public_transfer, and its fields. For packages, it's the bytecode modules plus type-origin and linkage tables.
Transactions name each input by an object reference: the triple (ID, version, digest). The digest is a hash of the object's contents and metadata, so the sender and the validators agree on exactly which state is being used.
Kinds of objects
- Move objects: instances of
keystructs defined in some package, such asCoin<SUI>or yourTodoList. - Packages: published Move code is itself an immutable object. Upgrading a package creates a new package object and leaves the old one in place.
Why it matters
Ownership tells validators which transactions can touch which objects. Transactions on address-owned objects can use the fastpath and run in parallel without global ordering. Transactions on shared objects go through consensus. This is the main design choice you make when writing Sui Move, covered in What kinds of object ownership does Sui have? and When should I use shared objects versus owned objects?.
Reading an object
From the CLI:
sui client object <OBJECT_ID>From TypeScript with @mysten/sui v2:
import { SuiGrpcClient } from '@mysten/sui/grpc';
const client = new SuiGrpcClient({
network: 'testnet',
baseUrl: 'https://fullnode.testnet.sui.io:443',
});
const { object } = await client.getObject({
objectId: '0x6',
include: { json: true },
});
console.log(object.type, object.version, object.owner.$kind, object.json);0x6 is the shared Clock object, which exists on every network. Objects also have size limits (see What are the object size limits on Sui?).
Sources
- Object Model, Sui documentation
- Objects, Sui documentation
- object.move, Sui framework source
- Object Model, The Move Book