# 0001 — Event-driven CQRS **Status:** accepted **Date:** 2026-06-18 ## Context K-Frame has a natural write/read split: the write model is config (widgets, data sources, layout) mutated via web UI, the read model is runtime state (current widget data, active layout) pushed to display clients. We need a mechanism to bridge the two — when config changes, runtime behavior must update (restart polling loops, push new layout to clients). ## Decision Full event-driven CQRS. Commands mutate config and emit domain events. The read side projects current state from events and DataSource poll results. Events drive side effects: restarting poll loops, pushing updates to connected clients. ## Alternatives considered **Imperative approach** — commands mutate config, then application layer imperatively calls "restart poll loop" / "push to clients." Simpler, but tangles command handling with side-effect orchestration. Adding new reactions to config changes requires modifying command handlers. ## Consequences - Clean separation: command handlers only mutate config and emit events, never trigger side effects directly. - New reactions to config changes are just new event listeners — no command handler modification. - More moving parts than the imperative approach — event bus, event handlers, projections. - Events are in-memory only (no event store / event sourcing). This is CQRS, not ES.