diff --git a/lbry/extras/daemon/daemon.py b/lbry/extras/daemon/daemon.py
index dbf9ae20d..819f83c0d 100644
--- a/lbry/extras/daemon/daemon.py
+++ b/lbry/extras/daemon/daemon.py
@@ -4461,7 +4461,7 @@ class Daemon(metaclass=JSONRPCServerType):
 
     @requires(WALLET_COMPONENT)
     async def jsonrpc_txo_spend(
-            self, account_id=None, wallet_id=None, batch_size=500,
+            self, account_id=None, wallet_id=None, batch_size=100,
             include_full_tx=False, preview=False, blocking=False, **kwargs):
         """
         Spend transaction outputs, batching into multiple transactions as necessary.
@@ -4500,7 +4500,10 @@ class Daemon(metaclass=JSONRPCServerType):
         accounts = [wallet.get_account_or_error(account_id)] if account_id else wallet.accounts
         txos = await self.ledger.get_txos(
             wallet=wallet, accounts=accounts, read_only=True,
-            **self._constrain_txo_from_kwargs({}, is_not_spent=True, is_my_output=True, **kwargs)
+            no_tx=True, no_channel_info=True,
+            **self._constrain_txo_from_kwargs(
+                {}, is_not_spent=True, is_my_output=True, **kwargs
+            )
         )
         txs = []
         while txos:
diff --git a/lbry/wallet/database.py b/lbry/wallet/database.py
index d980bb72d..7ca342421 100644
--- a/lbry/wallet/database.py
+++ b/lbry/wallet/database.py
@@ -965,16 +965,18 @@ class Database(SQLiteMixin):
             sql.append("LEFT JOIN txi ON (txi.position=0 AND txi.txid=txo.txid)")
         return await self.db.execute_fetchall(*query(' '.join(sql), **constraints), read_only=read_only)
 
-    async def get_txos(self, wallet=None, no_tx=False, read_only=False, **constraints):
+    async def get_txos(self, wallet=None, no_tx=False, no_channel_info=False, read_only=False, **constraints):
         include_is_spent = constraints.get('include_is_spent', False)
         include_is_my_input = constraints.get('include_is_my_input', False)
         include_is_my_output = constraints.pop('include_is_my_output', False)
         include_received_tips = constraints.pop('include_received_tips', False)
 
         select_columns = [
-            "tx.txid, raw, tx.height, tx.position as tx_position, tx.is_verified, "
+            "tx.txid, tx.height, tx.position as tx_position, tx.is_verified, "
             "txo_type, txo.position as txo_position, amount, script"
         ]
+        if not no_tx:
+            select_columns.append("raw")
 
         my_accounts = {a.public_key.address for a in wallet.accounts} if wallet else set()
         my_accounts_sql = ""
@@ -1052,32 +1054,33 @@ class Database(SQLiteMixin):
                 txo.received_tips = row['received_tips']
             txos.append(txo)
 
-        channel_ids = set()
-        for txo in txos:
-            if txo.is_claim and txo.can_decode_claim:
-                if txo.claim.is_signed:
-                    channel_ids.add(txo.claim.signing_channel_id)
-                if txo.claim.is_channel and wallet:
-                    for account in wallet.accounts:
-                        private_key = await account.get_channel_private_key(
-                            txo.claim.channel.public_key_bytes
-                        )
-                        if private_key:
-                            txo.private_key = private_key
-                            break
-
-        if channel_ids:
-            channels = {
-                txo.claim_id: txo for txo in
-                (await self.get_channels(
-                    wallet=wallet,
-                    claim_id__in=channel_ids,
-                    read_only=read_only
-                ))
-            }
+        if not no_channel_info:
+            channel_ids = set()
             for txo in txos:
                 if txo.is_claim and txo.can_decode_claim:
-                    txo.channel = channels.get(txo.claim.signing_channel_id, None)
+                    if txo.claim.is_signed:
+                        channel_ids.add(txo.claim.signing_channel_id)
+                    if txo.claim.is_channel and wallet:
+                        for account in wallet.accounts:
+                            private_key = await account.get_channel_private_key(
+                                txo.claim.channel.public_key_bytes
+                            )
+                            if private_key:
+                                txo.private_key = private_key
+                                break
+
+            if channel_ids:
+                channels = {
+                    txo.claim_id: txo for txo in
+                    (await self.get_channels(
+                        wallet=wallet,
+                        claim_id__in=channel_ids,
+                        read_only=read_only
+                    ))
+                }
+                for txo in txos:
+                    if txo.is_claim and txo.can_decode_claim:
+                        txo.channel = channels.get(txo.claim.signing_channel_id, None)
 
         return txos
 
diff --git a/lbry/wallet/ledger.py b/lbry/wallet/ledger.py
index c68ad3407..cd1a78d4e 100644
--- a/lbry/wallet/ledger.py
+++ b/lbry/wallet/ledger.py
@@ -231,7 +231,7 @@ class Ledger(metaclass=LedgerRegistry):
     async def get_effective_amount_estimators(self, funding_accounts: Iterable[Account]):
         estimators = []
         for account in funding_accounts:
-            utxos = await account.get_utxos()
+            utxos = await account.get_utxos(no_tx=True, no_channel_info=True)
             for utxo in utxos:
                 estimators.append(utxo.get_estimator(self))
         return estimators
diff --git a/lbry/wallet/transaction.py b/lbry/wallet/transaction.py
index d5a60c354..c05d7bc12 100644
--- a/lbry/wallet/transaction.py
+++ b/lbry/wallet/transaction.py
@@ -539,6 +539,7 @@ class Transaction:
                  height: int = -2, position: int = -1, julian_day: int = None) -> None:
         self._raw = raw
         self._raw_sans_segwit = None
+        self._raw_outputs = None
         self.is_segwit_flag = 0
         self.witnesses: List[bytes] = []
         self.ref = TXRefMutable(self)
@@ -600,6 +601,7 @@ class Transaction:
     def _reset(self):
         self._raw = None
         self._raw_sans_segwit = None
+        self._raw_outputs = None
         self.ref.reset()
 
     @property
@@ -693,9 +695,7 @@ class Transaction:
             stream.write_compact_size(len(self._inputs))
             for txin in self._inputs:
                 txin.serialize_to(stream)
-        stream.write_compact_size(len(self._outputs))
-        for txout in self._outputs:
-            txout.serialize_to(stream)
+        self._serialize_outputs(stream)
         stream.write_uint32(self.locktime)
         return stream.get_bytes()
 
@@ -709,13 +709,19 @@ class Transaction:
                 txin.serialize_to(stream, txin.txo_ref.txo.script.source)
             else:
                 txin.serialize_to(stream, b'')
-        stream.write_compact_size(len(self._outputs))
-        for txout in self._outputs:
-            txout.serialize_to(stream)
+        self._serialize_outputs(stream)
         stream.write_uint32(self.locktime)
         stream.write_uint32(self.signature_hash_type(1))  # signature hash type: SIGHASH_ALL
         return stream.get_bytes()
 
+    def _serialize_outputs(self, stream):
+        if self._raw_outputs is None:
+            self._raw_outputs = BCDataStream()
+            self._raw_outputs.write_compact_size(len(self._outputs))
+            for txout in self._outputs:
+                txout.serialize_to(self._raw_outputs)
+        stream.write(self._raw_outputs.get_bytes())
+
     def _deserialize(self):
         if self._raw is not None:
             stream = BCDataStream(self._raw)