Lessons Learned from Building a Multi-Tenant Saas Content Management System on Mongo with C#
The document introduces Kevin Wright and Jonathan Roeder, who both have experience with MongoDB. It then provides information about their company, which has been in business since 1999 and processes $2.8 billion annually on its ecommerce platform. It goes on to describe their multi-tenant CMS application built with .NET and MongoDB, including approaches taken for schema design, sharding implementation, and best practices.
In this document
Powered by AI
Introduction of presenters Kevin Wright and Jonathan Roeder, highlighting their experience and roles in the company.
Company founded in 1999, providing SaaS eCommerce services, with 40,000+ online stores and $2.8B processed in 2012. Fun aspects of company culture noted.
Discusses the need for a new multi-tenant service focused on efficient scaling and CMS functionality through a .NET REST service.
Initial MongoDB provisioning issues led to reinventing database management. Introduced sharding for better scalability.
Strategies for using .NET static types with MongoDB's dynamic schema. Discusses leveraging compile-time safety and serialization.
Advice on using static types, LINQ support complexities, update best practices, and data modeling considerations without traditional joins.
Emphasis on denormalization with pro and cons. Discusses how folder paths are managed within content documents to ease updates.
Focus on optimistic concurrency and issues like benign writes. Encouragement to engage and vote on solutions discussed.
Kevin Wright (The long-haired hippie one)
◦ Over 100 years of experience! (Just look at this
PowerPoint Template!)
◦ Worked on the Space Station!
◦ 2 years of Mongo experience
Jonathan Roeder (The short-haired hipster
one)
◦ 10 years of High Scale eCommerce / CMS / Search
◦ 1.5 years of Mongo experience
3.
Founded in 1999
SaaS eCommerce and related services
40,000+ Online stores
330+ Employees
$2.8B processed on our platform in 2012
WHY write one?
Theworld needed ONE MORE!?!
Critical focus on
Multi-Tenancy
Focus on Small footprint / Efficient scaling
8.
What it is:
.NET REST Service
Standard use case of enabling CMS users to
define Meta schemas (Content & Property
Types)
CRUD operations on Data that conforms to
the Meta schemas (Content)
Structures for organizing Content (Content
Lists and Folders)
9.
Initial approach programmatically provisioned
a Mongo Database for each Tenant.
Reinventing the wheel with database
management.
Suffering from two minute incremental boot
up time per Database was untenable (get it!).
New approach: Embrace Sharding as the
appropriate scale out approach
10.
Opt-in per Collection
Don’t do it to earn your Sharding merit badge
Read the documentation three times.
Implement four times. (a.k.a Prototype)
The Along Came Polly joke will never get old
11.
.NET static type system + MongoDB dynamic
schema is like mixing Simon and Garfunkel
…(it can be great if you don’t Garfunkel it up)
Driver allows for pure dynamic schema
interaction but is maturing to allow type safe
access via Lambdas and LINQ.
◦ Aggregation framework tbd [CSHARP-601]
Be as static as you can be.
◦ POCO types for each MongoDB Document schema
(Data Transfer Object, DTO pattern)
◦ Leverage compile-time safety. The newest driver
makes it easy with Generics and Lambdas
◦ Duck-typing and magic strings are for gooses!
Explore very rich serialization hooks and
levers
◦ (SetIgnoreIfNullConvention, BsonExtraElements,…)
17.
Now that you’ve created static types, leverage
them!
18.
LINQ support is great. Just know that:
◦ No projection [CSHARP-456]
◦ Hard to mix in dynamic schema elements (use Inject
extension method)
Fall back to
MongoDB.Driver.Builders.Query<T> or
QueryBuilder<T>
◦ Mix in dynamic schema elements via non-generic
version
If your data can’t be dirty, don’t denoramlize
Example: Store only the FolderId on Content
Document instead of materialized Folder path
◦ Pros: Updates are easy!
◦ Cons: Queries are hard!
◦ When wanting to find Content within child
Folders, must first query for all child Folders, then
OR those IDs using the ‘In’ operator
27.
MongoDB.org approaches for actually
retrieving the Folders :
http://docs.mongodb.org/manual/tutorial/m
odel-tree-structures/
28.
Optimistic Concurrency
Benign Writes
Benign Wrongs
Compensate
Be prepared to carefully think this through.
http://blog.mongodb.org/post/475279604/
on-distributed-consistency-part-1
http://docs.mongodb.org/manual/tutorial/p
erform-two-phase-commits/