Event Horizon

Learn about Event Horizon, Subscriptions, Consumers and Producers

At the heart of the Dolittle runtime sits the concept of Event Horizon. Event horizon is the mechanism for a microservice to give Consent for another microservice to Subscribe to its Public Stream and receive Public Events.

flowchart BT
    subgraph Producer
        ProdEventLog[(Event Log)] -->|Public events| PublicFilter[Public Filter]
        PublicFilter -->|matches go into| PublicStream[(Public Stream)]
        Consent(((Consent))) -->|gives access to| PublicStream
    subgraph Consumer
        direction LR
        Subscription -->|stores| ConEventLog[(Scoped Event Log)]
    Subscription -->|asks for events| Consent


The producer is a Tenant in a Microservice that has one or more public streams that Consumer can subscribe to. Only public events are eligible for being filtered into a public stream.

Once an event moves past the event horizon, the producer will no longer see it. The producer doesn’t know or care, what happens with an event after it has gone past the event horizon.

The producer has to give consent for a consumer to subscribe to a Partition in the producers public stream. Consents are defined in event-horizon-consents.json.


A consumer is a tenant that subscribes to a partition in one of the Producer’s public streams. The events coming from the producer will be stored into a Scoped Event Log in the consumer’s event store. This way even if the producer would get removed or deprecated, the produced events are still saved in the consumer. To process events from a scoped event log you need scoped event handlers & filters.

The consumer sets up the subscription and will keep asking the producer for events. The producers Runtime will check whether it has a consent for that specific subscription and will only allow events to flow if that consent exists. If the producer goes offline or doesn’t consent, the consumer will keep retrying.


A subscription is setup by the consumer to receive events from a producer. Additionally the consumer has to add the producer to its microservices.json.

This is a simplified structure of a Subscription in the consumer.

Subscription {
    // the producers microservice, tenant, public stream and partition
    MicroserviceId Guid
    TenantId Guid
    PublicStreamId Guid
    PartitionId string
    // the consumers scoped event log
    ScopeId Guid

Event migration

We’re working on a solution for event migration strategies using Generations. As of now there is no mechanism for dealing with generations, so they are best left alone. Extra caution should be paid to changing public events so as not to break other microservices consuming those events.