Tu arquitectura me parece correcta en principio. El patrón Observer es ideal para esto. El hecho de que el 90% sea WebSocket ahora no significa que no añadas más canales después (push móvil, Slack, etc.). La separación te da flexibilidad.
Lo que yo haría: en lugar de que cada Observer reciba el Event completo, crearía una interfaz más específica:
interface Notification {
userId: string;
type: 'comment' | 'assignment' | 'status_change';
payload: Record;
}Así los notificadores solo ven lo que necesitan. También considera usar un Router que decida, basado en reglas, qué notificadores deben ejecutarse para cada evento.