Eventstore projections or subscriptions

I want to create read models of the current state of aggregates from their event streams, for storing in different databases (eg graph and document).

I can do this in a couple of ways:

  • Use an Eventstore projection to store current state and subscribe to that projection in the client
  • Subscribe to individual events using the client API (or atom feeds) and run the projection in the client (I know there are various optimizations for this approach, eg bulk processing)
    Is one way better than the other? If not, what are the trade offs?

See this post for some guidelines.!topic/event-store/83ESaV0kcCA

This doesn’t address my question. I want to know what trade offs to consider when deciding whether to use a projection. Eg, does it hurt performance to run a current state projection for a stream of events from an aggregate on each event (snapshotting for each event)?

Yes it does and why would you want to snapshot like that? What happens if you change representation

Sorry, I’m a bit confused. That post is asking if you can do without a separate DB. I know I want a separate DB to do the querying, I’m just asking the best way to populate that DB with the read model from the event streams. As far as I can see, I can either:

  1. Use an Eventstore projection to create a full read model for every event, subscribe to that projection in the client, then simply overwrite the entry in the DB with each new event
  2. Subscribe to individual events using the client API, then with each new event, load the read model from the DB and apply a projection in the client

Ah, okay I get you now.

I choose #2. Seems to me that #1 would cost performance on the write side for read concerns in addition to being extra configuration (setting up all those projections). #1 might also have some concerns for replay-ability. You will have to delete a projection and re-create it force a replay. I can’t remember if it is currently possible to recreate a projection with the same name. (I believe this feature was added?) And you have more control over it with #2.

You will never get away with one database for everything, at least not if your application grows. If you need searching, filtering, sorting, lists, etc then you need a separate database(s) for that.

@kasey Or you can create a new projection with a new name. It’s just another stream :slight_smile:

Thanks, glad you understand me now :slight_smile:

This is along the lines of what I was thinking, and I have been building an F# library to help with #2 that builds the projections in the client with support for batching (when catching up). This led me to the question, because if the write cost is not too high and the re-creation of a projection is possible and also not too high, then #1 might be desirable. This is because we would never have to worry about historic events when creating new models or catching up existing ones, we could just read the last event on the “current state” projection, then project off that in the client.

This is the trade off I was considering. Hope that makes sense.

In his scenario if you do that, then you have to change your configuration to look for the new stream name.

Yes. In your application startup you can create the projection there. A lot like IndexCreation.CreateIndexes(myAssembly, documentStore)

Either way, you still have to write the code to fold the events into a model. #1, you will just be writing it in Javascript as a projection. Then you still have to have a listener to put the state from projections into the correct table/document group/whatever. There is probably a reduction in code since with #1 you aren’t having to write the mechanics for the projection. But there is added dependency/cfg.mgmt on ES projections for that.