Framework
revoframework/Revo avatar
revoframework/Revo

Revo: an opinionated event sourcing, CQRS and DDD framework for .NET

Event Sourcing, CQRS and DDD framework for C#/.NET Core.

715 stars81 forksC#MIT

At a glance

What is it?
Revo is a C#/.NET application framework that combines event sourcing, CQRS and domain-driven design into one opinionated stack, with event store backends on PostgreSQL, SQL Server and SQLite, projections, sagas and outbox support. It suits teams that have already decided to model with events, and it is a poor fit for a team that wants to pick and choose each pattern separately.
Who is it for?
Revo fits a .NET team that has committed to event sourcing and wants the surrounding infrastructure, projections, sagas, authorization, multi-tenancy and testing support supplied by one framework rather than assembled. It does not fit a team that wants CQRS without event sourcing, or one that needs its own messaging and persistence choices.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three patterns welded together, with opinions you inherit

Revo is an application framework for modern server C#/.NET applications built with event sourcing, CQRS and DDD, and the readme is unusually direct about the consequence. The project combines those three concepts and takes some rather opinionated approaches on the design of certain parts of its architecture.

That word, opinionated, is the whole evaluation in one place. A framework that offers event sourcing as one option among many is easy to adopt and easy to ignore. A framework that assumes you want event-sourced persistence, that separates commands from queries at the handler level, and that expects your domain model to be built from aggregates, entities, value objects and domain events is not optional in the same way. You can use it, but you use it as designed or you fight it.

The stated motivation is a set of properties: applications that are scalable, maintainable, can work in distributed environments and are easy to integrate with the outside world. The features list adds the infrastructure a complete application tends to need anyway: authorizations, validations, messaging, integrations, multi-tenancy and testing. And the extensions layer adds entity history change-tracking, auditing and user notifications.

The audience is a .NET team on the server side. The topics list Entity Framework alongside event sourcing and the outbox pattern, and the documentation site at docs.revoframework.net is the reference. The repository is MIT licensed, not archived, and the last push was on 2026-10-15, with the newest release Revo-1.38.4 from 2026-09-25.

The DDD building blocks, and where the framework draws its lines

The domain-driven design section is the shortest and tells you what the framework considers non-negotiable. The building blocks listed are aggregates, entities, value objects, domain events and repositories, and each one is a first-class concept with its own reference page rather than a convention you follow yourself.

The way the other layers are described is what reveals the framework's shape.

Event sourcing is described as event-sourced entity persistence with support for multiple event store backends, listed as PostgreSQL, MSSQL and SQLite. The event processing section covers both synchronous and asynchronous processing, and it states three properties explicitly: guaranteed at-least-once delivery, event queues with strict sequence ordering as an option, and event source catch-ups.

At-least-once delivery with optional strict ordering is the honest description of a real event store. It means every consumer has to be idempotent, and it means the ordering guarantee is something you opt into per queue rather than something the system gives you by default. The readme also mentions optional pseudo-synchronous event dispatch for listeners such as projectors, which is the mechanism for making a projection update look synchronous to the caller when the application needs it.

CQRS is described as segregating command and query responsibilities with commands and queries, command and query handlers, a processing pipeline with filters for cross-cutting concerns such as authorization and validation, and different read and write models.

Projections and data access: Entity Framework and RavenDB side by side

The read side of CQRS is where a framework either helps or gets in the way, and Revo's approach is to keep the read model a database query rather than a separate store.

Data access is described as a thin abstraction layer for easy data persistence, for example querying read models, using Entity Framework Core, Entity Framework 6, RavenDB, a testable in-memory database or other data providers, and it includes support for simple database migrations.

Projections then work against those same backends, with the list given as Entity Framework Core on PostgreSQL, MSSQL and SQLite, Entity Framework 6 and RavenDB, and the framework handling idempotency and concurrency automatically.

