What should I choose between these two options:

  1. utility.batch()

I can batch multiple calls into one call, so it avoids making too many calls, but I'm afraid this will exceed the size of the block if I put all of my 20 000 transactions, and I would end up with something unwanted. Or does batch() can dispatch the calls on multiple blocks ?

  1. the call

Or I could just signAndSend each transaction. It makes a lot of transaction, but I think it would be the best way as I'm (almost) sure everything will be sent across multiple blocks, but it will also be very long, and I'll need to make sure I don't have network/PC problem while the script is running

2 Answers 2


I can batch multiple calls into one call, so it avoid making too many calls, but i'm afraid this will exceed the size of the block if i put all of my 20 000 transactions, and i would end up with something unwanted... Or does batch() can dispatch the calls on multiple blocks ?

utility.batch() will be a single transaction and I guess with 20.000 inner transactions this will probably never be included in a block as it's too big.

  • Are the transactions in any kind related to each other? Meaning, if tx_A fails then tx_B should not be submitted?

I ran into this problem once, and for me, the biggest issue was that the "default" transaction-pool-size is rather small. So transactions were being dropped as I tried submitting them. My rather amateurish solution was to simply restrict the number of concurrent transactions.

Not sure, if this is still working but you can find the code that manages the dispatching here: https://github.com/centrifuge/centrifuge-cli/tree/main/packages/libs/dispatcher/src

  • i'll need every transaction to works, but they are destructive (setBalance), so if one doesnt work, i'll make them all again, and previous values will be erased. If i "spam" transaction, will they be queued until they can be processed ? or if there is too many, they will be ignored ?
    – Nathan
    Jun 29, 2022 at 8:33
  • At least from my experience, they were lost. But this might be due to how polkadod-js api is handling rejections from rpc calls. Are you the only one who is allowed to submit transactions during this time? Otherwise, one might move funds and get another setBalance plus. Jun 29, 2022 at 14:15
  • Anyone can, but they will be signed by the only sudo account. If it really gonna block, maybe i can manually push it on different blocks, but i hope this isn't the only solution...
    – Nathan
    Jun 29, 2022 at 14:18
  • I am probably too paranoid, but in this case I would set a Call-filter for the period the system might be in an inconsistent state (i.e. if one set balance fails and you are rerunning everything again). Jun 29, 2022 at 16:06
  • Actually it worked ! i dispatched ~40k transactions, they all queued until they could all pass !
    – Nathan
    Jul 1, 2022 at 16:45

Alternative 3: smaller batches.

Figure out how much you are able to fit in a utiliy.batch() call, it depends on the weights of the inner transactions. When I did something similar on my chain I was able to fit 20-50 transactions into one batch.

  1. Enable mortality, set lifetime to 16 blocks, so you know a batch which did not end up on chain does not suddenly come back alive.
  2. Pace the submissions to not exhaust the transaction pool. Submit three to four blocks worth of extrinsics at once, to be able to fill all the block's capacity
  3. wait until the first few batch extrinsics are completed, then submit a few more.

If some of the internal calls have dependencies it is possible put utility.batch(), utility.bactchAll() and utility.forceBatch() into each other to achieve failable atomic transaction without stopping the correct ones.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.