Persistence in Event Sourcing/CQRS


I’m new to Event Sourcing/CQRS/DDD/etc.
I’ve been reading about it for a few years now, I have tried Axon (where most of my knowledge comes from), and now I’m about to implement my first real-world system in Kafka so I have a few doubts:

  1. Do I really need DDD with Event Sourcing and CQRS? DDD seems really complex. I want the benefits of Event Sourcing and CQRS but in a more traditional system without Aggregates, Sagas, etc.

  2. Can I have a write state per command handler instead of centering all the commands on the same entity (like an aggregate) and just update this state using events from other commands? It seems that the command handlers could be decoupled from each other just like the queries. It wouldn’t have a huge impact on disk space, as the command handlers states just need to store the data needed for validation.

  3. Can I persist this command handler state on a database instead of using snapshots? It seems easier and faster. The concept of snapshots seems like a cheap excuse to not go too far from Event Sourcing. In practice, we already have a persisted state but still need to rebuild the rest of it from events. Why not go all the way and just save/load the state from a database at each command? The source of truth would still be the events and this state could be destroyed and rebuilt from the events, I could still have time-traveling, absolute logs, decoupling, and all the advantages of event-sourcing.

To better clarify, I made a quick drawing.

Each command/query handler would have its own event handlers and state.

The Command Handler would validate the commands against its state (persisted on a database) and if it passes the validations, it would dispatch an event. This command state would be updated one time per event by its command Event Handlers when a relevant event happens.

The Query Handler would just pull the entities from its state and this state would be updated once per event by its query Event Handlers.

The main contrast I see here in relation to traditional Event Sourced systems are two:

  1. The commands use separate states.
  2. I don’t load a snapshot and rerun the events after it at every command, instead I listen to each event once per handler, update the handler persisted state and read it when a command happens.

What advantages of Event Sourcing / CQRS would I lose with this approach?