Mnesia is _not_ the storage layer for messages (except for delayed messages).
Mnesia stores vhosts, users, permissions, queue definitions and more. This is being transitioned to Khepri, which improves a lot of things (maybe most importantly netsplits) but not directly message speeds.
This will be huge. One of the biggest issues I had running an erlang system that moved lots of arbitrary sized, untrusted data through it in a parallel way was understanding what was going on in the process heaps and reference counted shared binary heap. Especially the shared heap since there's no way to set an upper bound on it, and when you exceed it the VM crashes.
erlang:process_info(Pid, binary) for all processes with some post processing was usually pretty helpful for me, although I don't think it tells you much about ets tables, which is where my big bloat usually was. If you store binaries in ets (or mnesia) and the binaries live for a long time, it's useful to run them through binary:copy/1 if the binary is a sub-binary that references a large binary that's otherwise garbage. Or at least this used to be useful; sometimes my experiencs get obsoleted when OTP updates have efficiency changes.