En primer lugar, mantenga los datos normalizados (no redundantes) tanto como pueda. Si los datos están completamente normalizados, ninguna actualización única de los datos puede hacer que sean inconsistentes.
No siempre puede mantener los datos normalizados, en otras palabras, es posible que no pueda eliminar la redundancia, en cuyo caso puede tener estados inconsistentes. Lo que hay que hacer es tolerar la inconsistencia y repararla periódicamente con algún tipo de programa que lo abarque y lo repare.
Existe una fuerte tendencia a tratar de gestionar la redundancia de manera estricta mediante notificaciones. No solo es difícil asegurarse de que sean correctos, sino que pueden conducir a enormes ineficiencias. (Parte de la tentación de escribir notificaciones surge porque en OOP prácticamente se les alienta).
En general, cualquier cosa que dependa de la secuencia temporal de eventos, mensajes, etc., será vulnerable y requerirá toneladas de codificación defensiva. Los eventos y mensajes son característicos de los datos con redundancia, ya que están comunicando cambios de una parte a otra, tratando de evitar inconsistencias.
Como dije, si debe tener redundancia (y es muy probable que deba hacerlo), lo mejor es poder a) tolerar y b) repararlo. Si intenta evitar inconsistencias únicamente mediante mensajes, notificaciones, disparadores, etc., le resultará muy difícil hacerlo robusto.