That is a design choice with a clear logic. A projection is a database table, or a RavenDB document, that the framework keeps in step with the event stream, and the framework guarantees the update is idempotent and safe under concurrency. You do not have to write a consumer that deduplicates.

The alternative approach, and the one Revo is arguing against without saying so, is a separate read store fed by a message broker, with a projection consumer that has to be written, deployed, monitored and made idempotent by hand. Revo's version keeps the read model in the database you already run, which is simpler to operate and less consistent with the event store.

The in-memory database in the data access list is the detail that shows this is aimed at test suites, because a testable in-memory provider is what lets a test exercise a whole command-to-projection path without a database.

Sagas, messaging and the outbox pattern

Long-running processes are handled with sagas, described as coordinating long-running processes or inter-aggregate cooperation with sagas that react to events, a.k.a. process managers.

That is the standard event-sourcing answer to the problem, and it carries the standard trade-off: a saga is a state machine that advances by reacting to events, so its steps are asynchronous and its failure handling is retry-driven rather than transactional. A workflow that must be exactly-once across aggregates is not what this mechanism gives you.

For integration, the framework is described as SOA, messaging and integration, with the ability to scale and integrate by publishing and receiving events, commands and queries using common messaging patterns, for example a RabbitMQ message queue using the EasyNetQ connector or the Rebus service bus. The topics list outbox and outbox-pattern, and the package list includes both integrations.

The outbox pattern here is the piece that connects event sourcing to the broker. A projection is written to the database in the same transaction as the event store write, and a separate process publishes the event afterwards, so a crash between the two does not lose the event. It is more machinery than a plain publish-after-commit, and it is the price of the guarantee that a committed event eventually reaches a consumer.

The supporting layer: authorization, validations, multi-tenancy and testing

The framework is explicit that it includes the cross-cutting concerns that a server application tends to need, and the readme lists them rather than leaving them to be discovered later.

Authorization is basic permission and role-based ACL for commands and queries, with fine-grained row filtering. The interesting part is where the ACL attaches: to commands and queries, through the processing pipeline, not to the domain objects themselves. Validation works the same way, as a pipeline filter. The consequence is that a domain method invoked outside the pipeline bypasses both, which is a real trade-off for a framework that pushes you towards thin domain models with the interesting behaviour in the pipeline.

There is also a filter-based processing pipeline generally, which is the extension point that the authorization, validation and presumably other cross-cutting filters plug into.

The readme also mentions integrations, multi-tenancy and testing as first-class features, and the repository has a Revo.Testing project and a Tests directory, plus an Examples/Todos directory that gives a worked example rather than only documentation. The presence of a Todos example is a good sign, because a CQRS framework without a small end-to-end example is hard to evaluate, and the documented Super-short example in the readme serves the same purpose.

Packages, builds and where the documentation actually lives

The repository is a multi-project Visual Studio solution, Revo.sln, with the code split into Revo.Core, Revo.Domain, Revo.Infrastructure, Revo.DataAccess and Revo.Testing, plus Providers/ for the persistence backends, Extensions/ for the optional features such as auditing and change tracking, Examples/ for the Todos sample, and Tools/ for build and release scripts.

That layering is the dependency story in one view. Revo.Domain holds the DDD building blocks, Revo.Core holds the framework machinery, Revo.DataAccess holds the persistence abstraction, and Revo.Infrastructure holds the pieces that talk to the outside world. A project that wants to reference only parts of it can, which matters for a framework that otherwise pulls in a lot.

The build is Cake based, with build.cake, build.config, build.ps1, build.sh and cake.config, driven by azure-pipelines.yml, and coverage is tracked through codecov with a coverlet.runsettings file. The NuGet packages are published to nuget.org and to a CI feed on Azure DevOps, and the badge points at the Revo.Core package specifically, which is a hint about which package a new project starts from.

