Dolittle is a decentralized, distributed, event-driven microservice platform built to harness the power of events. It’s a reliable ecosystem for microservices to thrive so that you can build complex applications with small, focused microservices that are loosely coupled, event driven and highly maintainable.
- Events are “facts that have happened” in your system and they form the truth of the system.
- Event Handlers & Filter and Projections process events.
- The Runtime is the core of all Dolittle applications and manages connections from the SDKs and other Runtimes to its Event Store. The Runtime is packaged as a Docker image
- The Event Store is the underlying database where the events are stored.
- The Head is the user code that uses the SDKs, which connect to the Runtime in the same way as a client (SDK) connects to a server (runtime).
- A Microservice is one or more Heads talking to a Runtime.
- Microservices can produce and consume events between each other over the Event Horizon.
Dolittle uses a style of Event-Driven Architecture called Event Sourcing, which means to “capture all changes to an applications state as a sequence of events”, these events then form the “truth” of the system. Events cannot be changed or deleted as they represent things that have happened.
With event sourcing your applications state is no longer stored as a snapshot of your current state but rather as a whole history of all state-changing events. These events can then be replayed to recreate the state whenever needed, eg. replay them to a test environment to see how it would behave. The system can also produce the state it had at any point in time.
Event sourcing allows for high scalability thanks to being a very loosely coupled system, eg. a stream of events can keep a set of in-memory databases updated instead of having to query a master database.
The history of events also forms an audit log to help with debugging and auditing.
Distributed & Decentralized
Dolittle applications are built from microservices that communicate with each other using events. These microservices can scale and fail independently as there is no centralized message bus like in Kafka. The Runtimes and event stores are independent of other parts of the system.
A microservice consists of one or many heads talking to one Runtime. Each microservice is autonomous and has its own resources and event store.
The core idea is that a microservice is an independently scalable unit of deployment that can be reused in other parts of the software however you like. You could compose it back in one application running inside a single process, or you could spread it across a cluster. It really is a deployment choice once the software is giving you this freedom.
This diagram shows the anatomy of a microservice with one head.
Read CacheThe Read Cache in these pictures is not part of Dolittle. Different projections call for different solutions depending on the sort of load and data to be stored.
Since computing is the most expensive resource, the Dolittle Runtime and SDK’s has been built from the ground up with multi-tenancy in mind. Multi-tenancy means that a single instance of the software and its supporting infrastructure serves multiple customers, making optimal use of resources. Dolittle supports multi-tenancy by separating the event stores for each tenant so that each tenant only has access to its own data.
This diagram shows a microservice with 2 tenants, each of them with their own resources.
What Dolittle isn’t
Dolittle is not a traditional backend library nor an event driven message bus like Kafka. Dolittle uses Event Sourcing, which means that the state of the system is built from an append-only Event Store that has all the events ever produced by the application.
Dolittle does not provide a solution for read models/cache. Different situations call for different databases depending on the sort of load and data to be stored. The event store only defines how the events are written in the system, it doesn’t define how things are read or interpreted.
Dolittle isn’t a CQRS framework, but it used to be.
- Runtime repository
- C# SDK repository
- The connection between the runtime and the SDKs is managed through gRPC calls, defined in our Contracts repository
The Event Store is implemented with MongoDB.