Move.

Publicación

Comparte tu conocimiento.

Jeff.
Jeff461
Sep 01, 2025
P&R expertos

How does Sui achieve parallel execution for transactions?

I know Sui uses a different approach compared to other blockchains for transaction processing. Can someone explain how parallel execution works in Sui and what best practices developers should follow in Move code to leverage this feature?

  • Move CLI
0
2
Cuota
Comentarios
.

Respuestas

2
acher.
Sep 1 2025, 13:17

You’ll notice that Sui achieves parallel execution by moving away from the “global state machine” model used in chains like Ethereum and instead embracing an object-centric model. Every asset, contract, or record in Sui exists as an object with unique ownership. If a transaction only touches owned objects (objects tied to a single address), Sui can safely execute it in parallel with other independent transactions because there’s no risk of conflicts. On the other hand, if a transaction touches a shared object (like a global marketplace or liquidity pool), Sui has to serialize execution to prevent race conditions. This design is what gives Sui its high throughput without sacrificing safety.

In practice, as a Move developer, you can optimize for parallelism by designing modules that minimize reliance on shared objects. For example, instead of storing every user’s balance in a single global registry (which forces serialization), you can create separate owned objects for each user’s balance. That way, transfers, swaps, or updates can happen in parallel as long as they don’t collide on the same object.

Here’s a quick example showing the difference:

// Bad pattern (serialized on shared object)
module bad_bank::bank {
    struct Bank has key {
        balances: table::Table<address, u64>,
    }

    public entry fun deposit(bank: &mut Bank, user: address, amount: u64) {
        table::add(&mut bank.balances, user, amount);
    }
}

// Better pattern (parallel-friendly, each user has their own owned object)
module good_bank::bank {
    struct Account has key {
        balance: u64,
    }

    public entry fun deposit(account: &mut Account, amount: u64) {
        account.balance = account.balance + amount;
    }
}

In the first case, every deposit hits the same shared Bank object, so the runtime has to serialize those calls. In the second, each user has their own Account object, letting deposits execute in parallel.

Best practices to leverage Sui’s parallel execution:

  • Favor owned objects over shared objects whenever possible.
  • Split state into finer-grained objects so unrelated transactions don’t collide.
  • Use shared objects only for coordination (e.g., global order book, governance), and isolate them from high-frequency operations.
  • Benchmark your flows with the Sui Explorer or CLI to detect unintended serialization hotspots.
1
Comentarios
.
NakaMoto. SUI.
Sep 1 2025, 18:39

Sui achieves parallel execution by scheduling transactions based on the objects they touch: the runtime builds a dependency graph from each transaction’s input objects and runs transactions in parallel when their read/write sets don’t conflict, while transactions that mutate the same object are serialized, so to get parallelism you must design your Move code and data layout so most transactions operate on disjoint sets of objects; design for per-user or per-resource objects (one object per user, per order, per pool) instead of one global state object, prefer immutable reads (&T) when possible, minimize &mut access to shared objects, push mutable state to owned objects or per-key shards (dynamic fields or separate shard objects) so each transaction touches only its shard, use events for append-only history rather than writing large logs on-chain, use capability tokens or small permission objects to avoid storing per-user mutable records inside a hot shared object, batch related owned-object updates into a single Programmable Transaction Block so the shared object is touched once at commit (example TypeScript PTB snippet: const tx = new TransactionBlock(); /* modify owned objects */ tx.moveCall({ target: "pkg::module::settle", arguments: [ tx.object(shardId) ] });), avoid global counters by using UIDs or tx-derived ids, design operations to be commutative or partitionable (deltas, bucketed counters) to reduce ordering constraints, watch out for common pitfalls such as storing growing vectors inside a shared root (that becomes a hotspot), forgetting to use object::new/UID for per-instance objects, and expecting dynamic fields to remove all contention (they still mutate the parent object if added/removed), debug contention by monitoring retries and effects in node logs and by running load tests that simulate many parallel clients targeting different keys, and when you see high retry rates add shards, move heavy payloads into child objects or events, or change workflow to settle periodically; for concrete patterns and API references read the Sui docs: https://docs.sui.io/build/objects and if you want I can show a short Move example that implements a sharded counter and a matching PTB/TypeScript flow to illustrate the safe pattern.

0
Comentarios
.

Sabes la respuesta?

Inicie sesión y compártalo.

Move is an executable bytecode language used to implement custom transactions and smart contracts.

270Publicaciones616Respuestas
Sui.X.Peera.

Gana tu parte de 1000 Sui

Gana puntos de reputación y obtén recompensas por ayudar a crecer a la comunidad de Sui.