The documentation is split in two, and that split is worth knowing before you start. There is a GitBook at revoframework.gitbook.io/revo with the reference guide, which is where the feature links in the readme point, and a separate site at docs.revoframework.net that the readme links as the full documentation. The readme's own Getting started section is where the installation steps live, and for the version details the releases on GitHub and the RELEASE_NOTES.md file in the repository root are the places to look for what changed between 1.38.2 and 1.38.4.

Who should use this, and what to check before you commit

Revo is a framework for teams who have already chosen event sourcing, not for teams exploring it. The reason is the coupling. Once your aggregates are event-sourced, your write model is an event stream, your read models are projections maintained by the framework, and your cross-aggregate workflows are sagas, and all three of those are Revo's design rather than yours. Adopting Revo is not adding a persistence library, it is accepting a specific answer to how the application is structured.

For a team that wants the opposite, a thin persistence abstraction over Entity Framework with occasional domain events would be less machinery, and there are many ways to build that without an event store at all. The trade Revo offers is that the hard infrastructure, projections, sagas, the outbox, authorization filters, validation filters, multi-tenancy and testing helpers, comes supplied and consistent.

The specific things to verify before committing are the ones the readme does not answer. Which persistence providers in Providers/ are actively supported, since the list in the readme includes both Entity Framework Core and Entity Framework 6, and the older one is a compatibility artefact rather than a choice. Which event store backends are production-ready among PostgreSQL, MSSQL and SQLite. And which messaging transport you will use, since RabbitMQ via EasyNetQ and Rebus are alternatives with different operational profiles.

One maintenance fact to hold onto: this is a project with a sponsor behind it, since development is supported by OLIFY, and a named release cadence rather than a hobby pace, with 1.38.1 in January, 1.38.2 in May and 1.38.4 in September 2026, and a last push on 2026-10-15. The default branch is develop, so the branch you track for day-to-day work is the same one the releases are cut from.

Editorial conclusion

Revo fits a .NET team that has committed to event sourcing and wants the surrounding infrastructure, projections, sagas, authorization, multi-tenancy and testing support supplied by one framework rather than assembled. It does not fit a team that wants CQRS without event sourcing, or one that needs its own messaging and persistence choices. Before adopting it, read the GitBook reference for the parts the readme only summarises, confirm the Revo.Core package version on NuGet matches the release you plan to pin, and check the persistence providers in Providers/ against the store you actually run.

Frequently asked questions

What is the Revo framework for .NET?

Revo is an application framework for modern server C#/.NET applications built with event sourcing, CQRS and DDD. It combines those three concepts and takes opinionated approaches on parts of its architecture, adding common infrastructure such as authorizations, validations, messaging, integrations, multi-tenancy and testing.

Which event store backends does Revo support?

The readme lists multiple event store backends, naming PostgreSQL, MSSQL and SQLite, and the same providers appear for read-model projections alongside Entity Framework 6 and RavenDB. The event processing layer supports synchronous and asynchronous processing with guaranteed at-least-once delivery, optional strict sequence ordering and event source catch-ups.

How do Revo projections work?

Read-model projections are supported on several backends, and the framework handles idempotency and concurrency automatically. Data access is a thin abstraction over Entity Framework Core, Entity Framework 6, RavenDB or a testable in-memory database, so the read model stays in the database you already run rather than in a separate store.

What does Revo provide for long-running processes and integration?

Sagas, also called process managers, coordinate long-running processes and inter-aggregate cooperation by reacting to events. Integration is by publishing and receiving events, commands and queries with common messaging patterns, for example a RabbitMQ queue through the EasyNetQ connector or the Rebus service bus, and the topic list includes the outbox pattern.

Where is the Revo documentation and what licence does it use?

The readme links a GitBook reference guide at revoframework.gitbook.io/revo and a full documentation site at docs.revoframework.net, and the repository ships an Examples/Todos project and a Revo.Testing project. The licence is MIT, the newest release is Revo-1.38.4 from 2026-09-25, and the default branch is develop.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. revoframework/Revo on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/revoframework-revo.svg)](https://hysenlabs.com/projects/revoframework-revo)

Was this useful?