Java and C++ have invested tremendous amounts of effort into preserving backwards compatibility for decades, often requiring bending over backwards and very suboptimal designs for new features, especially in C++.
But it keeps users happy. At least the ones with large old code bases.
I think Rust has one of the cleanest models for this, which keeps complexity low: editions.
The compiler will always support old code written against older editions, but the language can still introduce breaking changes in newer editions. Developers can either opt in to new editions and migrate their code, or do nothing, and things continue to work fine. There is seamless/transparent interoperability.
Of course Rust is still pretty young, and if this model will work long term remains to be seen. For example, I imagine this causes a lot of implementation complexity in the compiler, the standard library is much more restricted and must remain stable across editions, and major overhauls probably won't be possible.
But so far it has worked out really well, allowing the team to fix warts and mistakes in the language.