Party Objects - The Missing Piece for Single-Owner Consensus on Sui
When I first started building on Sui, I had this problem of understanding where I should I use an owned object or a shared object. I finally understood this and this is what I can say:
Owned objects give you one clear owner, but you’re stuck with manual version tracking and no concurrency.
Shared objects let the network handle versioning and allow multiple operations at once, but anyone can touch them.
These features are specific, but a bit too rigid for certain use cases. Party objects eliminate those rigid limitations by allowing single ownership with automatic versioning as well as concurrent transactions.
Why Party Objects Exist
Let’s take an example where someone’s building a DeFi protocol where each user has a capability token that controls what they can do. You need:
Single ownership (only the user controls it)
Automatic versioning (so you don’t have to manually track history)
Concurrent transactions (users shouldn’t wait on each other’s ops)
Owned objects fail because you get no automatic versioning and no concurrency. Shared objects fail because they’re open to anyone.
Party objects fix that exact gap.
What does “Ownership” really entail on Sui?
The concept of Ownership on Sui actually mixes three different things:
Authorization – who can use the object?
AddressOwner: one accountObjectOwner: delegated to another objectShared: anyoneImmutable: anyone can read, nobody can change
Versioning – how do we track changes?
Manual (you track it yourself)
Automatic (network tracks it)
None (if immutable)
Dissemination – how does the object get processed?
Fastpath → quick, no consensus
Consensus → network-wide agreement
Party objects mix these up in a new way:
How They Work
A party object is just telling Sui:
“This object belongs to one person, but I still want the network to track every change and handle concurrency.”
So instead of running on fastpath like owned objects, party objects always go through consensus.
Example:
// Normal owned object transfer
transfer::transfer(my_capability, recipient);
// Party object transfer
party::party_transfer(my_capability, party::new(recipient));
The trade-off: latency is a bit higher (since consensus is slower). But you get concurrency and automatic version history, which is usually worth it.
Building With Party Objects
Here’s a simple walkthrough of using party objects for a capability system.
Step 1: Define the capability
struct Capability has key, store {
id: UID,
level: u8, // 1 = read, 2 = write, 3 = admin
usage_count: u64,
max_uses: u64, // 0 = unlimited
recent_ops: vector<String> // small audit log
}
Step 2: Issue as a party object
public fun issue_capability(
level: u8,
max_uses: u64,
recipient: address,
ctx: &mut TxContext
) {
let cap = Capability { ... };
party::public_party_transfer(cap, party::new(recipient));
}
Step 3: Use the capability
public fun use_capability(
cap: &mut Capability,
operation: String,
) {
assert!(cap.max_uses == 0 || cap.usage_count < cap.max_uses, 1);
cap.usage_count = cap.usage_count + 1;
vector::push_back(&mut cap.recent_ops, operation);
if (vector::length(&cap.recent_ops) > 10) {
vector::remove(&mut cap.recent_ops, 0);
}
}
Step 4: Transfer ownership
public fun transfer_capability(
cap: Capability,
new_owner: address,
) {
party::public_party_transfer(cap, party::new(new_owner));
}
Now you’ve got single-owner objects with automatic history and concurrency.
Performance Trade-offs
Owned objects: Around 300ms. This is the fast path. They’re perfect when you only need quick, single-owner updates. But you don’t get automatic versioning or concurrency, just one transaction at a time.
Party objects: Around 600–700ms, similar to shared objects. The extra cost comes from going through consensus, but in return you get automatic versioning and the ability to handle multiple transactions at once without blocking. Great when you need both control and smooth parallel activity.
Shared objects: Also in the 600–700ms range. They scale well for public, multi-user access, but ownership is open and anyone can interact with them.
The Future: Multi-Party
Right now, party objects only support one owner. But the plan is to support multi-party ownership (think multi-sig):
party::multi_party_transfer(
object,
party::new_multi(
vector[alice, bob, charlie],
2 // threshold
)
);
That opens the door for:
DAO treasuries
Multi-sig wallets
Collaborative apps
Conclusion
Party objects fill the gap between owned and shared objects. They give you:
One owner
Automatic versioning
Concurrency
I would say, party objects are worth exploring. They’re designed to make capability systems and permissioned objects much simpler, and chances are they’ll solve problems you might not even realize you have yet.



