This question concerns the Signal protocol's X3DH key agreement protocol as documented here.
Obviously, if Alice and Bob have never contacted each other before, they need to run X3DH at least once to agree on a key.
However, it is unclear to me why X3DH needs to be run more than once between the same two users: now that they have agreed on a key, and given the Double Ratchet algorithm is used to generate new keys for each message to ensure perfect forward secrecy, why would they ever need to run X3DH again?
Without the need to run a key agreement protocol a second time between the same two users, a simple DH between Alice and Bob's identity keys should suffice, and perfect forward secrecy is not an issue since the protocol would never be run again. Only if the protocol needs to be run more than once would X3DH be called for, to restore perfect forward secrecy.
I imagine this is due to an implementation decision of not committing any keys beyond the bare minimum (private keys for the identity key, signed prekey and one-time prekeys) to non-volatile storage, so that when the app is restarted, the protocol would need to be run again. Can anyone confirm?