Transaction memos were traditionally used for this purpose, and many services still rely on them. Muxed accounts are better in the long term, but they aren’t yet supported by all wallets, exchanges, and anchors, so you may want to support both memos and muxed accounts, at least for a while. This guide covers both approaches.
Pooled accounts
A pooled account allows a single Stellar account ID to be shared across many users. Generally, services that use pooled accounts track their customers in a separate, internal database and use the muxed accounts feature to map an incoming and outgoing payment to the corresponding internal customer. The benefits of using a pooled account are lower costs – no base reserves are needed for each account – and lower key complexity – you only need to manage one account keypair. However, with a single pooled account, it is now your responsibility to manage all individual customer balances and payments. You can no longer rely on the Stellar ledger to accumulate value, handle errors and atomicity, or manage transactions on an account-by-account basis.Muxed accounts
Muxed accounts are embedded into the protocol for convenience and standardization. They distinguish individual accounts that all exist under a single, traditional Stellar account. They combine the familiarGABC… address with a 64-bit integer ID.
Muxed accounts do not exist on the ledger, but their shared underlying GABC… account does.
Muxed accounts are defined in CAP-27, introduced in Protocol 13, and their string representation is described in SEP-23.
It is safe for all wallets to implement sending to muxed accounts.
If you wish to receive deposits to muxed accounts please keep in mind that they are not yet supported by all wallets and exchanges.
Address format
Muxed accounts have their own address format that starts with an M prefix. For example, from a traditional Stellar account address:GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ, we can create new muxed accounts with different IDs. The IDs are embedded into the address itself- when you parse the muxed account addresses, you get the G address from above plus another number.
MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAAAACJUQhas the ID 0, whileMA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUAAAAAAAAAABUTGI4has the ID 420.
GA7Q… address when used with one of the supported operations.
Supported operations
Not all operations can be used with muxed accounts. Here is what you can use them for:- The source account of any operation or transaction;
- The fee source of a fee-bump transaction;
- The destination of all three types of payments:
Payment,PathPaymentStrictSend, andPathPaymentStrictReceive;
- The destination of an AccountMerge; and
- The target of a
Clawbackoperation (i.e. the from field).
Examples
The following examples demonstrate how muxed accounts work in practice, showing the three main payment scenarios: standard account-to-account, muxed-to-unmuxed, and muxed-to-muxed payments. Note: The complete code implementation for all examples follows after this section. You can run individual examples using their respective functions or execute all three sequentially using the main function. Muxed accounts (M…) are a client-side abstraction that don’t actually exist on the Stellar ledger — only the underlying G account lives on-chain. This means operations like loading account data must always use the base G account, while payment operations can still provide either M or G address. The code diverges only slightly to handle this distinction between the logical muxed account and the actual account. Transaction Fees: All transactions incur a fee (typically 100 stroops or 0.0000100 XLM). Since the custodian account is the source of all transactions in these examples, fees are always debited from the custodian’s balance. You’ll see this reflected in the before/after balance comparisons, where the custodian account decreases by both the payment amount and the transaction fee.Example 1 - Basic Payment (G → G)
This example establishes baseline behavior with a standard payment between two regular Stellar accounts. Both accounts exist directly on the ledger, demonstrating traditional Stellar payment flow without muxed account abstractions. The custodian account balance decreases by 10 XLM plus transaction fees, while the outsider account increases by exactly 10 XLM.Example 2 - Muxed to Unmuxed Payment (M → G)
This demonstrates a payment from a muxed account (representing a custodial customer) to a regular Stellar account. The underlying custodian account executes the payment, but the transaction includes the muxed address to identify which customer initiated it. The transaction is signed with custodian keys since muxed accounts have no secret keys. The custodian account balance decreases by 10 XLM plus fees.Example 3 - Muxed to Muxed Payment (M → M)
When two muxed accounts share the same underlying account, payments between them are essentially the account sending to itself. The payment amount (+10 XLM and -10 XLM) cancels out, but transaction fees are still charged since the operation is recorded on the ledger. The account balance decreases only by the transaction fee. You may want to detect these transactions in your application to avoid unnecessary fees. Note that payments between muxed accounts with different underlying accounts would behave like normal G-to-G payments.Code Implementation
The following code demonstrates all three examples using Stellar RPC. You can run all examples sequentially withrunAllMuxedExamples() or execute individual examples using their respective functions.
Running the Examples
- All Examples:
runAllMuxedExamples()- Runs setup once and executes all three examples - Individual Examples:
runUnmuxedExample()- Basic G→G paymentrunMuxedToUnmuxedExample()- Muxed→Unmuxed paymentrunMuxedToMuxedExample()- Muxed→Muxed payment
preamble() first to set up and fund the accounts.
More Examples
As is the case for most protocol-level features, you can find more usage examples and inspiration in the relevant test suite for your favorite SDK. For example, here are some of the JavaScript test cases.FAQs
What happens if I pay a muxed address, but the recipient doesn’t support them? In general, you should not send payments to muxed addresses on platforms that do not support them. These platforms will not be able to provide muxed destination addresses in the first place. Even still, if this does occur, parsing a transaction with a muxed parameter without handling them will lead to one of two things occurring:- If your SDK is out-of-date, parsing will error out. You should upgrade your SDK. For example, the JavaScript SDK will throw a helpful message:
- If your SDK is up-to-date, you will see the muxed (
M...) address parsed out. What happens next depends on your application.
trustor failed to parse as a Stellar account ID (G...). In other words, your code will fail and the invalid operation will never reach the network.
How do I validate Stellar addresses?
You should use the validation methods provided by your SDK or carefully adhere to SEP-23. For example, the JavaScript SDK provides the following methods for validating Stellar addresses:
Memo - differentiated accounts
Prior to the introduction of muxed accounts, products and services that relied on pooled accounts often used transaction memos to differentiate between users. Supporting muxed accounts is better in the long term, but for now you may want to support both memos and muxed accounts as all exchanges, anchors, and wallets may not support muxed accounts. To learn about what other purposes memos can be used for, see our Memos section.Why are muxed accounts better in the long term?
Muxed accounts are a better approach to differentiating between individuals in a pooled account because they have better:- Shareability — rather than worrying about error-prone things like copy-pasting memo IDs, you can just share your M… address.
- SDK support — the various SDKs support this abstraction natively, letting you create, manage, and work with muxed accounts easily. This means that you may see muxed addresses appear when parsing any of the fields that support them, so you should be ready to handle them. Refer to your SDK’s documentation for details; for example, v7.0.0 of the JavaScript SDK library stellar-base describes all of the fields and functions that relate to muxed accounts.
- Efficiency — by combining related virtual accounts under a single account’s umbrella, you can avoid holding reserves and paying fees for all of them to exist in the ledger individually. You can also combine multiple payments to multiple destinations within a single transaction since you do not need the per-transaction memo field anymore.