MVC: View → Controller → Model → View. The Controller mutates the Model; the View is expected to re-observe the Model itself. If that observe step is wired up late or skipped ("massive view controller"), the View shows stale data — a classic MVC missed update.
MVVM: View ⇄ ViewModel ⇄ Model via two-way data binding. Convenient, but if the View and the Model both push a change into the same ViewModel property in the same tick, the binding layer applies last-write-wins — one of the two updates is silently lost (a data-binding race).
MVI: Intent → Model(reducer) → State → View → (new Intent). Strictly unidirectional and single-source-of-truth, so classic races on shared mutable state can't happen — but a burst of Intents faster than the reducer can process still causes an intermediate State to be skipped (a lost frame, not a corruption).
MVC: View -> Controller -> Model -> View
MVVM: View <-> ViewModel <-> Model (binding both ways)
MVI: Intent -> Model -> State -> View -> Intent