Projections

Projections transform your events to queryable read models.

To make your stored sequence of events usable for your client, you typically define different projections/transformations. The projections are automatically maintained and updated in the background for you when the event is received by the projector.

Creating Projections

Your projection definition consists of a number of event handlers that are applied to your events in sequence, to modify the current state of a projection. Each event handler defines processing logic for a particular event type and includes a number of options for filtering/matching event data and producing different outputs. This is how you can easily create and adapt client-specific views based on your events.

Event handlers are defined in the handlers section of your projection definition. You can add any number of handlers to your projection definition, even though it’s likely that a few will suffice for most cases.

Feed-based

Projections are based on feeds, which is a separate process from the event store. When an event batch is stored (consistently) the feed for the corresponding aggregate type will pick up these new events and provide them to services in Serialized, such as the projector and reactor service. It is also possible for you to subscribe to a feed directly using the feeds API or on of our client libraries.

Built-in projectors

Serialized provides a built-in service that lets you create projections without writing handler code or managing the feed state yourself. The projections are defined declaratively using JSONPath and a collection of predefined helper functions that our platform provides.

Once the projection has processed an event the result will be stored and the projection is queryable using the API or one of our client libraries.

Custom projectors

If your projection logic is more involved, and the built-in projection language is too restraining, you can also implement your own projector functions using any programming language. The requirement is that the function is deployed on a server that is internet-accessible and Serialized is allowed to call the function over HTTPS.

For every event that is being processed, your function will receive the current state and the event to be processed and should return the new projection state. Below is some pseudo code to describe how this function looks.


function(currentState, event) {
  var newState = calculateProjectionState(currentState, event)
  return newState
}

Serialized will save the calculated state and make it queryable though the API so you still do not need a storage to implement custom projections. A common implementation method for custom projectors is to use AWS lambda or Google Cloud Functions, but any internet-accessible server works.

In order to secure the custom projector function, all requests to the function from Serialized are HMAC-signed and through HTTPS.

Eventual consistency

Since projections are based on feeds, they are eventually consistent to their source events. When building applications that both store events and read projections it is sometimes necessary to keep this in mind so that you do not confuse the user of your application by presenting information that is not yet up to date.
Strategies for handling eventual consistency in applications is a broad topic and the most important thing right now is to understand that is may take a few milliseconds before the stored events have had an effect on your projection that is configured to process that event type.

Custom projection IDs

By default, all Projections use the Aggregate ID from the feed they are created from as the ID of the Projection. If you want to query your data by referring to a different identifier from your events, it is possible to use a different field as the id for the generated projection.

For example, if you have stored a OrderPlaced event with both an orderId and a customerId where the orderId is also the aggregate id, you can create one projection to get orders by their id and another projection to get all placed order by customerId by using the customerId as the projection id field.

You can read more about custom projection ids in our documentation.

Aggregated projections

Aggregated projections are a special kind of projection that summarizes all events from the source feed into a single read model. This is useful is when you want to keep track of counts or statistics for a certain feed type where it does not make sense to base the ID of the resulting read model on the source event data since it should be aggregated.

Aggregated projections are queried by name which is provided by you when the projection definition is created.

More information

To read more about the details of feeds, see our API documentation.