Можно посмотреть на архитектуру
CQRS + Event Sourcing. Вместо того, чтобы хранить состояние сущности, хранят произошедшие с ней события. Накатив эти события в порядке очереди на сущность всегда можно получить состояние сущности на любой момент времени.
Упрощается работа с записью данных в хранилище, но усложняется чтение. Поэтому обычно еще используют CQRS с двумя хранилищами, одно для записи где хранится последовательность событий, другое для чтения, где хранится текущее состояние сущностей. WriteModel отправляет в брокер сообщение о произошедшем событии, ReadModel ловит это сообщение и обновляет свое состояние в базе данных. ReadModel можно всегда пересобрать заново с нуля по имеющимся событиям. Можно использовать денормализацию данных и писать в базу так, чтобы читать нужные данные используя простейшие запросы.
Базы данных можно брать любые, хотя обычно для ReadModel используют стандартную реляционную или документоориентированную, а для WriteModel можно взять что-нибудь более специализированное, например
event store, просто потому что все фишки реляционных субд для этой части приложения не требуются.
Можно посмотреть примеры реализации event sourcing
https://github.com/prooph/event-sourcing