Sui.

Post

Share your knowledge.

article banner.
D’versacy .
Aug 21, 2025
Article

🔄 Shared vs. Owned Objects: Choosing the Right Concurrency Pattern on Sui

🚨 Problem this solves: Many teams default to shared objects for everything that multiple users touch. The result? ❌ Contention, ❌ failed transactions, and ❌ confusing errors. Others overuse address-owned objects and suddenly can’t coordinate multi-party actions.

👉 What you really need is a clear decision framework for when to use address-owned, shared, or immutable — while still keeping throughput high and invariants tight.


🧭 1) The Decision Tree

Ask yourself these 3 quick questions:

1️⃣ Does only one address mutate it? → ✅ Address-owned (fast, parallel, no consensus overhead).

2️⃣ Do many addresses need to mutate the same record? → ✅ Shared (design carefully to reduce contention).

3️⃣ Is it reference data that never changes? → ✅ Immutable (publish once, reuse forever).


👤 2) Address-Owned Patterns

💡 Best for: wallets, inventories, positions, drafts, personal settings.

Why use it? ✨ No global contention — runs in parallel. ✨ Only the owner can fail their own tx (cleaner UX).

Step-by-step 👇

  1. Create a per-user root object (e.g., Profile, Inventory).
  2. Use dynamic fields for lists (items, positions) → avoids vector growth issues.
  3. For peer-to-peer actions → move objects between owners instead of touching a shared registry.

⚠️ Pitfall: Using a shared “Registry” for user lookups. ✅ Fix: Derive deterministic IDs or store a one-time mapping at signup. From then on → interact directly with each user’s object.


🤝 3) Shared Patterns (Safely!)

💡 Best for: order books, game rooms, auctions, governance pools.

The Risk: contention + version conflicts if everyone writes to the same object.

Partitioning Strategies 🪄

  • Spatial → one shared object per room/level/map.
  • Temporal → rotate objects per epoch/round.
  • Hash-based → bucket by hash(key) % N.
  • Semantic → split by category, price range, queue, etc.

Marketplace Example 🛒

  1. Collection (shared) → represents creator scope.
  2. OrderBookShard (shared) → per price bucket.
  3. Listing (address-owned) → lives with seller until matched.
  4. Matchmaking → only touches the shard for the relevant price bucket.
  5. Settlement → moves Listing to buyer + updates shard counters.

Invariant Rules:

  • Only touch the shard you need.
  • Don’t store global aggregates → compute off-chain or lazily.

📜 4) Immutable Patterns

💡 Best for: templates, schemas, metadata, descriptors.

Step-by-step:

  1. Publish immutable object with constant fields.
  2. Store its ObjectID in owned/shared objects.
  3. For upgrades → publish a new immutable object and let consumers opt-in.

⚠️ Pitfall: Putting live counters or user-specific data in immutable objects. ✅ Fix: Keep dynamic state in owned/shared, constants in immutable.


🔗 5) Handling Cross-Object Actions

When an action spans multiple objects:

  • Consume only what you need.
  • Re-emit derived objects instead of mutating massive shared state.
  • Keep the cut set (touched objects) minimal.

Conflict Checklist ✅

  • Writing only one shard?
  • Can independent actions commit without colliding?
  • On conflict, can the client retry with just one fresh read?

📊 6) Audit with Counters

Add simple diagnostic counters (e.g., “writes per shard per minute”) in testnet. 🔎 If one shard is too hot → increase bucket count or rethink your partition key.


🎯 Outcome

By consciously using the right object type for the right scenario:

  • 👤 Owned objects → smooth per-user flows.
  • 🔄 Shared objects → only for true coordination.
  • 📜 Immutable objects → reference data only.

👉 You’ll keep contention low, parallelism high, and user experience 🚀 seamless.

  • Architecture
0
Share
Comments
.