Nine .NET 8 services and a gateway: inside the ASCLAB insurance PoC
Very simplified insurance sales system made in a microservices architecture using .NET Core
At a glance
- What is it?
- The ASCLAB dotnetcore-microservices-poc is a deliberately simplified insurance sales system split into .NET 8 services with Eureka discovery, an Ocelot gateway, RabbitMQ messaging and ElasticSearch read models. It is a teaching reference for CQRS, event driven reads and service discovery, not a production starter kit, and the README hands the explanation to a seven part blog series rather than documenting how to run it.
- Who is it for?
- Read this repository when you want a concrete .NET 8 example of CQRS with MediatR, event driven read models, Eureka discovery and the transactional outbox, and be prepared to supply the missing operational knowledge yourself. Do not adopt it as an application base: the README documents no run command, no compose file contents and no release, and the last push was on 2026-09-17.
- Can I use it commercially?
- Yes. Apache-2.0 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 36 days ago.
- What is it written in?
- Mainly CSS, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The business case is small on purpose, which is what makes it readable
The system sells insurance. An agent logs in, sees the products they are allowed to sell, picks one for a customer, fills in the product's parameters, creates an offer, gets a calculated price back, and then converts the offer into a policy and prints a PDF certificate. Offers and policies can be searched afterwards. There is also agent-to-agent chat and a sales dashboard built on ElasticSearch aggregations and ChartJS.
That is a small domain, and that is the point. Each service in the repository exists to demonstrate one architectural decision rather than one business capability, so you can read PolicyService and come away with something about CQRS without also wading through a claims workflow. The project calls itself a very simplified insurance sales system, and the repository name still carries the poc suffix.
The technologies named in the README are .NET 8, Entity Framework Core, MediatR, Marten, Eureka, Ocelot, JWT tokens, RestEase, RawRabbit, NHibernate, Polly, NEST, Dapper, DynamicExpresso and SignalR. That is a lot of moving parts for a demo, which is also the main criticism worth making.
Each service demonstrates exactly one thing
Reading the service list tells you the teaching agenda. PolicyService creates offers and converts them into policies, and it is where CQRS read and write isolation is demonstrated. Inside it you find both communication styles at once: a synchronous REST call to PricingService through an HTTP client for the price, and asynchronous event publishing over RabbitMQ for newly created policies. Persistence there goes through NHibernate, a relational ORM.
PricingService calculates the price from a tariff, and the tariff is a set of rules parsed with DynamicExpresso. The README states the price depends on the customer's answers to defined questions, which means the pricing logic is data, not code, and is evaluated at runtime.
PolicySearchService is the counterpart. It listens for events from RabbitMQ, converts the received DTOs into a read model, and indexes that model in ElasticSearch to provide advanced search. DashboardService does the same thing for money: it subscribes to policy sale events, indexes sales data, and uses the ElasticSearch aggregation framework for totals per product per period, sales per agent and a sales timeline. Two separate read models built from the same event stream is the clearest demonstration in the repository of why CQRS splits exist.
Three persistence approaches in one solution, and no arguing about which is right
The repository touches relational data three different ways. NHibernate serves PolicyService, Dapper serves PaymentService, and Entity Framework Core is listed among the technologies. Marten is also listed among the technologies. Each service is allowed to pick its own, and the README does not present a house rule.
For a production system that is a decision you would have to make deliberately, with migration and backup stories attached. For a reference implementation it is arguably the most useful thing in the tree, because it shows what each approach costs. Dapper in PaymentService comes with an explicit reason: it is listed alongside a scheduled process that imports payments from a CSV file, which is a batch job shaped workload rather than an aggregate-shaped one.
The trade-off is consistency of practice. A reader who copies from two services inherits two different data access styles, and nothing in the README tells you which one the author would choose for new work.
JWT at the Auth Service, Ocelot in front of everything
Authentication is a separate Auth Service issuing JWT tokens, and the token is then used to check user permissions and which products a user may sell. That last part matters for the domain: product visibility is tied to identity, so the token is not only an authentication artefact.
The Agent Portal API Gateway sits in front of the back office services and is built with Ocelot. The README gives its reasoning rather than just naming it: a gateway per client application, with the stated plan that a future Xamarin mobile app would need its own dedicated gateway. It also acts as a security barrier that does not pass unauthenticated requests to backend services, and the README mentions content aggregation from multiple services as the other common use.
Service discovery is Eureka, with an eureka-server/ directory in the repository root, so services register and look each other up rather than hard-coding addresses. Polly is in the list for resilience at call sites. The gateway design is the piece most worth stealing, and also the piece with the most operational cost, because routing configuration in Ocelot has to stay in step with every service rename.
RabbitMQ appears in three places: chat, policy events and the outbox
Messaging is not decorative here. ChatService uses SignalR for agent chat, which is a pull style connection to browsers rather than a broker. The Transactional Outbox pattern gets its own blog entry in the series, which tells you it is treated as a headline feature rather than an afterthought.
The outbox exists because PolicyService both writes to its own database and publishes events about new policies, and those two actions must not diverge. The pattern's job is to make the intent to publish part of the same transaction as the write, so a crash between the two does not lose the event that PolicySearchService and DashboardService depend on. The README does not walk through the implementation, so the blog part is where the detail lives.
Asynchronous communication is also how the read models stay current. There is no synchronous call from PolicyService to ElasticSearch; the search and dashboard services build their indexes from the event stream. That is a deliberate choice with a cost: an index is eventually consistent with the database, so a search can lag a write.
What the repository contains, and what it does not tell you
The solution file DotNetMicroservicesPoc.sln ties together AgentPortalApiGateway/, AuthService/, ChatService.Api/, ChatService/, DashboardService/, PaymentService/, PolicySearchService/, PolicyService/, PricingService/, ProductService/ and Web/, plus a BlazorWasmClient/ directory and per-service test projects including PricingService.IntegrationTest/. Each business service has a matching.Api project, which the README describes as the hosting layer.
The repository also has postgres/, scripts/, readme-images/ and.dockerignore, and the topic list includes docker and docker-compose, so containerised infrastructure is clearly part of the picture. The gap is the documentation. The README contains no build command, no run command, no compose file contents and no list of required service versions or ports, and the repository has no GitHub releases. It also does not document the initial database seeding or how the gateway routes are configured.
The README links a seven-part blog series about the architecture, starting with Part 1 The Plan and covering CQRS with MediatR, Eureka, Ocelot gateways, Marten, SignalR with RabbitMQ, and the transactional outbox. That is a deliberate choice by the authors, and it is also the practical objection: the code is not self-explanatory enough to run from the README alone.
Maintenance state, licensing and the cost of copying this tree
The default branch is master and the last push was on 2026-09-17, roughly a month before this article. There are no GitHub releases, and nothing in the repository tells you which NuGet package versions were current when the code was written.
That is the main upgrade cost..NET 8 projects accumulate dependency drift, and with a stack this wide, including RestEase, RawRabbit, NEST, Marten and two ORMs, a tree copied into a new environment requires additional setup and compatibility work. The.NET 8 target is itself the main thing to re-verify if you plan to build on it.
The license is Apache-2.0, which is permissive and includes an explicit patent grant. That covers copying the code into a commercial product. It does not settle the question of which architecture suits your problem, and the README's own framing, a PoC, is the signal to treat these services as illustrations rather than as a starting point you extend.
Editorial conclusion
Read this repository when you want a concrete .NET 8 example of CQRS with MediatR, event driven read models, Eureka discovery and the transactional outbox, and be prepared to supply the missing operational knowledge yourself. Do not adopt it as an application base: the README documents no run command, no compose file contents and no release, and the last push was on 2026-09-17. Before using any of it, read PolicyService and PaymentService for the write path, PricingService for how tariffs are parsed, and the blog parts linked in the README for the reasoning the code does not carry.
Frequently asked questions
How do I run the ASCLAB dotnetcore-microservices-poc?
The README does not give a build or run command. It points readers to a seven part blog series covering the plan, CQRS with MediatR, Eureka, Ocelot gateways, Marten, SignalR with RabbitMQ and the transactional outbox, and the repository root contains a DotNetMicroservicesPoc.sln solution plus postgres/ and scripts/ directories.
Which services are in the dotnetcore-microservices-poc?
The README describes an Agent Portal API Gateway, Auth Service, Chat Service, Payment Service, Policy Service, Policy Search Service, Pricing Service, Product Service, Document Service and Dashboard Service, each with a matching .Api project, plus a VueJS single page application in Web/.
How does the dotnetcore-microservices-poc implement search and dashboards?
PolicySearchService and DashboardService both consume RabbitMQ events, convert them into read models and index them in ElasticSearch. DashboardService then uses the ElasticSearch aggregation framework for totals per product per period, sales per agent and a sales timeline, rendered with ChartJS.
Why does dotnetcore-microservices-poc use both NHibernate, Dapper and Entity Framework Core?
The README notes different services use different persistence approaches, with NHibernate in PolicyService and Dapper in PaymentService, where a scheduled CSV payment import also runs. Entity Framework Core is listed among the technologies. The README does not state a house rule for choosing between them.
Official sources
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.
[](https://hysenlabs.com/projects/asc-lab-dotnetcore-microservices-poc)Was this useful?