I've run across Marten a number of times over the last couple of years, usually when I was looking for platforms to implement Event Sourcing. Unfortunately, the fact that Marten requires PostgreSQL has made it a non-starter at the organizations I've been at since it would introduce an entirely new database platform that is similar to the already established MS SQL server or Oracle.
Recently, I was looking into options for both Event Sourcing as well as a document store. When I came across Marten this time I realized that I have AWS Aurora available and it supports PostgreSQL API. This triggered a deep dive into Marten and I spent some time exploring the details of how Marten works and what benefits it brings. What I found was impressive and motivated me to include it in my latest passion project.
Why not Mongo?
You may be asking, why not just use MongoDb. Well, I've looked at MongoDb a number of times over the years and I'm just not that impressed. It seems to work well for a small POC or demonstration project, but running it in a secure, resilient and performant implementation is not trivial and likely more expensive than more robust alternatives. Using MongoDb for a small non-critical application in a single node community edition configuration might be fine, but for business critical usage non-functional requirements like encryption at rest, support and protections against data loss are very important and should not be ignored.
What I learned early in my Marten journey is that it was founded by Jeremy Miller. Prior to starting Marten, Jeremy Miller was the author of StructureMap, the original IoC/DI container for .NET, among other open source projects. According to Jeremy Miller, Marten was originally created as a replacement to RavenDb. Since that time Marten has been expanded to include Event Sourcing and multi-tenancy capabilities.
The big difference between Marten and other document databases is that it leverages PostgreSQL as the data store. PostgreSQL has unique support for JSON documents with JSONB data type columns. The JSONB datatype allows for efficient queries and indexes of JSON documents stored in JSONB columns.
Documents in the Database
Using a relational database to store JSON or XML documents is something that I personally have a mixed history with. I've used this technique over the years for some scenarios and the part that always burned me was queries of the data within the document and making patches to the documents. Queries of data within the documents is often slow and complex to implement. Patches to the documents require complex and slow DML.
My past experience initially made me skeptical of the Marten approach of using a relational database for the data store, however once I performed some experiments I was won over. The combination of Marten functionality and the JSONB capabilities in PostgreSQL effectively mitigate all of the downsides I've run into when using a relational database for storing documents.
Marten on PostgreSQL Advantages
Using PostgreSQL provide Marten some distinct and unique advantages that are not present in document stores like MongoDb and RavenDb.
The first advantage is that PostgreSQL is battle tested and widely proven. The creators of Marten did not need to figure out how to solve the complex problems associated with creating a database platform from scratch. This allowed the creators to focus on higher level problems that make Marten unique.
The second advantage is that because PostgreSQL is a relational database you get familiar consistency models and foreign keys between documents for referential integrity. Most document databases leverage eventual consistency for scale out scenarios and foreign keys and joins are extremely inefficient if they are available at all.
In addition, there are some use cases that are much better served with relational tables over document stores. In these scenarios you can combine a micro-ORM like Dapper with Marten to keep all of the relational and document data in the same database. This eliminates the need for distributed transactions and reduces the infrastructure footprint required.
Having multi-tenancy and Event Sourcing built into a document database is unique. Both of these patterns are not trivial to implement and having them as part of a single platform is a powerful combination.
For anyone building a SaaS solution, you know that segmenting the data in a secure way and is something that requires a lot of thought. Remembering to include tenant keys in every query or DML statement is burdensome which makes it easy to inadvertently omit. Marten makes including the tenant key for all database interactions (easy to abstract away so that you don't need to think about it as much and you don't forget)[https://martendb.io/documentation/documents/tenancy/basicoperations/]. In addition the default tenant data capabilities solve the age old issue of where to put data that applies across tenants.
When designing a schema for a NoSQL database, you need to think about how the data will be consumed and not just about how to efficiently store it. Command Query Segregation known as CQRS and Event Sourcing are complementary patterns that solve this problem. CQRS separates the commands associated with business activities from queries that consume data that results from the commands. Event Sourcing persists each command in an event stream and then emits events to project the data in a format that is designed to be queried.
While I don't think it is wise to apply Event Sourcing to all use cases, having it available and easy to leverage for appropriate use cases seems like a powerful option to have available.
My early exploration and subsequent experiences with building a solution that leverage Marten have been a largely positive experience. While Marten is not an ORM, it is like working with an ORM that is a real tool instead of something that is going to bite you when you least expect it.
If you need a document store or Event Sourcing for your implementation and you are using .NET, then I highly recommend you consider Marten.