What are the object and transaction size limits on Sui?
November 10, 2026
On Sui mainnet, a single Move object can be at most 256,000 bytes, a serialized transaction at most 131,072 bytes (128 KiB), and a single pure argument at most 16,384 bytes (16 KiB). A programmable transaction block can hold up to 1,024 commands and 2,048 input objects. These are protocol constants: validators enforce them, they're listed in sui-protocol-config, and they change only through protocol upgrades. The values below were read from mainnet at protocol version 139 (epoch 1291, 25 October 2026).
Object and storage limits
| Limit | Mainnet value | Config key |
|---|---|---|
| Max Move object size | 256,000 bytes | max_move_object_size |
| Max total bytes written per transaction | 5,000,000 bytes | max_size_written_objects |
| Max package size | 102,400 bytes | max_move_package_size |
| Max modules per publish | 64 | max_modules_in_publish |
| Max package dependencies | 32 | max_package_dependencies |
| Max vector length | 262,144 elements | max_move_vector_len |
If you need more than 256 KB of state, split it across several objects. The usual pattern is a small parent object with dynamic fields or a Table/Bag, so each entry is its own object and only the entries you touch get loaded. For large files, store the blob off-chain (for example on Walrus) and keep only a reference on-chain.
Transaction limits
| Limit | Mainnet value | Config key |
|---|---|---|
| Max transaction size | 131,072 bytes | max_tx_size_bytes |
| Max single pure argument | 16,384 bytes | max_pure_argument_size |
| Max PTB commands | 1,024 | max_programmable_tx_commands |
| Max input objects | 2,048 | max_input_objects |
| Max arguments per Move call | 512 | max_arguments |
| Max type arguments | 16 | max_type_arguments |
| Max gas payment coins | 256 | max_gas_payment_objects |
The 16 KiB pure-argument limit is the one people hit most often. A vector<address> with more than about 500 entries won't fit in one argument. Pass it in chunks and join them with vector::append inside Move, or build it across several commands.
Per-transaction execution limits
| Limit | Mainnet value | Config key |
|---|---|---|
| New object IDs created | 2,048 | max_num_new_move_object_ids |
| Object IDs deleted | 2,048 | max_num_deleted_move_object_ids |
| Objects transferred | 2,048 | max_num_transferred_move_object_ids |
| Objects loaded at runtime (incl. dynamic fields) | 1,000 | object_runtime_max_num_cached_objects |
| Events emitted | 1,024 | max_num_event_emit |
| Max size of one event | 256,000 bytes | max_event_emit_size |
| Max computation units | 5,000,000 | max_gas_computation_bucket |
The 1,000-object runtime cap is why loops over dynamic fields need pagination. A function that reads every entry of a large table in one call will eventually abort.
Check the values yourself
Limits differ between networks and protocol versions, so check the network you're deploying to. The GraphQL service returns the live config:
curl -s https://graphql.mainnet.sui.io/graphql \
-H 'content-type: application/json' \
-d '{"query":"{ protocolConfigs { protocolVersion configs { key value } } }"}'From TypeScript (@mysten/sui v2):
import { SuiGrpcClient } from '@mysten/sui/grpc'
const client = new SuiGrpcClient({
network: 'mainnet',
baseUrl: 'https://fullnode.mainnet.sui.io:443',
})
const { protocolConfig } = await client.getProtocolConfig()
console.log(protocolConfig.attributes.max_move_object_size)Gotchas
- The Move Book rounds the object limit to "256KB". The exact protocol value is 256,000 bytes, not 262,144.
- Exceeding a limit either rejects the transaction before execution (size, inputs) or aborts it during execution (objects created, events). If it aborts, you still pay gas. See why did my transaction fail.
- When randomness is involved, an attacker can deliberately push a transaction into these limits. See on-chain randomness.
Sources
- sui-protocol-config/src/lib.rs, Sui source
- Building Against Limits, The Move Book
- What is a PTB?, Sui documentation